Merge pull request #2096 from yogstation13/upstream-merge-39513

[MIRROR] Felinid/catpeople are now their own human subspecies
This commit is contained in:
1fbff5f83b23d39d38b1dfcb4cac8d9b
2018-08-08 23:11:07 +02:00
committed by GitHub
17 changed files with 239 additions and 190 deletions

View File

@@ -58,9 +58,7 @@
#define iszombie(A) (is_species(A, /datum/species/zombie)) #define iszombie(A) (is_species(A, /datum/species/zombie))
#define ismoth(A) (is_species(A, /datum/species/moth)) #define ismoth(A) (is_species(A, /datum/species/moth))
#define ishumanbasic(A) (is_species(A, /datum/species/human)) #define ishumanbasic(A) (is_species(A, /datum/species/human))
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
//why arent catpeople a subspecies
#define iscatperson(A) (ishumanbasic(A) && ( A.dna.features["ears"] == "Cat" || A.dna.features["tail_human"] == "Cat") )
//more carbon mobs //more carbon mobs
#define ismonkey(A) (istype(A, /mob/living/carbon/monkey)) #define ismonkey(A) (istype(A, /mob/living/carbon/monkey))

View File

@@ -367,7 +367,7 @@ SUBSYSTEM_DEF(job)
var/allowed_to_be_a_loser = !jobban_isbanned(player, SSjob.overflow_role) var/allowed_to_be_a_loser = !jobban_isbanned(player, SSjob.overflow_role)
if(QDELETED(player) || !allowed_to_be_a_loser) if(QDELETED(player) || !allowed_to_be_a_loser)
RejectPlayer(player) RejectPlayer(player)
else else
if(!AssignRole(player, SSjob.overflow_role)) if(!AssignRole(player, SSjob.overflow_role))
RejectPlayer(player) RejectPlayer(player)
else if(player.client.prefs.joblessrole == BERANDOMJOB) else if(player.client.prefs.joblessrole == BERANDOMJOB)

View File

@@ -215,17 +215,21 @@
stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human
/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1) /mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE)
if(mrace && has_dna()) if(mrace && has_dna())
dna.species.on_species_loss(src) var/datum/species/new_race
var/old_species = dna.species
if(ispath(mrace)) if(ispath(mrace))
dna.species = new mrace() new_race = new mrace
else if(istype(mrace))
new_race = mrace
else else
dna.species = mrace return
dna.species.on_species_gain(src, old_species) dna.species.on_species_loss(src, new_race, pref_load)
var/datum/species/old_species = dna.species
dna.species = new_race
dna.species.on_species_gain(src, old_species, pref_load)
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1) /mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE)
..() ..()
if(icon_update) if(icon_update)
update_body() update_body()

View File

@@ -84,8 +84,8 @@
if(ishuman(owner)) if(ishuman(owner))
var/mob/living/carbon/human/H = owner var/mob/living/carbon/human/H = owner
if(iscatperson(H)) if(iscatperson(H))
H.startTailWag() H.dna.species.start_wagging_tail(H)
addtimer(CALLBACK(H, /mob/living/carbon/human.proc/endTailWag), 30) addtimer(CALLBACK(H.dna.species, /datum/species.proc/stop_wagging_tail, H), 30)
description = "<span class='nicegreen'>They want to play on the table!</span>\n" description = "<span class='nicegreen'>They want to play on the table!</span>\n"
mood_change = 2 mood_change = 2

View File

@@ -609,7 +609,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/slapper/attack(mob/M, mob/living/carbon/human/user) /obj/item/slapper/attack(mob/M, mob/living/carbon/human/user)
if(ishuman(M)) if(ishuman(M))
var/mob/living/carbon/human/L = M var/mob/living/carbon/human/L = M
L.endTailWag() if(L && L.dna && L.dna.species)
L.dna.species.stop_wagging_tail(M)
if(user.a_intent != INTENT_HARM && ((user.zone_selected == BODY_ZONE_PRECISE_MOUTH) || (user.zone_selected == BODY_ZONE_PRECISE_EYES) || (user.zone_selected == BODY_ZONE_HEAD))) if(user.a_intent != INTENT_HARM && ((user.zone_selected == BODY_ZONE_PRECISE_MOUTH) || (user.zone_selected == BODY_ZONE_PRECISE_EYES) || (user.zone_selected == BODY_ZONE_HEAD)))
user.do_attack_animation(M) user.do_attack_animation(M)
playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1) playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1)

