From 9e9995846d7ecd631a914398e2126b7710551e64 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Wed, 8 Aug 2018 10:56:46 -0700
Subject: [PATCH 1/4] Felinid/catpeople are now their own human subspecies
(#39513)
* Catpeople are nyow a species
* Fixes a runtime
* Fixes the issues with being forced ears when you chose none
* Neko --> Felinid
* P2
* Update
* Working this time I promise
---
code/__DEFINES/is_helpers.dm | 4 +-
code/controllers/subsystem/job.dm | 2 +-
code/datums/dna.dm | 18 ++-
.../mood_events/generic_negative_events.dm | 4 +-
code/game/objects/items/weaponry.dm | 3 +-
code/modules/admin/verbs/randomverbs.dm | 80 +----------
code/modules/client/preferences.dm | 58 ++++----
code/modules/client/preferences_savefile.dm | 13 +-
code/modules/jobs/job_types/job.dm | 1 -
code/modules/mob/living/carbon/human/emote.dm | 45 ++----
.../mob/living/carbon/human/species.dm | 18 ++-
.../carbon/human/species_types/felinid.dm | 130 ++++++++++++++++++
.../carbon/human/species_types/humans.dm | 20 +--
.../human/species_types/lizardpeople.dm | 26 +++-
code/modules/surgery/organs/tails.dm | 5 +-
tgstation.dme | 1 +
16 files changed, 238 insertions(+), 190 deletions(-)
create mode 100644 code/modules/mob/living/carbon/human/species_types/felinid.dm
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 5394f40d883e..15eaadb2f286 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -58,9 +58,7 @@
#define iszombie(A) (is_species(A, /datum/species/zombie))
#define ismoth(A) (is_species(A, /datum/species/moth))
#define ishumanbasic(A) (is_species(A, /datum/species/human))
-
-//why arent catpeople a subspecies
-#define iscatperson(A) (ishumanbasic(A) && ( A.dna.features["ears"] == "Cat" || A.dna.features["tail_human"] == "Cat") )
+#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
//more carbon mobs
#define ismonkey(A) (istype(A, /mob/living/carbon/monkey))
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index af7b165e99ea..d1c3391f5730 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -367,7 +367,7 @@ SUBSYSTEM_DEF(job)
var/allowed_to_be_a_loser = !jobban_isbanned(player, SSjob.overflow_role)
if(QDELETED(player) || !allowed_to_be_a_loser)
RejectPlayer(player)
- else
+ else
if(!AssignRole(player, SSjob.overflow_role))
RejectPlayer(player)
else if(player.client.prefs.joblessrole == BERANDOMJOB)
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index df75982b721e..0372b1392e55 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -215,17 +215,21 @@
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())
- dna.species.on_species_loss(src)
- var/old_species = dna.species
+ var/datum/species/new_race
if(ispath(mrace))
- dna.species = new mrace()
+ new_race = new mrace
+ else if(istype(mrace))
+ new_race = mrace
else
- dna.species = mrace
- dna.species.on_species_gain(src, old_species)
+ return
+ 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)
update_body()
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index 04be096439d2..b5e779faae81 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -84,8 +84,8 @@
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(iscatperson(H))
- H.startTailWag()
- addtimer(CALLBACK(H, /mob/living/carbon/human.proc/endTailWag), 30)
+ H.dna.species.start_wagging_tail(H)
+ addtimer(CALLBACK(H.dna.species, /datum/species.proc/stop_wagging_tail, H), 30)
description = "They want to play on the table!\n"
mood_change = 2
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 44c51099c6f4..b483bd03bac7 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -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)
if(ishuman(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)))
user.do_attack_animation(M)
playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1)
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index d306dacaae8b..59b0832bfdbe 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -48,12 +48,12 @@
/client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list)
set category = "Special Verbs"
set name = "Headset Message"
-
+
admin_headset_message(M)
/client/proc/admin_headset_message(mob/M in GLOB.mob_list, sender = null)
var/mob/living/carbon/human/H = M
-
+
if(!check_rights(R_ADMIN))
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.")
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()
set category = "Debug"
set name = "Modify goals"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 63ceda33eb53..3991831c8725 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -125,7 +125,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
for(var/custom_name_id in GLOB.preferences_custom_names)
custom_names[custom_name_id] = get_default_name(custom_name_id)
-
+
UI_style = GLOB.available_ui_styles[1]
if(istype(C))
if(!IsGuestKey(C.key))
@@ -405,34 +405,34 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += ""
mutant_category = 0
+ if("tail_human" in pref_species.default_features)
+ if(!mutant_category)
+ dat += APPEARANCE_CATEGORY_COLUMN
+
+ dat += "
Tail
"
+
+ dat += "[features["tail_human"]]
"
+
+ mutant_category++
+ if(mutant_category >= MAX_MUTANT_ROWS)
+ dat += ""
+ mutant_category = 0
+
+ if("ears" in pref_species.default_features)
+ if(!mutant_category)
+ dat += APPEARANCE_CATEGORY_COLUMN
+
+ dat += "Ears
"
+
+ dat += "[features["ears"]]
"
+
+ mutant_category++
+ if(mutant_category >= MAX_MUTANT_ROWS)
+ dat += ""
+ mutant_category = 0
+
if(CONFIG_GET(flag/join_with_mutant_humans))
- if("tail_human" in pref_species.default_features)
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Tail
"
-
- dat += "[features["tail_human"]]
"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if("ears" in pref_species.default_features)
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Ears
"
-
- dat += "[features["ears"]]
"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
if("wings" in pref_species.default_features && GLOB.r_wings_list.len >1)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -1645,7 +1645,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
chosen_species = /datum/species/human
pref_species = new /datum/species/human
save_character()
- character.set_species(chosen_species, icon_update=0)
+ character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE)
if(icon_updates)
character.update_body()
@@ -1670,7 +1670,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/namedata = GLOB.preferences_custom_names[name_id]
if(!namedata)
return
-
+
var/raw_name = input(user, "Choose your character's [namedata["qdesc"]]:","Character Preference") as text|null
if(!raw_name)
if(namedata["allow_null"])
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 2f12e6c2c48f..44a3ab04eb6f 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -226,7 +226,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["species"] >> species_id
if(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")
WRITE_FILE(S["features["mcolor"]"] , "#FFF")
@@ -263,12 +264,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else
S["feature_human_tail"] >> features["tail_human"]
S["feature_human_ears"] >> features["ears"]
-
+
//Custom names
for(var/custom_name_id in GLOB.preferences_custom_names)
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
//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_body = sanitize_integer(be_random_body, 0, 1, initial(be_random_body))
-
+
if(gender == MALE)
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)
@@ -404,7 +405,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
for(var/custom_name_id in GLOB.preferences_custom_names)
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["prefered_security_department"] , prefered_security_department)
//Jobs
diff --git a/code/modules/jobs/job_types/job.dm b/code/modules/jobs/job_types/job.dm
index 5d4802f93a96..2f4daed27982 100644
--- a/code/modules/jobs/job_types/job.dm
+++ b/code/modules/jobs/job_types/job.dm
@@ -82,7 +82,6 @@
if(H.dna.species.id != "human")
H.set_species(/datum/species/human)
H.apply_pref_name("human", H.client)
- purrbation_remove(H, silent=TRUE)
//Equip the rest of the gear
H.dna.species.before_equip_job(src, H, visualsOnly)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 786ddec5ddb3..0db3d8277705 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -77,54 +77,27 @@
if(!.)
return
var/mob/living/carbon/human/H = user
- if(!H.is_wagging_tail())
- H.startTailWag()
+ if(!istype(H) || !H.dna || !H.dna.species || !H.dna.species.can_wag_tail(H))
+ return
+ if(!H.dna.species.is_wagging_tail())
+ H.dna.species.start_wagging_tail(H)
else
- H.endTailWag()
-
-/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)))
+ H.dna.species.stop_wagging_tail(H)
/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE)
if(!..())
return FALSE
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 TRUE
+ return H.dna && H.dna.species && H.dna.species.can_wag_tail(user)
/datum/emote/living/carbon/human/wag/select_message_type(mob/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
-//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
key = "wing"
key_third_person = "wings"
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 367ab0fefda4..0115d8c34f73 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -242,7 +242,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/organ/I = new path()
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
for(var/slot_id in no_equip)
var/obj/item/thing = C.get_item_by_slot(slot_id)
@@ -287,7 +287,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
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)
C.dna.blood_type = random_blood_type()
if(DIGITIGRADE in species_traits)
@@ -1665,3 +1665,17 @@ GLOBAL_LIST_EMPTY(roundstart_races)
/datum/species/proc/negates_gravity(mob/living/carbon/human/H)
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)
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
new file mode 100644
index 000000000000..1d82614fb17c
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -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.")
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index 2751b8b7a753..0f947b7293ef 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -3,29 +3,11 @@
id = "human"
default_color = "FFFFFF"
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
skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED
-
/datum/species/human/qualifies_for_rank(rank, list/features)
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
- ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index 3af021fc0ed0..b20c14c3380d 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -38,13 +38,35 @@
//I wag in death
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
- H.endTailWag()
+ stop_wagging_tail(H)
/datum/species/lizard/spec_stun(mob/living/carbon/human/H,amount)
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
*/
diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm
index 8b05cbef08b1..b6701643a9e1 100644
--- a/code/modules/surgery/organs/tails.dm
+++ b/code/modules/surgery/organs/tails.dm
@@ -10,9 +10,8 @@
/obj/item/organ/tail/Remove(mob/living/carbon/human/H, special = 0)
..()
- if(istype(H))
- H.endTailWag()
-
+ if(H && H.dna && H.dna.species)
+ H.dna.species.stop_wagging_tail(H)
/obj/item/organ/tail/cat
name = "cat tail"
diff --git a/tgstation.dme b/tgstation.dme
index 0c1b869d42f7..b6e12e049891 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1901,6 +1901,7 @@
#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\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\golems.dm"
#include "code\modules\mob\living\carbon\human\species_types\humans.dm"
From 8d7cdcb5a1da929937d77ac162941f9fa0890085 Mon Sep 17 00:00:00 2001
From: Joe Schmoe
Date: Wed, 8 Aug 2018 22:09:41 +0200
Subject: [PATCH 3/4] awewefhjk
---
yogstation.dme | 1 -
1 file changed, 1 deletion(-)
diff --git a/yogstation.dme b/yogstation.dme
index 412aa6308d3d..995f7a16d793 100644
--- a/yogstation.dme
+++ b/yogstation.dme
@@ -2739,7 +2739,6 @@
#include "yogstation\code\modules\mob\dead\new_player\new_player.dm"
#include "yogstation\code\modules\mob\living\carbon\human\life.dm"
#include "yogstation\code\modules\mob\living\carbon\human\species_types\plantpeople.dm"
-#include "yogstation\code\modules\mob\living\silicon\silicon.dm"
#include "yogstation\code\modules\mob\living\silicon\ai\ai.dm"
#include "yogstation\code\modules\mob\living\silicon\ai\vox_sounds.dm"
#include "yogstation\code\modules\mob\living\silicon\robot\robot.dm"
From 6f738d085d1367b21c80ce42844b97676585f447 Mon Sep 17 00:00:00 2001
From: Joe Schmoe
Date: Wed, 8 Aug 2018 22:11:30 +0200
Subject: [PATCH 4/4] git wtf
---
yogstation.dme | 2 ++
1 file changed, 2 insertions(+)
diff --git a/yogstation.dme b/yogstation.dme
index 995f7a16d793..0cbec741c37d 100644
--- a/yogstation.dme
+++ b/yogstation.dme
@@ -1893,6 +1893,7 @@
#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\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\golems.dm"
#include "code\modules\mob\living\carbon\human\species_types\humans.dm"
@@ -2739,6 +2740,7 @@
#include "yogstation\code\modules\mob\dead\new_player\new_player.dm"
#include "yogstation\code\modules\mob\living\carbon\human\life.dm"
#include "yogstation\code\modules\mob\living\carbon\human\species_types\plantpeople.dm"
+#include "yogstation\code\modules\mob\living\silicon\silicon.dm"
#include "yogstation\code\modules\mob\living\silicon\ai\ai.dm"
#include "yogstation\code\modules\mob\living\silicon\ai\vox_sounds.dm"
#include "yogstation\code\modules\mob\living\silicon\robot\robot.dm"