Skip to content

Commit

Permalink
Adds goblin noses and Ported a tg external organ fix (#5576)
Browse files Browse the repository at this point in the history
## About The Pull Request
- Adds 5 different noses of arguable quality for goblins to chose from.
- Ported tgstation/tgstation#75963

None

![image](https://github.com/user-attachments/assets/6e6c2586-cd3b-45c9-b56f-48632e007a13)
Button

![image](https://github.com/user-attachments/assets/44c656db-2450-43f8-ae94-7bba5b3da896)
Liar

![image](https://github.com/user-attachments/assets/58e2fbed-08fe-4537-97e2-3a0be850d8c3)
Sniffer

![image](https://github.com/user-attachments/assets/76c511f3-89e8-4eda-9d91-3540f220ab9e)
Hook

![image](https://github.com/user-attachments/assets/63f5adb9-15be-44a9-ad86-760d9fea5560)
Wobble

![image](https://github.com/user-attachments/assets/47582ae6-d0ae-4842-bdd8-a6f781a0f10b)



## Why It's Good For The Game
- Character customisation and such
- Fixes a few oddities to do with external features that have the `None`
type selected

## Changelog
:cl:
add: Added Goblin Noses
fix: You can no longer manipulate "None" organs
/:cl:

---------

Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
  • Loading branch information
Sorenon and ZephyrTFA authored Feb 25, 2025
1 parent abbd7f8 commit 7e89d5e
Show file tree
Hide file tree
Showing 28 changed files with 171 additions and 35 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,6 @@
#define PLAYTIME_HARDCORE_RANDOM 120 // 2 hours
/// The time needed to unlock the gamer cloak in preferences
#define PLAYTIME_VETERAN 300000 // 5,000 hours

/// The key used for sprite accessories that should never actually be applied to the player.
#define SPRITE_ACCESSORY_NONE "None"
1 change: 1 addition & 0 deletions code/__HELPERS/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/arachnid_appendages, GLOB.arachnid_appendages_list) //Monkestation Addition
init_sprite_accessory_subtypes(/datum/sprite_accessory/arachnid_chelicerae, GLOB.arachnid_chelicerae_list) //Monkestation Addition
init_sprite_accessory_subtypes(/datum/sprite_accessory/goblin_ears, GLOB.goblin_ears_list) //Monkestation Addition
init_sprite_accessory_subtypes(/datum/sprite_accessory/goblin_nose, GLOB.goblin_nose_list) //Monkestation Addition
init_sprite_accessory_subtypes(/datum/sprite_accessory/floran_leaves, GLOB.floran_leaves_list) //Monkestation Addition
init_sprite_accessory_subtypes(/datum/sprite_accessory/apid_wings, GLOB.apid_wings_list) //Monkestation Addition
init_sprite_accessory_subtypes(/datum/sprite_accessory/satyr_fluff, GLOB.satyr_fluff_list) //Monkestation Addition
Expand Down
3 changes: 3 additions & 0 deletions code/__HELPERS/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/arachnid_chelicerae, GLOB.arachnid_chelicerae_list)
if(!length(GLOB.goblin_ears_list))
init_sprite_accessory_subtypes(/datum/sprite_accessory/goblin_ears, GLOB.goblin_ears_list)
if(!length(GLOB.goblin_nose_list))
init_sprite_accessory_subtypes(/datum/sprite_accessory/goblin_nose, GLOB.goblin_nose_list)
if(!length(GLOB.floran_leaves_list))
init_sprite_accessory_subtypes(/datum/sprite_accessory/floran_leaves, GLOB.floran_leaves_list)
if(!GLOB.satyr_fluff_list.len)
Expand Down Expand Up @@ -172,6 +174,7 @@
"arachnid_chelicerae" = pick(GLOB.arachnid_chelicerae_list), //Monkestation Addition
"animecolor" = "#[pick("7F","FF")][pick("7F","FF")][pick("7F","FF")]", //Monkestation Addition
"goblin_ears" = pick(GLOB.goblin_ears_list), //Monkestation Addition
"goblin_nose" = pick(GLOB.goblin_nose_list), //Monkestation Addition
"floran_leaves" = pick(GLOB.floran_leaves_list), //Monkestation Addition
"satyr_fluff" = pick(GLOB.satyr_fluff_list), //Monkestation Addition
"satyr_tail" = pick(GLOB.satyr_tail_list), //Monkestation Addition
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/lists/flavor_misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ GLOBAL_LIST_EMPTY(anime_bottom_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(arachnid_appendages_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(arachnid_chelicerae_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(goblin_ears_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(goblin_nose_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(floran_leaves_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(satyr_fluff_list) //Monkestation Addition
GLOBAL_LIST_EMPTY(satyr_tail_list) //Monkestation Addition
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/dead/new_player/sprite_accessories.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
male += D.name
female += D.name
if(add_blank)
L["None"] = new /datum/sprite_accessory/blank
L[SPRITE_ACCESSORY_NONE] = new /datum/sprite_accessory/blank

return L

Expand Down
10 changes: 10 additions & 0 deletions code/modules/mob/living/carbon/human/_species.dm
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,13 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/list/species_organs = mutant_organs + external_organs
for(var/organ_path in species_organs)
var/obj/item/organ/current_organ = organ_holder.get_organ_by_type(organ_path)
if(ispath(organ_path, /obj/item/organ/external) && !should_external_organ_apply_to(organ_path, organ_holder))
if(!isnull(current_organ) && replace_current)
// if we have an organ here and we're replacing organs, remove it
current_organ.Remove(organ_holder)
QDEL_NULL(current_organ)
continue

if(!current_organ || replace_current)
var/obj/item/organ/replacement = SSwardrobe.provide_type(organ_path)
// If there's an existing mutant organ, we're technically replacing it.
Expand Down Expand Up @@ -542,6 +549,9 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(ishuman(C))
var/mob/living/carbon/human/human = C
for(var/obj/item/organ/external/organ_path as anything in external_organs)
if(!should_external_organ_apply_to(organ_path, human))
continue

//Load a persons preferences from DNA
var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path)
new_organ.Insert(human, special=TRUE, drop_if_replaced=FALSE)
Expand Down
75 changes: 43 additions & 32 deletions code/modules/mob/living/carbon/human/dummy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -103,40 +103,51 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/log_mob_tag(text)
return

/// Takes in an accessory list and returns the first entry from that list, ensuring that we dont return SPRITE_ACCESSORY_NONE in the process.
/proc/get_consistent_feature_entry(list/accessory_feature_list)
var/consistent_entry = (accessory_feature_list- SPRITE_ACCESSORY_NONE)[1]
ASSERT(!isnull(consistent_entry))
return consistent_entry

/proc/create_consistent_human_dna(mob/living/carbon/human/target)
target.dna.initialize_dna(/datum/blood_type/crew/human/o_plus, skip_index = TRUE)
target.dna.features["body_markings"] = "None"
target.dna.features["ears"] = "None"
target.dna.features["frills"] = "None"
target.dna.features["horns"] = "None"
target.dna.features["moth_antennae"] = "Plain"
target.dna.features["moth_markings"] = "None"
target.dna.features["moth_wings"] = "Plain"
target.dna.features["snout"] = "Round"
target.dna.features["spines"] = "None"
target.dna.features["tail_cat"] = "None"
target.dna.features["tail_lizard"] = "Smooth"
target.dna.features["tail_monkey"] = "Monkey"
target.dna.features["pod_hair"] = "Ivy"
target.dna.initialize_dna(skip_index = TRUE)
/* monkestation removal
target.dna.features["mcolor"] = COLOR_VIBRANT_LIME
target.dna.features["ethcolor"] = COLOR_WHITE
*/
target.dna.features["body_markings"] = get_consistent_feature_entry(GLOB.body_markings_list)
target.dna.features["ears"] = get_consistent_feature_entry(GLOB.ears_list)
target.dna.features["frills"] = get_consistent_feature_entry(GLOB.frills_list)
target.dna.features["horns"] = get_consistent_feature_entry(GLOB.horns_list)
target.dna.features["moth_antennae"] = get_consistent_feature_entry(GLOB.moth_antennae_list)
target.dna.features["moth_markings"] = get_consistent_feature_entry(GLOB.moth_markings_list)
target.dna.features["moth_wings"] = get_consistent_feature_entry(GLOB.moth_wings_list)
target.dna.features["snout"] = get_consistent_feature_entry(GLOB.snouts_list)
target.dna.features["spines"] = get_consistent_feature_entry(GLOB.spines_list)
target.dna.features["tail_cat"] = get_consistent_feature_entry(GLOB.tails_list_human) // it's a lie
target.dna.features["tail_lizard"] = get_consistent_feature_entry(GLOB.tails_list_lizard)
target.dna.features["tail_monkey"] = get_consistent_feature_entry(GLOB.tails_list_monkey)
target.dna.features["pod_hair"] = get_consistent_feature_entry(GLOB.pod_hair_list)
target.dna.features["fur"] = COLOR_MONKEY_BROWN //Monkestation Addition
target.dna.features["ethereal_horns"] = "None" //Monkestation Addition
target.dna.features["ethereal_tail"] = "None" //Monkestation Addition
target.dna.features["ipc_screen"] = "BSOD" //Monkestation Addition
target.dna.features["ipc_chassis"] = "Bishop Cyberkinetics" //Monkestation Addition
target.dna.features["ipc_antenna"] = "None" //Monkestation Addition
target.dna.features["anime_top"] = "None" //Monkestation Addition
target.dna.features["anime_middle"] = "None" //Monkestation Addition
target.dna.features["anime_bottom"] = "None" //Monkestation Addition
target.dna.features["arachnid_appendages"] = "Long" //Monkestation Addition
target.dna.features["arachnid_chelicerae"] = "Basic" //Monkestation Addition
target.dna.features["goblin_ears"] = "Normal" //Monkestation Addition
target.dna.features["floran_leaves"] = "Furnivour" //Monkestation Addition
target.dna.features["satyr_fluff"] = "Normal" //Monkestation Addition
target.dna.features["satyr_tail"] = "Short" //Monkestation Addition
target.dna.features["satyr_horns"] = "Back" //Monkestation Addition
target.dna.features["arm_wings"] = "Monochrome" //Monkestation Addition
target.dna.features["ears_avian"] = "Hermes" //Monkestation Addition
target.dna.features["tail_avian"] = "Eagle" //Monkestation Addition
target.dna.features["ethereal_horns"] = get_consistent_feature_entry(GLOB.ethereal_horns_list) //Monkestation Addition
target.dna.features["ethereal_tail"] = get_consistent_feature_entry(GLOB.ethereal_tail_list) //Monkestation Addition
target.dna.features["ipc_screen"] = get_consistent_feature_entry(GLOB.ipc_screens_list) //Monkestation Addition
target.dna.features["ipc_chassis"] = get_consistent_feature_entry(GLOB.ipc_chassis_list) //Monkestation Addition
target.dna.features["ipc_antenna"] = get_consistent_feature_entry(GLOB.ipc_antennas_list) //Monkestation Addition
target.dna.features["anime_top"] = get_consistent_feature_entry(GLOB.anime_top_list) //Monkestation Addition
target.dna.features["anime_middle"] = get_consistent_feature_entry(GLOB.anime_middle_list) //Monkestation Addition
target.dna.features["anime_bottom"] = get_consistent_feature_entry(GLOB.anime_bottom_list) //Monkestation Addition
target.dna.features["arachnid_appendages"] = get_consistent_feature_entry(GLOB.arachnid_appendages_list) //Monkestation Addition
target.dna.features["arachnid_chelicerae"] = get_consistent_feature_entry(GLOB.arachnid_chelicerae_list) //Monkestation Addition
target.dna.features["goblin_ears"] = get_consistent_feature_entry(GLOB.goblin_ears_list) //Monkestation Addition
target.dna.features["goblin_nose"] = get_consistent_feature_entry(GLOB.goblin_nose_list) //Monkestation Addition
target.dna.features["floran_leaves"] = get_consistent_feature_entry(GLOB.floran_leaves_list) //Monkestation Addition
target.dna.features["satyr_fluff"] = get_consistent_feature_entry(GLOB.satyr_fluff_list) //Monkestation Addition
target.dna.features["satyr_tail"] = get_consistent_feature_entry(GLOB.satyr_tail_list) //Monkestation Addition
target.dna.features["satyr_horns"] = get_consistent_feature_entry(GLOB.satyr_horns_list) //Monkestation Addition
target.dna.features["arm_wings"] = get_consistent_feature_entry(GLOB.arm_wings_list) //Monkestation Addition
target.dna.features["ears_avian"] = get_consistent_feature_entry(GLOB.avian_ears_list) //Monkestation Addition
target.dna.features["tail_avian"] = get_consistent_feature_entry(GLOB.tails_list_avian) //Monkestation Addition

var/datum/color_palette/generic_colors/palette = target.dna.color_palettes[/datum/color_palette/generic_colors]
palette.mutant_color = COLOR_VIBRANT_LIME
Expand Down
11 changes: 10 additions & 1 deletion code/modules/mob/living/carbon/human/species_types/ethereal.dm
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@

/datum/species/ethereal/lustrous/on_species_gain(mob/living/carbon/new_lustrous, datum/species/old_species, pref_load)
..()
// monkestation edit start
/* original
default_color = new_lustrous.dna.features["ethcolor"]
new_lustrous.dna.features["ethcolor"] = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors.
*/
var/datum/color_palette/generic_colors/palette = new_lustrous.dna.color_palettes[/datum/color_palette/generic_colors]
default_color = palette.ethereal_color
palette.ethereal_color = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors.
if(istype(new_lustrous, /mob/living/carbon/human/dummy/consistent))
palette.ethereal_color = GLOB.color_list_lustrous[1]
else
palette.ethereal_color = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors.
// monkestation edit end
4 changes: 4 additions & 0 deletions code/modules/surgery/bodyparts/dismemberment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,10 @@

//Copied from /datum/species/proc/on_species_gain()
for(var/obj/item/organ/external/organ_path as anything in dna.species.external_organs)
// monkestation edit start
if (!should_external_organ_apply_to(organ_path, src))
continue
// monkestation edit end
//Load a persons preferences from DNA
var/zone = initial(organ_path.zone)
if(zone != limb_zone)
Expand Down
17 changes: 17 additions & 0 deletions code/modules/surgery/organs/external/_external_organs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
return ..()

/obj/item/organ/external/Insert(mob/living/carbon/receiver, special, drop_if_replaced)
if(!should_external_organ_apply_to(type, receiver))
stack_trace("adding a [type] to a [receiver.type] when it shouldn't be!")

var/obj/item/bodypart/limb = receiver.get_bodypart(deprecise_zone(zone))

if(!limb)
Expand Down Expand Up @@ -124,6 +127,20 @@
ownerlimb = null
return ..()

/proc/should_external_organ_apply_to(obj/item/organ/external/organpath, mob/living/carbon/target)
if(isnull(organpath) || isnull(target))
stack_trace("passed a null path or mob to 'should_external_organ_apply_to'")
return FALSE

var/datum/bodypart_overlay/mutant/bodypart_overlay = initial(organpath.bodypart_overlay)
var/feature_key = !isnull(bodypart_overlay) && initial(bodypart_overlay.feature_key)
if(isnull(feature_key))
return TRUE

if(target.dna.features[feature_key] != SPRITE_ACCESSORY_NONE)
return TRUE
return FALSE

///Update our features after something changed our appearance
/obj/item/organ/external/proc/mutate_feature(features, mob/living/carbon/human/human)
if(!dna_block)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions monkestation/code/datums/quirks/neutral_quirks/anime.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
var/datum/species/species = quirk_holder.has_dna()?.species
if(species)
for(var/obj/item/organ/external/organ_path as anything in anime_list)
if (!should_external_organ_apply_to(organ_path, quirk_holder))
continue
//Load a persons preferences from DNA
var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path)
new_organ.Insert(quirk_holder, special = TRUE, drop_if_replaced = FALSE)
Expand All @@ -32,4 +34,6 @@

/datum/quirk/anime/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species)
for(var/obj/item/organ/external/organ_path as anything in anime_list)
if (!should_external_organ_apply_to(organ_path, quirk_holder))
continue
new_species.external_organs |= organ_path
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,20 @@

/datum/preference/choiced/goblin_ears/apply_to_human(mob/living/carbon/human/target, value)
target.dna.features["goblin_ears"] = value

/datum/preference/choiced/goblin_nose
savefile_key = "feature_goblin_nose"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_FEATURES
main_feature_name = "Goblin Nose"
should_generate_icons = TRUE

/datum/preference/choiced/goblin_nose/init_possible_values()
return possible_values_for_sprite_accessory_list_for_body_part(
GLOB.goblin_nose_list,
"goblin_nose",
list("ADJ"),
)

/datum/preference/choiced/goblin_nose/apply_to_human(mob/living/carbon/human/target, value)
target.dna.features["goblin_nose"] = value
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,32 @@
/datum/sprite_accessory/goblin_ears/long
name = "Long"
icon_state = "long"

/datum/sprite_accessory/goblin_nose
icon = 'monkestation/icons/mob/species/goblin/goblin_nose.dmi'
palette = /datum/color_palette/generic_colors
palette_key = MUTANT_COLOR

/datum/sprite_accessory/goblin_nose/none
name = "None"
icon_state = "none"

/datum/sprite_accessory/goblin_nose/button
name = "Button"
icon_state = "button"

/datum/sprite_accessory/goblin_nose/liar
name = "Liar"
icon_state = "liar"

/datum/sprite_accessory/goblin_nose/sniffer
name = "Sniffer"
icon_state = "sniffer"

/datum/sprite_accessory/goblin_nose/hook
name = "Hook"
icon_state = "hook"

/datum/sprite_accessory/goblin_nose/wobble
name = "Wobble"
icon_state = "wobble"
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID
external_organs = list(
/obj/item/organ/external/goblin_ears = "long",
/obj/item/organ/external/goblin_nose = "small",
)
meat = /obj/item/food/meat/steak
mutanttongue = /obj/item/organ/internal/tongue/goblin
Expand Down
2 changes: 1 addition & 1 deletion monkestation/code/modules/pissing/bladder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
name = "bladder"
desc = "This is where the pee is stored"

icon = 'monkestation/icons/obj/organs.dmi'
icon = 'monkestation/icons/obj/medical/organs/organs.dmi'
icon_state = "bladder"

zone = BODY_ZONE_PRECISE_GROIN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,29 @@

/datum/bodypart_overlay/mutant/goblin_ears/can_draw_on_bodypart(mob/living/carbon/human/human)
return TRUE

/obj/item/organ/external/goblin_nose
name = "goblin nose"
desc = "It doesn't actually let you smell better."
icon_state = "goblin_nose"
icon = 'monkestation/icons/obj/medical/organs/organs.dmi'

preference = "feature_goblin_nose"
zone = BODY_ZONE_HEAD
slot = ORGAN_SLOT_EXTERNAL_SNOUT

use_mob_sprite_as_obj_sprite = TRUE
bodypart_overlay = /datum/bodypart_overlay/mutant/goblin_nose

/datum/bodypart_overlay/mutant/goblin_nose
layers = EXTERNAL_ADJACENT | EXTERNAL_FRONT
feature_key = "goblin_nose"

/datum/bodypart_overlay/mutant/goblin_nose/get_global_feature_list()
return GLOB.goblin_nose_list

/datum/bodypart_overlay/mutant/goblin_nose/get_base_icon_state()
return sprite_datum.icon_state

/datum/bodypart_overlay/mutant/goblin_nose/can_draw_on_bodypart(mob/living/carbon/human/human)
return TRUE
Binary file not shown.
Binary file modified monkestation/icons/obj/medical/organs/organs.dmi
Binary file not shown.
Binary file removed monkestation/icons/obj/organs.dmi
Binary file not shown.

0 comments on commit 7e89d5e

Please sign in to comment.