View File

@@ -48,12 +48,12 @@
/client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list) /client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list)
set category = "Special Verbs" set category = "Special Verbs"
set name = "Headset Message" set name = "Headset Message"
admin_headset_message(M) admin_headset_message(M)
/client/proc/admin_headset_message(mob/M in GLOB.mob_list, sender = null) /client/proc/admin_headset_message(mob/M in GLOB.mob_list, sender = null)
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
if(!check_rights(R_ADMIN)) if(!check_rights(R_ADMIN))
return return
@@ -1201,82 +1201,6 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
log_admin("[key_name(usr)] sent \"[input]\" as the Tip of the Round.") log_admin("[key_name(usr)] sent \"[input]\" as the Tip of the Round.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Tip") SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Tip")
/proc/mass_purrbation()
for(var/M in GLOB.mob_list)
if(ishumanbasic(M))
purrbation_apply(M)
CHECK_TICK
/proc/mass_remove_purrbation()
for(var/M in GLOB.mob_list)
if(ishumanbasic(M))
purrbation_remove(M)
CHECK_TICK
/proc/purrbation_toggle(mob/living/carbon/human/H, silent = FALSE)
if(!ishumanbasic(H))
return
if(!iscatperson(H))
purrbation_apply(H, silent)
. = TRUE
else
purrbation_remove(H, silent)
. = FALSE
/proc/purrbation_apply(mob/living/carbon/human/H, silent = FALSE)
if(!ishuman(H))
return
if(iscatperson(H))
return
var/obj/item/organ/ears/cat/ears = new
var/obj/item/organ/tail/cat/tail = new
ears.Insert(H, drop_if_replaced=FALSE)
tail.Insert(H, drop_if_replaced=FALSE)
if(!silent)
to_chat(H, "Something is nya~t right.")
playsound(get_turf(H), 'sound/effects/meow1.ogg', 50, 1, -1)
/proc/purrbation_remove(mob/living/carbon/human/H, silent = FALSE)
if(!ishuman(H))
return
if(!iscatperson(H))
return
var/obj/item/organ/ears/cat/ears = H.getorgan(/obj/item/organ/ears/cat)
var/obj/item/organ/tail/cat/tail = H.getorgan(/obj/item/organ/tail/cat)
if(ears)
var/obj/item/organ/ears/NE
if(H.dna.species && H.dna.species.mutantears)
// Roundstart cat ears override H.dna.species.mutantears, reset it here.
H.dna.species.mutantears = initial(H.dna.species.mutantears)
if(H.dna.species.mutantears)
NE = new H.dna.species.mutantears()
if(!NE)
// Go with default ears
NE = new /obj/item/organ/ears()
NE.Insert(H, drop_if_replaced = FALSE)
if(tail)
var/obj/item/organ/tail/NT
if(H.dna.species && H.dna.species.mutanttail)
// Roundstart cat tail overrides H.dna.species.mutanttail, reset it here.
H.dna.species.mutanttail = initial(H.dna.species.mutanttail)
if(H.dna.species.mutanttail)
NT = new H.dna.species.mutanttail()
if(NT)
NT.Insert(H, drop_if_replaced = FALSE)
else
tail.Remove(H)
if(!silent)
to_chat(H, "You are no longer a cat.")
/client/proc/modify_goals() /client/proc/modify_goals()
set category = "Debug" set category = "Debug"
set name = "Modify goals" set name = "Modify goals"

View File

@@ -125,7 +125,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
for(var/custom_name_id in GLOB.preferences_custom_names) for(var/custom_name_id in GLOB.preferences_custom_names)
custom_names[custom_name_id] = get_default_name(custom_name_id) custom_names[custom_name_id] = get_default_name(custom_name_id)
UI_style = GLOB.available_ui_styles[1] UI_style = GLOB.available_ui_styles[1]
if(istype(C)) if(istype(C))
if(!IsGuestKey(C.key)) if(!IsGuestKey(C.key))
@@ -405,34 +405,34 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>" dat += "</td>"
mutant_category = 0 mutant_category = 0
if("tail_human" in pref_species.default_features)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>Tail</h3>"
dat += "<a href='?_src_=prefs;preference=tail_human;task=input'>[features["tail_human"]]</a><BR>"
mutant_category++
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("ears" in pref_species.default_features)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>Ears</h3>"
dat += "<a href='?_src_=prefs;preference=ears;task=input'>[features["ears"]]</a><BR>"
mutant_category++
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if(CONFIG_GET(flag/join_with_mutant_humans)) if(CONFIG_GET(flag/join_with_mutant_humans))
if("tail_human" in pref_species.default_features)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>Tail</h3>"
dat += "<a href='?_src_=prefs;preference=tail_human;task=input'>[features["tail_human"]]</a><BR>"
mutant_category++
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("ears" in pref_species.default_features)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>Ears</h3>"
dat += "<a href='?_src_=prefs;preference=ears;task=input'>[features["ears"]]</a><BR>"
mutant_category++
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("wings" in pref_species.default_features && GLOB.r_wings_list.len >1) if("wings" in pref_species.default_features && GLOB.r_wings_list.len >1)
if(!mutant_category) if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN dat += APPEARANCE_CATEGORY_COLUMN
@@ -1645,7 +1645,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
chosen_species = /datum/species/human chosen_species = /datum/species/human
pref_species = new /datum/species/human pref_species = new /datum/species/human
save_character() save_character()
character.set_species(chosen_species, icon_update=0) character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE)
if(icon_updates) if(icon_updates)
character.update_body() character.update_body()
@@ -1670,7 +1670,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/namedata = GLOB.preferences_custom_names[name_id] var/namedata = GLOB.preferences_custom_names[name_id]
if(!namedata) if(!namedata)
return return
var/raw_name = input(user, "Choose your character's [namedata["qdesc"]]:","Character Preference") as text|null var/raw_name = input(user, "Choose your character's [namedata["qdesc"]]:","Character Preference") as text|null
if(!raw_name) if(!raw_name)
if(namedata["allow_null"]) if(namedata["allow_null"])

View File

@@ -226,7 +226,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["species"] >> species_id S["species"] >> species_id
if(species_id) if(species_id)
var/newtype = GLOB.species_list[species_id] var/newtype = GLOB.species_list[species_id]
pref_species = new newtype() if(newtype)
pref_species = new newtype
if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000") if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000")
WRITE_FILE(S["features["mcolor"]"] , "#FFF") WRITE_FILE(S["features["mcolor"]"] , "#FFF")
@@ -263,12 +264,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else else
S["feature_human_tail"] >> features["tail_human"] S["feature_human_tail"] >> features["tail_human"]
S["feature_human_ears"] >> features["ears"] S["feature_human_ears"] >> features["ears"]
//Custom names //Custom names
for(var/custom_name_id in GLOB.preferences_custom_names) for(var/custom_name_id in GLOB.preferences_custom_names)
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
S[savefile_slot_name] >> custom_names[custom_name_id] S[savefile_slot_name] >> custom_names[custom_name_id]
S["prefered_security_department"] >> prefered_security_department S["prefered_security_department"] >> prefered_security_department
//Jobs //Jobs
@@ -311,7 +312,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
be_random_body = sanitize_integer(be_random_body, 0, 1, initial(be_random_body)) be_random_body = sanitize_integer(be_random_body, 0, 1, initial(be_random_body))
if(gender == MALE) if(gender == MALE)
hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_male_list) hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_male_list)
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_male_list) facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_male_list)
@@ -404,7 +405,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
for(var/custom_name_id in GLOB.preferences_custom_names) for(var/custom_name_id in GLOB.preferences_custom_names)
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
WRITE_FILE(S[savefile_slot_name],custom_names[custom_name_id]) WRITE_FILE(S[savefile_slot_name],custom_names[custom_name_id])
WRITE_FILE(S["prefered_security_department"] , prefered_security_department) WRITE_FILE(S["prefered_security_department"] , prefered_security_department)
//Jobs //Jobs

View File

@@ -82,7 +82,6 @@
if(H.dna.species.id != "human") if(H.dna.species.id != "human")
H.set_species(/datum/species/human) H.set_species(/datum/species/human)
H.apply_pref_name("human", H.client) H.apply_pref_name("human", H.client)
purrbation_remove(H, silent=TRUE)
//Equip the rest of the gear //Equip the rest of the gear
H.dna.species.before_equip_job(src, H, visualsOnly) H.dna.species.before_equip_job(src, H, visualsOnly)

View File

@@ -77,54 +77,27 @@
if(!.) if(!.)
return return
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(!H.is_wagging_tail()) if(!istype(H) || !H.dna || !H.dna.species || !H.dna.species.can_wag_tail(H))
H.startTailWag() return
if(!H.dna.species.is_wagging_tail())
H.dna.species.start_wagging_tail(H)
else else
H.endTailWag() H.dna.species.stop_wagging_tail(H)
/mob/living/carbon/human/proc/is_wagging_tail()
return (dna && dna.species && (("waggingtail_lizard" in dna.species.mutant_bodyparts) || ("waggingtail_human" in dna.species.mutant_bodyparts)))
/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE) /datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE)
if(!..()) if(!..())
return FALSE return FALSE
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(H.dna && H.dna.species && (("tail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("tail_human" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts))) return H.dna && H.dna.species && H.dna.species.can_wag_tail(user)
return TRUE
/datum/emote/living/carbon/human/wag/select_message_type(mob/user) /datum/emote/living/carbon/human/wag/select_message_type(mob/user)
. = ..() . = ..()
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(H.is_wagging_tail()) if(!H.dna || !H.dna.species)
return
if(H.dna.species.is_wagging_tail())
. = null . = null
//Don't know where else to put this, it's basically an emote
/mob/living/carbon/human/proc/startTailWag()
if(!dna || !dna.species)
return
if("tail_lizard" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_lizard"
dna.species.mutant_bodyparts -= "spines"
dna.species.mutant_bodyparts |= "waggingtail_lizard"
dna.species.mutant_bodyparts |= "waggingspines"
if("tail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_human"
dna.species.mutant_bodyparts |= "waggingtail_human"
update_body()
/mob/living/carbon/human/proc/endTailWag()
if(!dna || !dna.species)
return
if("waggingtail_lizard" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_lizard"
dna.species.mutant_bodyparts -= "waggingspines"
dna.species.mutant_bodyparts |= "tail_lizard"
dna.species.mutant_bodyparts |= "spines"
if("waggingtail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_human"
dna.species.mutant_bodyparts |= "tail_human"
update_body()
/datum/emote/living/carbon/human/wing /datum/emote/living/carbon/human/wing
key = "wing" key = "wing"
key_third_person = "wings" key_third_person = "wings"

View File

@@ -242,7 +242,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/organ/I = new path() var/obj/item/organ/I = new path()
I.Insert(C) I.Insert(C)
/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species) /datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
// Drop the items the new species can't wear // Drop the items the new species can't wear
for(var/slot_id in no_equip) for(var/slot_id in no_equip)
var/obj/item/thing = C.get_item_by_slot(slot_id) var/obj/item/thing = C.get_item_by_slot(slot_id)
@@ -287,7 +287,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
A.cure(FALSE) A.cure(FALSE)
/datum/species/proc/on_species_loss(mob/living/carbon/C) /datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
if(C.dna.species.exotic_bloodtype) if(C.dna.species.exotic_bloodtype)
C.dna.blood_type = random_blood_type() C.dna.blood_type = random_blood_type()
if(DIGITIGRADE in species_traits) if(DIGITIGRADE in species_traits)
@@ -1665,3 +1665,17 @@ GLOBAL_LIST_EMPTY(roundstart_races)
/datum/species/proc/negates_gravity(mob/living/carbon/human/H) /datum/species/proc/negates_gravity(mob/living/carbon/human/H)
return 0 return 0
////////////////
//Tail Wagging//
////////////////
/datum/species/proc/can_wag_tail(mob/living/carbon/human/H)
return FALSE
/datum/species/proc/is_wagging_tail(mob/living/carbon/human/H)
return FALSE
/datum/species/proc/start_wagging_tail(mob/living/carbon/human/H)
/datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H)

View File

@@ -0,0 +1,130 @@
//Subtype of human
/datum/species/human/felinid
name = "Felinid"
id = "felinid"
limbs_id = "human"
mutant_bodyparts = list("ears", "tail_human")
default_features = list("mcolor" = "FFF", "tail_human" = "Cat", "ears" = "Cat", "wings" = "None")
mutantears = /obj/item/organ/ears/cat
mutanttail = /obj/item/organ/tail/cat
/datum/species/human/felinid/qualifies_for_rank(rank, list/features)
return TRUE
//Curiosity killed the cat's wagging tail.
/datum/species/human/felinid/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
stop_wagging_tail(H)
/datum/species/human/felinid/spec_stun(mob/living/carbon/human/H,amount)
if(H)
stop_wagging_tail(H)
. = ..()
/datum/species/human/felinid/can_wag_tail(mob/living/carbon/human/H)
return ("tail_human" in mutant_bodyparts) || ("waggingtail_human" in mutant_bodyparts)
/datum/species/human/felinid/is_wagging_tail(mob/living/carbon/human/H)
return ("waggingtail_human" in mutant_bodyparts)
/datum/species/human/felinid/start_wagging_tail(mob/living/carbon/human/H)
if("tail_human" in mutant_bodyparts)
mutant_bodyparts -= "tail_human"
mutant_bodyparts |= "waggingtail_human"
H.update_body()
/datum/species/human/felinid/stop_wagging_tail(mob/living/carbon/human/H)
if("waggingtail_human" in mutant_bodyparts)
mutant_bodyparts -= "waggingtail_human"
mutant_bodyparts |= "tail_human"
H.update_body()
/datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(!pref_load) //Hah! They got forcefully purrbation'd. Force default felinid parts on them if they have no mutant parts in those areas!
if(H.dna.features["tail_human"] == "None")
H.dna.features["tail_human"] = "Cat"
if(H.dna.features["ears"] == "None")
H.dna.features["ears"] = "Cat"
if(H.dna.features["ears"] == "Cat")
var/obj/item/organ/ears/cat/ears = new
ears.Insert(H, drop_if_replaced = FALSE)
else
mutantears = /obj/item/organ/ears
if(H.dna.features["tail_human"] == "Cat")
var/obj/item/organ/tail/cat/tail = new
tail.Insert(H, drop_if_replaced = FALSE)
else
mutanttail = null
return ..()
/datum/species/human/felinid/on_species_loss(mob/living/carbon/H, datum/species/new_species, pref_load)
var/obj/item/organ/ears/cat/ears = H.getorgan(/obj/item/organ/ears/cat)
var/obj/item/organ/tail/cat/tail = H.getorgan(/obj/item/organ/tail/cat)
if(ears)
var/obj/item/organ/ears/NE
if(new_species && new_species.mutantears)
// Roundstart cat ears override new_species.mutantears, reset it here.
new_species.mutantears = initial(new_species.mutantears)
if(new_species.mutantears)
NE = new new_species.mutantears
if(!NE)
// Go with default ears
NE = new /obj/item/organ/ears
NE.Insert(H, drop_if_replaced = FALSE)
if(tail)
var/obj/item/organ/tail/NT
if(new_species && new_species.mutanttail)
// Roundstart cat tail overrides new_species.mutanttail, reset it here.
new_species.mutanttail = initial(new_species.mutanttail)
if(new_species.mutanttail)
NT = new new_species.mutanttail
if(NT)
NT.Insert(H, drop_if_replaced = FALSE)
else
tail.Remove(H)
/proc/mass_purrbation()
for(var/M in GLOB.mob_list)
if(ishumanbasic(M))
purrbation_apply(M)
CHECK_TICK
/proc/mass_remove_purrbation()
for(var/M in GLOB.mob_list)
if(ishumanbasic(M))
purrbation_remove(M)
CHECK_TICK
/proc/purrbation_toggle(mob/living/carbon/human/H, silent = FALSE)
if(!ishumanbasic(H))
return
if(!iscatperson(H))
purrbation_apply(H, silent)
. = TRUE
else
purrbation_remove(H, silent)
. = FALSE
/proc/purrbation_apply(mob/living/carbon/human/H, silent = FALSE)
if(!ishuman(H) || iscatperson(H))
return
H.set_species(/datum/species/human/felinid)
if(!silent)
to_chat(H, "Something is nya~t right.")
playsound(get_turf(H), 'sound/effects/meow1.ogg', 50, 1, -1)
/proc/purrbation_remove(mob/living/carbon/human/H, silent = FALSE)
if(!ishuman(H) || !iscatperson(H))
return
H.set_species(/datum/species/human)
if(!silent)
to_chat(H, "You are no longer a cat.")

View File

@@ -3,29 +3,11 @@
id = "human" id = "human"
default_color = "FFFFFF" default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None") default_features = list("mcolor" = "FFF", "wings" = "None")
use_skintones = 1 use_skintones = 1
skinned_type = /obj/item/stack/sheet/animalhide/human skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED liked_food = JUNKFOOD | FRIED
/datum/species/human/qualifies_for_rank(rank, list/features) /datum/species/human/qualifies_for_rank(rank, list/features)
return TRUE //Pure humans are always allowed in all roles. return TRUE //Pure humans are always allowed in all roles.
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
/datum/species/human/spec_stun(mob/living/carbon/human/H,amount)
if(H)
H.endTailWag()
. = ..()
/datum/species/human/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
if(H.dna.features["ears"] == "Cat")
mutantears = /obj/item/organ/ears/cat
if(H.dna.features["tail_human"] == "Cat")
mutanttail = /obj/item/organ/tail/cat
..()

View File

@@ -38,13 +38,35 @@
//I wag in death //I wag in death
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H) /datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
if(H) if(H)
H.endTailWag() stop_wagging_tail(H)
/datum/species/lizard/spec_stun(mob/living/carbon/human/H,amount) /datum/species/lizard/spec_stun(mob/living/carbon/human/H,amount)
if(H) if(H)
H.endTailWag() stop_wagging_tail(H)
. = ..() . = ..()
/datum/species/lizard/can_wag_tail(mob/living/carbon/human/H)
return ("tail_lizard" in mutant_bodyparts) || ("waggingtail_lizard" in mutant_bodyparts)
/datum/species/lizard/is_wagging_tail(mob/living/carbon/human/H)
return ("waggingtail_lizard" in mutant_bodyparts)
/datum/species/lizard/start_wagging_tail(mob/living/carbon/human/H)
if("tail_lizard" in mutant_bodyparts)
mutant_bodyparts -= "tail_lizard"
mutant_bodyparts -= "spines"
mutant_bodyparts |= "waggingtail_lizard"
mutant_bodyparts |= "waggingspines"
H.update_body()
/datum/species/lizard/stop_wagging_tail(mob/living/carbon/human/H)
if("waggingtail_lizard" in mutant_bodyparts)
mutant_bodyparts -= "waggingtail_lizard"
mutant_bodyparts -= "waggingspines"
mutant_bodyparts |= "tail_lizard"
mutant_bodyparts |= "spines"
H.update_body()
/* /*
Lizard subspecies: ASHWALKERS Lizard subspecies: ASHWALKERS
*/ */

View File

@@ -10,9 +10,8 @@
/obj/item/organ/tail/Remove(mob/living/carbon/human/H, special = 0) /obj/item/organ/tail/Remove(mob/living/carbon/human/H, special = 0)
..() ..()
if(istype(H)) if(H && H.dna && H.dna.species)
H.endTailWag() H.dna.species.stop_wagging_tail(H)
/obj/item/organ/tail/cat /obj/item/organ/tail/cat
name = "cat tail" name = "cat tail"

View File

@@ -1901,6 +1901,7 @@
#include "code\modules\mob\living\carbon\human\species_types\angel.dm" #include "code\modules\mob\living\carbon\human\species_types\angel.dm"
#include "code\modules\mob\living\carbon\human\species_types\corporate.dm" #include "code\modules\mob\living\carbon\human\species_types\corporate.dm"
#include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\dullahan.dm"
#include "code\modules\mob\living\carbon\human\species_types\felinid.dm"
#include "code\modules\mob\living\carbon\human\species_types\flypeople.dm" #include "code\modules\mob\living\carbon\human\species_types\flypeople.dm"
#include "code\modules\mob\living\carbon\human\species_types\golems.dm" #include "code\modules\mob\living\carbon\human\species_types\golems.dm"
#include "code\modules\mob\living\carbon\human\species_types\humans.dm" #include "code\modules\mob\living\carbon\human\species_types\humans.dm"

View File

@@ -1893,6 +1893,7 @@
#include "code\modules\mob\living\carbon\human\species_types\angel.dm" #include "code\modules\mob\living\carbon\human\species_types\angel.dm"
#include "code\modules\mob\living\carbon\human\species_types\corporate.dm" #include "code\modules\mob\living\carbon\human\species_types\corporate.dm"
#include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\dullahan.dm"
#include "code\modules\mob\living\carbon\human\species_types\felinid.dm"
#include "code\modules\mob\living\carbon\human\species_types\flypeople.dm" #include "code\modules\mob\living\carbon\human\species_types\flypeople.dm"
#include "code\modules\mob\living\carbon\human\species_types\golems.dm" #include "code\modules\mob\living\carbon\human\species_types\golems.dm"
#include "code\modules\mob\living\carbon\human\species_types\humans.dm" #include "code\modules\mob\living\carbon\human\species_types\humans.dm"