diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index c46a75e4ac8..227256f4956 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -78,38 +78,40 @@ #define ALIEN_BODYPART "alien" #define LARVA_BODYPART "larva" -//Bodytype defines for how things can be worn, surgery, and other misc things. +//Bodytype defines for surgery, and other misc things. ///The limb is organic. #define BODYTYPE_ORGANIC (1<<0) ///The limb is robotic. #define BODYTYPE_ROBOTIC (1<<1) -///The limb fits the human mold. This is not meant to be literal, if the sprite "fits" on a human, it is "humanoid", regardless of origin. -#define BODYTYPE_HUMANOID (1<<2) -///The limb fits the monkey mold. -#define BODYTYPE_MONKEY (1<<3) -///The limb is digitigrade. -#define BODYTYPE_DIGITIGRADE (1<<4) -///The limb is snouted. -#define BODYTYPE_SNOUTED (1<<5) ///A placeholder bodytype for xeno larva, so their limbs cannot be attached to anything. -#define BODYTYPE_LARVA_PLACEHOLDER (1<<6) +#define BODYTYPE_LARVA_PLACEHOLDER (1<<2) ///The limb is from a xenomorph. -#define BODYTYPE_ALIEN (1<<7) +#define BODYTYPE_ALIEN (1<<3) ///The limb is from a golem -#define BODYTYPE_GOLEM (1<<8) +#define BODYTYPE_GOLEM (1<<4) // NOVA EDIT ADDITION ///The limb fits a modular custom shape -#define BODYTYPE_CUSTOM (1<<9) +#define BODYSHAPE_CUSTOM (1<<9) ///The limb fits a taur body -#define BODYTYPE_TAUR (1<<10) +#define BODYSHAPE_TAUR (1<<10) ///The limb causes shoes to no longer be displayed, useful for taurs. -#define BODYTYPE_HIDE_SHOES (1<<11) +#define BODYSHAPE_HIDE_SHOES (1<<11) ///The limb causes glasses and hats to be drawn on layers 5 and 4 respectively. Currently used for snouts with the (Top) suffix, which are drawn on layer 6 and would normally cover facewear -#define BODYTYPE_ALT_FACEWEAR_LAYER (1<<12) +#define BODYSHAPE_ALT_FACEWEAR_LAYER (1<<12) // NOVA EDIT END -#define BODYTYPE_BIOSCRAMBLE_COMPATIBLE (BODYTYPE_HUMANOID | BODYTYPE_MONKEY | BODYTYPE_ALIEN) -#define BODYTYPE_CAN_BE_BIOSCRAMBLED(bodytype) (!(bodytype & BODYTYPE_ROBOTIC) && (bodytype & BODYTYPE_BIOSCRAMBLE_COMPATIBLE)) +// Bodyshape defines for how things can be worn, i.e., what "shape" the mob sprite is +///The limb fits the human mold. This is not meant to be literal, if the sprite "fits" on a human, it is "humanoid", regardless of origin. +#define BODYSHAPE_HUMANOID (1<<0) +///The limb fits the monkey mold. +#define BODYSHAPE_MONKEY (1<<1) +///The limb is digitigrade. +#define BODYSHAPE_DIGITIGRADE (1<<2) +///The limb is snouted. +#define BODYSHAPE_SNOUTED (1<<3) + +#define BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE (BODYTYPE_ROBOTIC | BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_GOLEM) +#define BODYTYPE_CAN_BE_BIOSCRAMBLED(bodytype) (!(bodytype & BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE)) // Defines for Species IDs. Used to refer to the name of a species, for things like bodypart names or species preferences. #define SPECIES_ABDUCTOR "abductor" diff --git a/code/__DEFINES/~nova_defines/antag_optin_defines.dm b/code/__DEFINES/~nova_defines/antag_optin_defines.dm new file mode 100644 index 00000000000..50e750053b9 --- /dev/null +++ b/code/__DEFINES/~nova_defines/antag_optin_defines.dm @@ -0,0 +1,45 @@ +//defines for antag opt in objective checking +//objectives check for all players with a value equal or greater than the 'threat' level of an objective then pick from that list +//command + sec roles are always opted in regardless of opt in status + +/// For temporary or otherwise 'inconvenient' objectives like kidnapping or theft +#define OPT_IN_YES_TEMP 1 +/// Cool with being killed or otherwise occupied but not removed from the round +#define OPT_IN_YES_KILL 2 +/// Fine with being round removed. +#define OPT_IN_YES_ROUND_REMOVE 3 + +#define OPT_IN_YES_TEMP_STRING "Yes - Temporary/Inconvenience" +#define OPT_IN_YES_KILL_STRING "Yes - Kill" +#define OPT_IN_YES_ROUND_REMOVE_STRING "Yes - Round Remove" +#define OPT_IN_NOT_TARGET_STRING "No" + +/// Assoc list of stringified opt_in_## define to the front-end string to show users as a representation of the setting. +GLOBAL_LIST_INIT(antag_opt_in_strings, list( + "0" = OPT_IN_NOT_TARGET_STRING, + "1" = OPT_IN_YES_TEMP_STRING, + "2" = OPT_IN_YES_KILL_STRING, + "3" = OPT_IN_YES_ROUND_REMOVE_STRING, +)) + +/// Assoc list of stringified opt_in_## define to the color associated with it. +GLOBAL_LIST_INIT(antag_opt_in_colors, list( + OPT_IN_NOT_TARGET_STRING = COLOR_GRAY, + OPT_IN_YES_TEMP_STRING = COLOR_EMERALD, + OPT_IN_YES_KILL_STRING = COLOR_ORANGE, + OPT_IN_YES_ROUND_REMOVE_STRING = COLOR_RED +)) + +/// Prefers not to be a target. Will still be a potential target if playing sec or command. +#define OPT_IN_NOT_TARGET 0 + +/// The minimum opt-in level for people playing sec. +#define SECURITY_OPT_IN_LEVEL OPT_IN_YES_KILL +/// The minimum opt-in level for people playing command. +#define COMMAND_OPT_IN_LEVEL OPT_IN_YES_KILL + +/// The default opt in level for preferences and mindless mobs. +#define OPT_IN_DEFAULT_LEVEL OPT_IN_NOT_TARGET + +/// If the player has any non-ghost role antags enabled, they are forced to use a minimum of this. +#define OPT_IN_ANTAG_ENABLED_LEVEL OPT_IN_YES_TEMP diff --git a/code/__DEFINES/~nova_defines/jobs.dm b/code/__DEFINES/~nova_defines/jobs.dm index 7aa6486c9d5..a8cc61a9cf7 100644 --- a/code/__DEFINES/~nova_defines/jobs.dm +++ b/code/__DEFINES/~nova_defines/jobs.dm @@ -6,9 +6,11 @@ #define JOB_UNAVAILABLE_FLAVOUR (JOB_UNAVAILABLE_LANGUAGE + 1) #define JOB_UNAVAILABLE_AUGMENT (JOB_UNAVAILABLE_FLAVOUR + 1) -#define SEC_RESTRICTED_QUIRKS "Blind" = TRUE, "Brain Tumor" = TRUE, "Deaf" = TRUE, "Paraplegic" = TRUE, "Hemiplegic" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Pacifist" = TRUE, "No Guns" = TRUE, "Illiterate" = TRUE, "Nerve Stapled" = TRUE -#define HEAD_RESTRICTED_QUIRKS "Blind" = TRUE, "Deaf" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Brain Tumor" = TRUE, "Illiterate" = TRUE +#define SEC_RESTRICTED_QUIRKS "Blind" = TRUE, "Brain Tumor" = TRUE, "Deaf" = TRUE, "Paraplegic" = TRUE, "Hemiplegic" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Pacifist" = TRUE, "No Guns" = TRUE, "Illiterate" = TRUE, "Nerve Stapled" = TRUE, "Underworld Connections" = TRUE +#define HEAD_RESTRICTED_QUIRKS "Blind" = TRUE, "Deaf" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Brain Tumor" = TRUE, "Illiterate" = TRUE, "Underworld Connections" = TRUE +#define HEAD_RESTRICTED_QUIRKS_QM "Blind" = TRUE, "Deaf" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Brain Tumor" = TRUE, "Illiterate" = TRUE #define GUARD_RESTRICTED_QUIRKS "Blind" = TRUE, "Deaf" = TRUE, "Foreigner" = TRUE, "Pacifist" = TRUE, "Nerve Stapled" = TRUE +#define PRISONER_RESTRICTED_QUIRKS "Underworld Connections" = TRUE #define RESTRICTED_QUIRKS_EXCEPTIONS list("Mute" = "Signer") diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index a6a888e07b9..83eb942c2ad 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -378,10 +378,6 @@ DEFINE_BITFIELD(reaction_flags, list( DEFINE_BITFIELD(bodytype, list( "BODYTYPE_ORGANIC" = BODYTYPE_ORGANIC, "BODYTYPE_ROBOTIC" = BODYTYPE_ROBOTIC, - "BODYTYPE_HUMANOID" = BODYTYPE_HUMANOID, - "BODYTYPE_MONKEY" = BODYTYPE_MONKEY, - "BODYTYPE_DIGITIGRADE" = BODYTYPE_DIGITIGRADE, - "BODYTYPE_SNOUTED" = BODYTYPE_SNOUTED, "BODYTYPE_LARVA_PLACEHOLDER" = BODYTYPE_LARVA_PLACEHOLDER, "BODYTYPE_ALIEN" = BODYTYPE_ALIEN, "BODYTYPE_GOLEM" = BODYTYPE_GOLEM, @@ -390,18 +386,34 @@ DEFINE_BITFIELD(bodytype, list( DEFINE_BITFIELD(acceptable_bodytype, list( "BODYTYPE_ORGANIC" = BODYTYPE_ORGANIC, "BODYTYPE_ROBOTIC" = BODYTYPE_ROBOTIC, - "BODYTYPE_HUMANOID" = BODYTYPE_HUMANOID, - "BODYTYPE_MONKEY" = BODYTYPE_MONKEY, - "BODYTYPE_DIGITIGRADE" = BODYTYPE_DIGITIGRADE, - "BODYTYPE_SNOUTED" = BODYTYPE_SNOUTED, "BODYTYPE_LARVA_PLACEHOLDER" = BODYTYPE_LARVA_PLACEHOLDER, "BODYTYPE_ALIEN" = BODYTYPE_ALIEN, "BODYTYPE_GOLEM" = BODYTYPE_GOLEM, +)) + +DEFINE_BITFIELD(bodyshape, list( + "BODYSHAPE_HUMANOID" = BODYSHAPE_HUMANOID, + "BODYSHAPE_MONKEY" = BODYSHAPE_MONKEY, + "BODYSHAPE_DIGITIGRADE" = BODYSHAPE_DIGITIGRADE, + "BODYSHAPE_SNOUTED" = BODYSHAPE_SNOUTED, + // NOVA EDIT ADDITION - customization + "BODYSHAPE__CUSTOM" = BODYSHAPE_CUSTOM, + "BODYSHAPE__TAUR" = BODYSHAPE_TAUR, + "BODYSHAPE__HIDE_SHOES" = BODYSHAPE_HIDE_SHOES, + "BODYSHAPE__ALT_FACEWEAR_LAYER" = BODYSHAPE_ALT_FACEWEAR_LAYER, + // NOVA EDIT END +)) + +DEFINE_BITFIELD(acceptable_bodyshape, list( + "BODYSHAPE_HUMANOID" = BODYSHAPE_HUMANOID, + "BODYSHAPE_MONKEY" = BODYSHAPE_MONKEY, + "BODYSHAPE_DIGITIGRADE" = BODYSHAPE_DIGITIGRADE, + "BODYSHAPE_SNOUTED" = BODYSHAPE_SNOUTED, // NOVA EDIT ADDITION - customization - "BODYTYPE_CUSTOM" = BODYTYPE_CUSTOM, - "BODYTYPE_TAUR" = BODYTYPE_TAUR, - "BODYTYPE_HIDE_SHOES" = BODYTYPE_HIDE_SHOES, - "BODYTYPE_ALT_FACEWEAR_LAYER" = BODYTYPE_ALT_FACEWEAR_LAYER, + "BODYSHAPE__CUSTOM" = BODYSHAPE_CUSTOM, + "BODYSHAPE__TAUR" = BODYSHAPE_TAUR, + "BODYSHAPE__HIDE_SHOES" = BODYSHAPE_HIDE_SHOES, + "BODYSHAPE__ALT_FACEWEAR_LAYER" = BODYSHAPE_ALT_FACEWEAR_LAYER, // NOVA EDIT END )) diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm index 036236b0a91..79e47cb3b3d 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm @@ -942,12 +942,16 @@ /datum/dynamic_ruleset/midround/from_ghosts/paradox_clone/proc/find_original() var/list/possible_targets = list() + var/opt_in_disabled = CONFIG_GET(flag/disable_antag_opt_in_preferences) // NOVA EDIT ADDITION - ANTAG OPT-IN for(var/mob/living/carbon/human/player in GLOB.player_list) if(!player.client || !player.mind || player.stat) continue if(!(player.mind.assigned_role.job_flags & JOB_CREW_MEMBER)) continue - possible_targets += player + // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + Antag Optin + if (!opt_in_disabled && player.mind?.get_effective_opt_in_level() < OPT_IN_YES_ROUND_REMOVE) + continue + // NOVA EDIT ADDITION END if(possible_targets.len) return pick(possible_targets) diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index 4ae9272e970..25efd8695dc 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -33,6 +33,9 @@ SUBSYSTEM_DEF(materials) new /datum/stack_recipe("Carving block", /obj/structure/carving_block, 5, time = 3 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, applies_mats = TRUE, category = CAT_STRUCTURE), ) + ///A list of dimensional themes used by the dimensional anomaly and other things, most of which require materials to function. + var/list/datum/dimension_theme/dimensional_themes + ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) /datum/controller/subsystem/materials/proc/InitializeMaterials() materials = list() @@ -47,6 +50,8 @@ SUBSYSTEM_DEF(materials) continue // Do not initialize at mapload InitializeMaterial(list(mat_type)) + dimensional_themes = init_subtypes_w_path_keys(/datum/dimension_theme) + /** Creates and caches a material datum. * * Arugments: diff --git a/code/datums/brain_damage/creepy_trauma.dm b/code/datums/brain_damage/creepy_trauma.dm index b056ddfb8de..11283588543 100644 --- a/code/datums/brain_damage/creepy_trauma.dm +++ b/code/datums/brain_damage/creepy_trauma.dm @@ -131,15 +131,18 @@ var/list/special_pool = list() //The special list, for quirk-based var/chosen_victim //The obsession target + var/opt_in_disabled = CONFIG_GET(flag/disable_antag_opt_in_preferences) // NOVA EDIT ADDITION - ANTAG OPT-IN for(var/mob/player as anything in GLOB.player_list)//prevents crew members falling in love with nuke ops they never met, and other annoying hijinks if(!player.client || !player.mind || isnewplayer(player) || player.stat == DEAD || isbrain(player) || player == owner) continue if(!(player.mind.assigned_role.job_flags & JOB_CREW_MEMBER)) continue - // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + Antag Optin if(SSticker.IsRoundInProgress() && istype(get_area(player), /area/centcom/interlink)) continue - // NOVA EDIT END + if (!opt_in_disabled && player.mind?.get_effective_opt_in_level() < OPT_IN_YES_KILL) + continue + // NOVA EDIT ADDITION END viable_minds += player.mind for(var/datum/mind/possible_target as anything in viable_minds) if(possible_target != owner && ishuman(possible_target.current)) diff --git a/code/datums/components/creamed.dm b/code/datums/components/creamed.dm index d1c76b4759d..be536bb792d 100644 --- a/code/datums/components/creamed.dm +++ b/code/datums/components/creamed.dm @@ -39,9 +39,9 @@ GLOBAL_LIST_INIT(creamable, typecacheof(list( qdel(src) return bodypart_overlay = new() - if(carbon_parent.bodytype & BODYTYPE_SNOUTED) //stupid, but external organ bodytypes are not stored on the limb + if(carbon_parent.bodyshape & BODYSHAPE_SNOUTED) //stupid, but external organ bodytypes are not stored on the limb bodypart_overlay.icon_state = "creampie_lizard" - else if(my_head.bodytype & BODYTYPE_MONKEY) + else if(my_head.bodyshape & BODYSHAPE_MONKEY) bodypart_overlay.icon_state = "creampie_monkey" else bodypart_overlay.icon_state = "creampie_human" diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index f8a2cbede01..7c7deb058f2 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -157,6 +157,7 @@ GLOBAL_LIST_EMPTY(objectives) //NOVA EDIT ADDITION var/datum/mind/O = I if(O.late_joiner) try_target_late_joiners = TRUE + var/opt_in_disabled = CONFIG_GET(flag/disable_antag_opt_in_preferences) // NOVA EDIT ADDITION - ANTAG OPT-IN for(var/datum/mind/possible_target in get_crewmember_minds()) if(possible_target in owners) continue @@ -166,6 +167,10 @@ GLOBAL_LIST_EMPTY(objectives) //NOVA EDIT ADDITION continue if(!is_valid_target(possible_target)) continue + // NOVA EDIT ADDITION START - Antag Opt In + if (!opt_in_disabled && !opt_in_valid(possible_target)) + continue + // NOVA EDIT ADDITION END possible_targets += possible_target if(try_target_late_joiners) var/list/all_possible_targets = possible_targets.Copy() @@ -871,7 +876,15 @@ GLOBAL_LIST_EMPTY(possible_items) /datum/objective/destroy/find_target(dupe_search_range, list/blacklist) var/list/possible_targets = active_ais(TRUE) possible_targets -= blacklist - var/mob/living/silicon/ai/target_ai = pick(possible_targets) + //var/mob/living/silicon/ai/target_ai = pick(possible_targets) // NOVA EDIT REMOVAL - Uses the below loop + // NOVA EDIT ADDITION BEGIN - ANTAG OPTIN + var/mob/living/silicon/ai/target_ai + var/opt_in_disabled = CONFIG_GET(flag/disable_antag_opt_in_preferences) // NOVA EDIT ADDITION - ANTAG OPT-IN + for (var/mob/living/silicon/ai/possible_target as anything in shuffle(possible_targets)) + if (!opt_in_disabled && !opt_in_valid(possible_target)) + continue + target_ai = possible_target + // NOVA EDIT ADDITION END target = target_ai.mind update_explanation_text() return target diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 9f803020b55..ebe24b44974 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -584,8 +584,6 @@ qdel(src) -<<<<<<< HEAD -======= #define DIMENSION_CHOICE_RANDOM "None/Randomized" /obj/item/bombcore/dimensional @@ -650,7 +648,6 @@ #undef DIMENSION_CHOICE_RANDOM ->>>>>>> beb979d19ac ([MIRROR] [NO GBP] Fixing the multi-dimensional bomb payload (#1209)) ///Syndicate Detonator (aka the big red button)/// /obj/item/syndicatedetonator diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm index 9aea9dfea6a..16dd5bafcfa 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm @@ -21,6 +21,11 @@ animate(src, transform = matrix()*0.85, time = 3, loop = -1) animate(transform = matrix(), time = 3, loop = -1) +/obj/effect/anomaly/dimensional/Destroy() + theme = null + target_turfs = null + return ..() + /obj/effect/anomaly/dimensional/anomalyEffect(seconds_per_tick) . = ..() transmute_area() @@ -36,8 +41,7 @@ return var/turf/affected_turf = target_turfs[1] - new /obj/effect/temp_visual/transmute_tile_flash(affected_turf) - theme.apply_theme(affected_turf) + theme.apply_theme(affected_turf, show_effect = TRUE) target_turfs -= affected_turf /** @@ -47,7 +51,7 @@ /obj/effect/anomaly/dimensional/proc/prepare_area(new_theme_path) if (!new_theme_path) new_theme_path = pick(subtypesof(/datum/dimension_theme)) - theme = new new_theme_path() + theme = SSmaterials.dimensional_themes[new_theme_path] apply_theme_icon() target_turfs = list() diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm index 16408ea9ce6..c6190a0d84a 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm @@ -1,4 +1,3 @@ - /** * Datum which describes a theme and replaces turfs and objects in specified locations to match that theme */ @@ -44,12 +43,16 @@ * * Arguments * * affected_turf - Turf to transform. + * * skip_sound - If the sound shouldn't be played. + * * show_effect - if the temp visual effect should be shown. */ -/datum/dimension_theme/proc/apply_theme(turf/affected_turf, skip_sound = FALSE) +/datum/dimension_theme/proc/apply_theme(turf/affected_turf, skip_sound = FALSE, show_effect = FALSE) if (!replace_turf(affected_turf)) return if (!skip_sound) playsound(affected_turf, sound, 100, TRUE) + if(show_effect) + new /obj/effect/temp_visual/transmute_tile_flash(affected_turf) for (var/obj/object in affected_turf) replace_object(object) if (length(random_spawns) && prob(random_spawn_chance) && !affected_turf.is_blocked_turf(exclude_mobs = TRUE)) @@ -250,7 +253,7 @@ /datum/dimension_theme/radioactive name = "Radioactive" icon = 'icons/obj/ore.dmi' - icon_state = "Uranium ore" + icon_state = "uranium" material = /datum/material/uranium sound = 'sound/items/welder.ogg' @@ -353,7 +356,14 @@ name = "Fancy" icon = 'icons/obj/clothing/head/costume.dmi' icon_state = "fancycrown" + replace_floors = null replace_walls = /turf/closed/wall/mineral/wood/nonmetal + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/comfy = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), + ) + ///cooldown for changing carpets, It's kinda dull to always use the same one, but we also can't make it too random. + COOLDOWN_DECLARE(carpet_switch_cd) #define FANCY_CARPETS list(\ /turf/open/floor/eighties, \ @@ -369,14 +379,12 @@ /turf/open/floor/carpet/royalblack, \ /turf/open/floor/carpet/royalblue,) -/datum/dimension_theme/fancy/New() - . = ..() - replace_floors = list(pick(FANCY_CARPETS) = 1) - replace_objs = list( - /obj/structure/chair = list(/obj/structure/chair/comfy = 1), - /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), - /obj/structure/table/wood = list(pick(subtypesof(/obj/structure/table/wood/fancy)) = 1), - ) +/datum/dimension_theme/fancy/apply_theme(turf/affected_turf, skip_sound = FALSE, show_effect = FALSE) + if(COOLDOWN_FINISHED(src, carpet_switch_cd)) + replace_floors = list(pick(FANCY_CARPETS) = 1) + replace_objs[/obj/structure/table/wood] = list(pick(subtypesof(/obj/structure/table/wood/fancy)) = 1) + COOLDOWN_START(src, carpet_switch_cd, 90 SECONDS) + return ..() #undef FANCY_CARPETS diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 7ad2b14448c..1f3ac272d6f 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -90,8 +90,8 @@ chemical_cost = 1000 dna_cost = CHANGELING_POWER_UNOBTAINABLE - var/helmet_type = /obj/item - var/suit_type = /obj/item + var/helmet_type = null + var/suit_type = null var/suit_name_simple = " " var/helmet_name_simple = " " var/recharge_slowdown = 0 @@ -125,10 +125,14 @@ if(!ishuman(user) || !changeling) return 1 var/mob/living/carbon/human/H = user + if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type)) - H.visible_message(span_warning("[H] casts off [H.p_their()] [suit_name_simple]!"), span_warning("We cast off our [suit_name_simple]."), span_hear("You hear the organic matter ripping and tearing!")) - H.temporarilyRemoveItemFromInventory(H.head, TRUE) //The qdel on dropped() takes care of it - H.temporarilyRemoveItemFromInventory(H.wear_suit, TRUE) + var/name_to_use = (isnull(suit_type) ? helmet_name_simple : suit_name_simple) + H.visible_message(span_warning("[H] casts off [H.p_their()] [name_to_use]!"), span_warning("We cast off our [name_to_use]."), span_hear("You hear the organic matter ripping and tearing!")) + if(!isnull(helmet_type)) + H.temporarilyRemoveItemFromInventory(H.head, TRUE) //The qdel on dropped() takes care of it + if(!isnull(suit_type)) + H.temporarilyRemoveItemFromInventory(H.wear_suit, TRUE) H.update_worn_oversuit() H.update_worn_head() H.update_body_parts() @@ -141,18 +145,19 @@ return 1 /datum/action/changeling/suit/sting_action(mob/living/carbon/human/user) - if(!user.canUnEquip(user.wear_suit)) + if(!user.canUnEquip(user.wear_suit) && !isnull(suit_type)) user.balloon_alert(user, "body occupied!") return - if(!user.canUnEquip(user.head)) + if(!user.canUnEquip(user.head) && !isnull(helmet_type)) user.balloon_alert(user, "head occupied!") return ..() - user.dropItemToGround(user.head) - user.dropItemToGround(user.wear_suit) - - user.equip_to_slot_if_possible(new suit_type(user), ITEM_SLOT_OCLOTHING, 1, 1, 1) - user.equip_to_slot_if_possible(new helmet_type(user), ITEM_SLOT_HEAD, 1, 1, 1) + if(!isnull(suit_type)) + user.dropItemToGround(user.wear_suit) + user.equip_to_slot_if_possible(new suit_type(user), ITEM_SLOT_OCLOTHING, 1, 1, 1) + if(!isnull(helmet_type)) + user.dropItemToGround(user.head) + user.equip_to_slot_if_possible(new helmet_type(user), ITEM_SLOT_HEAD, 1, 1, 1) var/datum/antagonist/changeling/changeling = IS_CHANGELING(user) changeling.chem_recharge_slowdown += recharge_slowdown @@ -582,3 +587,130 @@ /obj/item/clothing/head/helmet/changeling/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) + +/datum/action/changeling/suit/hive_head + name = "Hive Head" + desc = "We coat our head in a waxy outing coating similar to a bee hive which can be used to manufacture bees to attack our enemies. Costs 15 chemicals." + helptext = "While the hive head does not provide much in the ways of armor, it does allow the user to send bees out to attack targets. Reagents can poured inside the hive to cause all bees released to inject said reagents." + button_icon_state = "hive_head" + chemical_cost = 15 + dna_cost = 2 + req_human = FALSE + blood_on_castoff = TRUE + + helmet_type = /obj/item/clothing/head/helmet/changeling_hivehead + helmet_name_simple = "hive head" + +/obj/item/clothing/head/helmet/changeling_hivehead + name = "hive head" + desc = "A strange, waxy outer coating covering your head. Gives you tinnitus." + icon_state = "hivehead" + inhand_icon_state = null + flash_protect = FLASH_PROTECTION_FLASH + item_flags = DROPDEL + armor_type = /datum/armor/changeling_hivehead + flags_inv = HIDEEARS|HIDEHAIR|HIDEEYES|HIDEFACIALHAIR|HIDEFACE|HIDESNOUT + actions_types = list(/datum/action/cooldown/hivehead_spawn_minions) + ///Does this hive head hold reagents? + var/holds_reagents = TRUE + +/obj/item/clothing/head/helmet/changeling_hivehead/Initialize(mapload) + . = ..() + if(holds_reagents) + create_reagents(50, REFILLABLE) + +/datum/armor/changeling_hivehead + melee = 10 + bullet = 10 + laser = 10 + energy = 10 + bio = 50 + +/obj/item/clothing/head/helmet/changeling_hivehead/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) + +/obj/item/clothing/head/helmet/changeling_hivehead/attackby(obj/item/attacking_item, mob/user, params) + . = ..() + if(!istype(attacking_item, /obj/item/organ/internal/monster_core/regenerative_core/legion) || !holds_reagents) + return + visible_message(span_boldwarning("As [user] shoves [attacking_item] into [src], [src] begins to mutate.")) + var/mob/living/carbon/wearer = loc + playsound(wearer, 'sound/effects/attackblob.ogg', 60, TRUE) + wearer.temporarilyRemoveItemFromInventory(wearer.head, TRUE) + wearer.equip_to_slot_if_possible(new /obj/item/clothing/head/helmet/changeling_hivehead/legion(wearer), ITEM_SLOT_HEAD, 1, 1, 1) + qdel(attacking_item) + + +/datum/action/cooldown/hivehead_spawn_minions + name = "Release Bees" + desc = "Release a group of bees to attack all other lifeforms." + background_icon_state = "bg_demon" + overlay_icon_state = "bg_demon_border" + button_icon = 'icons/mob/simple/bees.dmi' + button_icon_state = "queen_item" + cooldown_time = 30 SECONDS + ///The mob we're going to spawn + var/spawn_type = /mob/living/basic/bee + ///How many are we going to spawn + var/spawn_count = 6 + ///How long our summoned mobs last for + var/spawn_lifespan = 25 SECONDS + +/datum/action/cooldown/hivehead_spawn_minions/PreActivate(atom/target) + if(owner.movement_type & VENTCRAWLING) + owner.balloon_alert(owner, "unavailable here") + return + . = ..() + +/datum/action/cooldown/hivehead_spawn_minions/Activate(atom/target) + . = ..() + do_tell() + var/spawns = spawn_count + if(owner.stat >= HARD_CRIT) + spawns = 1 + for(var/i in 1 to spawns) + var/mob/living/basic/summoned_minion = new spawn_type(get_turf(owner)) + summoned_minion.faction = list("[REF(owner)]") + if(spawn_lifespan != 0 SECONDS) + QDEL_IN(summoned_minion, spawn_lifespan) + minion_additional_changes(summoned_minion) + +///Our tell that we're using this ability. Usually a sound and a visible message.area +/datum/action/cooldown/hivehead_spawn_minions/proc/do_tell() + owner.visible_message(span_warning("[owner]'s head begins to buzz as bees begin to pour out!"), span_warning("We release the bees."), span_hear("You hear a loud buzzing sound!")) + playsound(owner, 'sound/creatures/bee_swarm.ogg', 60, TRUE) + +///Stuff we want to do to our minions. This is in its own proc so subtypes can override this behaviour. +/datum/action/cooldown/hivehead_spawn_minions/proc/minion_additional_changes(mob/living/basic/minion) + var/mob/living/basic/bee/summoned_bee = minion + var/mob/living/carbon/wearer = owner + if(istype(summoned_bee) && length(wearer.head.reagents.reagent_list)) + summoned_bee.assign_reagent(pick(wearer.head.reagents.reagent_list)) + +/obj/item/clothing/head/helmet/changeling_hivehead/legion + name = "legion hive head" + desc = "A strange, boney coating covering your head with a fleshy inside. Surprisingly comfortable." + icon_state = "hivehead_legion" + actions_types = list(/datum/action/cooldown/hivehead_spawn_minions/legion) + holds_reagents = FALSE + +/datum/action/cooldown/hivehead_spawn_minions/legion + name = "Release Legion" + desc = "Release a group of legion to attack all other lifeforms." + button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + button_icon_state = "legion_head" + cooldown_time = 15 SECONDS + spawn_type = /mob/living/basic/legion_brood + spawn_count = 4 + //Legion heads go away by themselves, we don't have to handle that + spawn_lifespan = 0 SECONDS + +/datum/action/cooldown/hivehead_spawn_minions/legion/do_tell() + owner.visible_message(span_warning("[owner]'s head begins to shake as legion begin to pour out!"), span_warning("We release the legion."), span_hear("You hear a loud squishing sound!")) + playsound(owner, 'sound/effects/attackblob.ogg', 60, TRUE) + +/datum/action/cooldown/hivehead_spawn_minions/legion/minion_additional_changes(mob/living/basic/minion) + var/mob/living/basic/legion_brood/brood = minion + if (istype(brood)) + brood.assign_creator(owner, FALSE) diff --git a/code/modules/antagonists/cult/cult_objectives.dm b/code/modules/antagonists/cult/cult_objectives.dm index 7da5d095661..42312eea2dd 100644 --- a/code/modules/antagonists/cult/cult_objectives.dm +++ b/code/modules/antagonists/cult/cult_objectives.dm @@ -19,19 +19,24 @@ return var/datum/team/cult/cult = team var/list/target_candidates = list() + var/opt_in_disabled = CONFIG_GET(flag/disable_antag_opt_in_preferences) // NOVA EDIT ADDITION - ANTAG OPT-IN for(var/mob/living/carbon/human/player in GLOB.player_list) - // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + Antag Optin if(SSticker.IsRoundInProgress() && istype(get_area(player), /area/centcom/interlink)) continue + if (!opt_in_disabled && !opt_in_valid(player)) + continue // NOVA EDIT END if(player.mind && !player.mind.has_antag_datum(/datum/antagonist/cult) && !is_convertable_to_cult(player) && player.stat != DEAD) target_candidates += player.mind if(target_candidates.len == 0) message_admins("Cult Sacrifice: Could not find unconvertible target, checking for convertible target.") for(var/mob/living/carbon/human/player in GLOB.player_list) - // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + // NOVA EDIT ADDITION START - Players in the interlink can't be obsession targets + Antag Optin if(SSticker.IsRoundInProgress() && istype(get_area(player), /area/centcom/interlink)) continue + if (!opt_in_disabled && !opt_in_valid(player)) + continue // NOVA EDIT END if(player.mind && !player.mind.has_antag_datum(/datum/antagonist/cult) && player.stat != DEAD) target_candidates += player.mind diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm index 797d754ea0b..f515b3e25bd 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm @@ -113,6 +113,10 @@ continue if(possible_target.current.stat == DEAD) continue + // NOVA EDIT ADDITION BEGIN - Antag opt-in (Only security and command can be targetted) + if (!possible_target.assigned_role?.heretic_sac_target) + continue + // NOVA EDIT ADDITION END valid_targets += possible_target @@ -142,12 +146,14 @@ valid_targets -= sec_mind break + /* NOVA EDIT REMOVAL -- Antag Opt In (Only sec and command may be targetted) // Third target, someone in their department. for(var/datum/mind/department_mind as anything in shuffle(valid_targets)) if(department_mind.assigned_role?.departments_bitflags & user.mind.assigned_role?.departments_bitflags) final_targets += department_mind valid_targets -= department_mind break + */ // NOVA EDIT REMOVAL END // Now grab completely random targets until we'll full var/target_sanity = 0 diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm index ee16daae7d5..052074a30b3 100644 --- a/code/modules/cargo/markets/market_items/weapons.dm +++ b/code/modules/cargo/markets/market_items/weapons.dm @@ -73,3 +73,12 @@ price_max = CARGO_CRATE_VALUE * 4 stock_max = 1 availability_prob = 75 + +/datum/market_item/weapon/dimensional_bomb + name = "Multi-Dimensional Bomb Core" + desc = "A special bomb core, one of a kind, for all your 'terraforming gone wrong' purposes." + item = /obj/item/bombcore/dimensional + price_min = CARGO_CRATE_VALUE * 40 + price_max = CARGO_CRATE_VALUE * 50 + stock_max = 1 + availability_prob = 15 diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 008c99e9e5f..8d4c948d99a 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -152,7 +152,7 @@ /* NOVA EDIT REMOVAL - This breaks jumpsuit adjustment. Plus, we don't support it. if((supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) && ishuman(user)) var/mob/living/carbon/human/wearer = user - if(wearer.bodytype & BODYTYPE_DIGITIGRADE) + if(wearer.bodyshape & BODYSHAPE_DIGITIGRADE) adjusted = DIGITIGRADE_STYLE update_appearance() */ // NOVA EDIT END diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index c0a56dc7a67..70bc9113150 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -312,6 +312,15 @@ info += span_boldnotice("As this station was initially staffed with a \ [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] \ have been added to your ID card.") + //NOVA EDIT ADDITION BEGIN - ANTAG OPT IN + if (!CONFIG_GET(flag/disable_antag_opt_in_preferences)) + if (isnum(minimum_opt_in_level) && minimum_opt_in_level > OPT_IN_NOT_TARGET) + info += span_bolddanger("This job forces a minimum opt-in setting of [GLOB.antag_opt_in_strings["[minimum_opt_in_level]"]].") + if (heretic_sac_target) + info += span_bolddanger("This job can be sacrificed by heretics.") + if (contractable) + info += span_bolddanger("This job can be targeted by contractors.") + //NOVA EDIT ADDITION END //NOVA EDIT ADDITION START - ALTERNATIVE_JOB_TITLES if(alt_title != title) info += span_warning("Remember that alternate titles are purely for flavor and roleplay.") diff --git a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm index 66c0d129962..5510b81679e 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm @@ -25,10 +25,6 @@ response_harm_continuous = "squashes" response_harm_simple = "squash" - mob_size = MOB_SIZE_LARGE - pixel_x = -16 - base_pixel_x = -16 - speed = 1 maxHealth = 10 health = 10 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 147419272a5..5fcfeec8d72 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1045,6 +1045,7 @@ set_usable_hands(usable_hands + 1) synchronize_bodytypes() + synchronize_bodyshapes() ///Proc to hook behavior on bodypart removals. Do not directly call. You're looking for [/obj/item/bodypart/proc/drop_limb()]. /mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart, special) @@ -1071,6 +1072,7 @@ set_usable_hands(usable_hands - 1) synchronize_bodytypes() + synchronize_bodyshapes() ///Updates the bodypart speed modifier based on our bodyparts. /mob/living/carbon/proc/update_bodypart_speed_modifier() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 38571bccdb1..2e2168eca9d 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -118,7 +118,10 @@ var/last_top_offset /// A bitfield of "bodytypes", updated by /obj/item/bodypart/proc/synchronize_bodytypes() - var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC + var/bodytype = BODYTYPE_ORGANIC + + /// A bitfield of "bodyshapes", updated by /obj/item/bodypart/proc/synchronize_bodyshapes() + var/bodyshape = BODYSHAPE_HUMANOID COOLDOWN_DECLARE(bleeding_message_cd) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 85a6b06a2d3..13d7b37e6b8 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -42,7 +42,7 @@ for(var/obj/item/organ/organ as anything in organs) if((drop_bitflags & DROP_BRAIN) && istype(organ, /obj/item/organ/internal/brain)) - if(drop_bitflags & DROP_BODYPARTS) + if(drop_bitflags & DROP_BODYPARTS && (check_zone(organ.zone) != BODY_ZONE_CHEST)) // NOVA EDIT CHANGE - sYNTH BRAINS - ORIGINAL: if(drop_bitflags & DROP_BODYPARTS) continue // the head will drop, so the brain should stay inside organ.Remove(src) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 504ceabe915..82ec5a6f311 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -693,7 +693,7 @@ GLOBAL_LIST_EMPTY(features_by_species) working_shirt.pixel_y += height_offset standing += working_shirt - if(species_human.socks && species_human.num_legs >= 2 && !(species_human.bodytype & BODYTYPE_DIGITIGRADE)) + if(species_human.socks && species_human.num_legs >= 2 && !(species_human.bodyshape & BODYSHAPE_DIGITIGRADE)) var/datum/sprite_accessory/socks/socks = GLOB.socks_list[species_human.socks] if(socks) standing += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER) @@ -936,7 +936,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(H.num_legs < 2) return FALSE /* NOVA EDIT REMOVAL - if((H.bodytype & BODYTYPE_DIGITIGRADE) && !(I.item_flags & IGNORE_DIGITIGRADE)) + if((H.bodyshape & BODYSHAPE_DIGITIGRADE) && !(I.item_flags & IGNORE_DIGITIGRADE)) if(!(I.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON))) if(!disable_warning) to_chat(H, span_warning("The footwear around here isn't compatible with your feet!")) @@ -968,7 +968,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return equip_delay_self_check(I, H, bypass_equip_delay_self) if(ITEM_SLOT_ICLOTHING) var/obj/item/bodypart/chest = H.get_bodypart(BODY_ZONE_CHEST) - if(chest && (chest.bodytype & BODYTYPE_MONKEY)) + if(chest && (chest.bodyshape & BODYSHAPE_MONKEY)) if(!(I.supports_variations_flags & CLOTHING_MONKEY_VARIATION)) if(!disable_warning) to_chat(H, span_warning("[I] doesn't fit your [chest.name]!")) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 735d6f83cc1..c628b9ddcb8 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -505,6 +505,12 @@ if(erp_status_pref && !CONFIG_GET(flag/disable_erp_preferences)) . += span_notice("ERP STATUS: [erp_status_pref]") + if (!CONFIG_GET(flag/disable_antag_opt_in_preferences)) + var/opt_in_status = mind?.get_effective_opt_in_level() + if (!isnull(opt_in_status)) + var/stringified_optin = GLOB.antag_opt_in_strings["[opt_in_status]"] + . += span_notice("Antag Opt-in Status: [stringified_optin]") + //Temporary flavor text addition: if(temporary_flavor_text) if(length_char(temporary_flavor_text) < TEMPORARY_FLAVOR_PREVIEW_LIMIT) diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 3ea41f2302b..802146d8435 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -93,29 +93,29 @@ There are several things that need to be remembered: var/mutable_appearance/uniform_overlay //This is how non-humanoid clothing works. You check if the mob has the right bodyflag, and the clothing has the corresponding clothing flag. - //handled_by_bodytype is used to track whether or not we successfully used an alternate sprite. It's set to TRUE to ease up on copy-paste. + //handled_by_bodyshape is used to track whether or not we successfully used an alternate sprite. It's set to TRUE to ease up on copy-paste. //icon_file MUST be set to null by default, or it causes issues. - //handled_by_bodytype MUST be set to FALSE under the if(!icon_exists()) statement, or everything breaks. - //"override_file = handled_by_bodytype ? icon_file : null" MUST be added to the arguments of build_worn_icon() + //handled_by_bodyshape MUST be set to FALSE under the if(!icon_exists()) statement, or everything breaks. + //"override_file = handled_by_bodyshape ? icon_file : null" MUST be added to the arguments of build_worn_icon() //Friendly reminder that icon_exists(file, state, scream = TRUE) is your friend when debugging this code. - var/handled_by_bodytype = TRUE + var/handled_by_bodyshape = TRUE var/icon_file var/woman var/digi // NOVA EDIT ADDITION - Digi female gender shaping var/female_sprite_flags = uniform.female_sprite_flags // NOVA EDIT ADDITION - Digi female gender shaping var/mutant_styles = NONE // NOVA EDIT ADDITON - mutant styles to pass down to build_worn_icon. //BEGIN SPECIES HANDLING - if((bodytype & BODYTYPE_MONKEY) && (uniform.supports_variations_flags & CLOTHING_MONKEY_VARIATION)) + if((bodyshape & BODYSHAPE_MONKEY) && (uniform.supports_variations_flags & CLOTHING_MONKEY_VARIATION)) icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_UNIFORM, w_uniform, src) // NOVA EDIT CHANGE - ORIGINAL: icon_file = MONKEY_UNIFORM_FILE - else if((bodytype & BODYTYPE_DIGITIGRADE) && (uniform.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) + else if((bodyshape & BODYSHAPE_DIGITIGRADE) && (uniform.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) icon_file = uniform.worn_icon_digi || DIGITIGRADE_UNIFORM_FILE // NOVA EDIT CHANGE - ORIGINAL: icon_file = DIGITIGRADE_UNIFORM_FILE digi = TRUE // NOVA EDIT ADDITION - Digi female gender shaping // NOVA EDIT ADDITION - birbs - else if(bodytype & BODYTYPE_CUSTOM) + else if(bodyshape & BODYSHAPE_CUSTOM) icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_UNIFORM, w_uniform, src) // Might have to refactor how this works eventually, maybe. // NOVA EDIT END //Female sprites have lower priority than digitigrade sprites - if(dna.species.sexes && (bodytype & BODYTYPE_HUMANOID) && physique == FEMALE && !(female_sprite_flags & NO_FEMALE_UNIFORM)) //Agggggggghhhhh // NOVA EDIT CHANGE - ORIGINAL: else if(dna.species.sexes && (bodytype & BODYTYPE_HUMANOID) && physique == FEMALE && !(uniform.female_sprite_flags & NO_FEMALE_UNIFORM)) + if(dna.species.sexes && (bodyshape & BODYSHAPE_HUMANOID) && physique == FEMALE && !(female_sprite_flags & NO_FEMALE_UNIFORM)) // NOVA EDIT CHANGE - ORIGINAL: else if(dna.species.sexes && (bodyshape & BODYSHAPE_HUMANOID) && physique == FEMALE && !(uniform.female_sprite_flags & NO_FEMALE_UNIFORM)) //Agggggggghhhhh woman = TRUE // NOVA EDIT ADDITION START - Digi female gender shaping if(digi) @@ -127,10 +127,10 @@ There are several things that need to be remembered: if(!icon_exists(icon_file, RESOLVE_ICON_STATE(uniform))) icon_file = DEFAULT_UNIFORM_FILE - handled_by_bodytype = FALSE + handled_by_bodyshape = FALSE // NOVA EDIT ADDITION START - Taur-friendly suits! - if(bodytype & BODYTYPE_TAUR) + if(bodyshape & BODYSHAPE_TAUR) if(istype(uniform) && uniform.gets_cropped_on_taurs) mutant_styles |= get_taur_mode() // NOVA EDIT END @@ -142,7 +142,7 @@ There are several things that need to be remembered: isinhands = FALSE, female_uniform = woman ? female_sprite_flags : null, // NOVA EDIT CHANGE - Digi female gender shaping - ORIGINAL: female_uniform = woman ? uniform.female_sprite_flags : null, override_state = target_overlay, - override_file = handled_by_bodytype ? icon_file : null, + override_file = handled_by_bodyshape ? icon_file : null, mutant_styles = mutant_styles, // NOVA EDIT ADDITION - Taur-friendly uniforms! ) @@ -209,7 +209,7 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_GLOVES, gloves, src) if(species_icon_file) icon_file = species_icon_file @@ -252,7 +252,7 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_GLASSES, glasses, src) if(species_icon_file) icon_file = species_icon_file @@ -291,7 +291,7 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_EARS, ears, src) if(species_icon_file) icon_file = species_icon_file @@ -325,13 +325,13 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_NECK, wear_neck, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE //On the off-chance we have a neck item that has to move around or cover the muzzle, it ALSO gets worn_icon_muzzled compatiability - if((bodytype & BODYTYPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION) && worn_item.worn_icon_muzzled) + if((bodyshape & BODYSHAPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION) && worn_item.worn_icon_muzzled) var/snout_icon_file = worn_item.worn_icon_muzzled if(snout_icon_file && icon_exists(snout_icon_file, RESOLVE_ICON_STATE(worn_item))) icon_file = snout_icon_file @@ -371,17 +371,17 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION START var/mutant_override = FALSE - if((bodytype & BODYTYPE_DIGITIGRADE) && (worn_item.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) + if((bodyshape & BODYSHAPE_DIGITIGRADE) && (worn_item.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) var/obj/item/bodypart/leg = src.get_bodypart(BODY_ZONE_L_LEG) - if(leg.limb_id == "digitigrade" || leg.bodytype & BODYTYPE_DIGITIGRADE)//Snowflakey and bad. But it makes it look consistent. + if(leg.limb_id == "digitigrade" || leg.bodyshape & BODYSHAPE_DIGITIGRADE)//Snowflakey and bad. But it makes it look consistent. icon_file = worn_item.worn_icon_digi || DIGITIGRADE_SHOES_FILE // NOVA EDIT CHANGE mutant_override = TRUE // NOVA EDIT ADDITION - if(!mutant_override && bodytype & BODYTYPE_CUSTOM) + if(!mutant_override && bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_SHOES, shoes, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE - if(bodytype & BODYTYPE_HIDE_SHOES) + if(bodyshape & BODYSHAPE_HIDE_SHOES) return // We just don't want shoes that float if we're not displaying legs (useful for taurs, for now) // NOVA EDIT END @@ -444,12 +444,12 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION - This needs to be refactored. var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_HEAD, head, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE - if((icon_file == 'icons/mob/clothing/head/default.dmi') && (bodytype & BODYTYPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION)) + if((icon_file == 'icons/mob/clothing/head/default.dmi') && (bodyshape & BODYSHAPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION)) var/snout_icon_file = worn_item.worn_icon_muzzled || SNOUTED_HEAD_FILE if(snout_icon_file && icon_exists(snout_icon_file, RESOLVE_ICON_STATE(worn_item))) icon_file = snout_icon_file @@ -486,7 +486,7 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_BELT, belt, src) if(species_icon_file) icon_file = species_icon_file @@ -521,18 +521,18 @@ There are several things that need to be remembered: var/mutant_styles = NONE //More currently unused digitigrade handling - if(bodytype & BODYTYPE_DIGITIGRADE) + if(bodyshape & BODYSHAPE_DIGITIGRADE) if(worn_item.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) icon_file = worn_item.worn_icon_digi || DIGITIGRADE_SUIT_FILE // NOVA EDIT CHANGE mutant_override = TRUE - if(!mutant_override && bodytype & BODYTYPE_CUSTOM) + if(!mutant_override && bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_SUIT, wear_suit, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE - if(bodytype & BODYTYPE_TAUR) + if(bodyshape & BODYSHAPE_TAUR) var/obj/item/clothing/suit/worn_suit = wear_suit if(istype(worn_suit) && worn_suit.gets_cropped_on_taurs) mutant_styles |= get_taur_mode() @@ -595,12 +595,12 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MASK, wear_mask, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE - if((icon_file == 'icons/mob/clothing/mask.dmi') && (bodytype & BODYTYPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION)) + if((icon_file == 'icons/mob/clothing/mask.dmi') && (bodyshape & BODYSHAPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION)) var/snout_icon_file = worn_item.worn_icon_muzzled || SNOUTED_MASK_FILE if(snout_icon_file && icon_exists(snout_icon_file, RESOLVE_ICON_STATE(worn_item))) icon_file = snout_icon_file @@ -633,7 +633,7 @@ There are several things that need to be remembered: // NOVA EDIT ADDITION var/mutant_override = FALSE - if(bodytype & BODYTYPE_CUSTOM) + if(bodyshape & BODYSHAPE_CUSTOM) var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MISC, back, src) if(species_icon_file) icon_file = species_icon_file diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index ee0450f4075..92abcffd186 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -19,7 +19,7 @@ death(TRUE) ghostize() - spill_organs(drop_bitflags) + spill_organs(issynthetic(src) ? drop_bitflags|DROP_BRAIN : drop_bitflags) // NOVA EDIT CHANGE - Synths always drop brains - ORIGINAL: spill_organs(drop_bitflags) if(drop_bitflags & DROP_BODYPARTS) spread_bodyparts(drop_bitflags) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 9253448563b..ac9031f59c3 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -356,8 +356,7 @@ /obj/machinery/anomalous_crystal/theme_warp/Initialize(mapload) . = ..() - var/terrain_type = pick(subtypesof(/datum/dimension_theme)) - terrain_theme = new terrain_type() + terrain_theme = SSmaterials.dimensional_themes[pick(subtypesof(/datum/dimension_theme))] observer_desc = "This crystal changes the area around it to match the theme of \"[terrain_theme.name]\"." /obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method) @@ -372,7 +371,7 @@ return TRUE /obj/machinery/anomalous_crystal/theme_warp/Destroy() - QDEL_NULL(terrain_theme) + terrain_theme = null converted_areas.Cut() return ..() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 83d4200bb65..5b66789ad21 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -34,8 +34,10 @@ * Set to BIO_STANDARD_UNJOINTED because most species have both flesh bone and blood in their limbs. */ var/biological_state = BIO_STANDARD_UNJOINTED - ///A bitfield of bodytypes for clothing, surgery, and misc information - var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC + ///A bitfield of bodytypes for surgery, and misc information + var/bodytype = BODYTYPE_ORGANIC + ///A bitfield of bodyshapes for clothing and other sprite information + var/bodyshape = BODYSHAPE_HUMANOID ///Defines when a bodypart should not be changed. Example: BP_BLOCK_CHANGE_SPECIES prevents the limb from being overwritten on species gain var/change_exempt_flags = NONE ///Random flags that describe this bodypart diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index dc107e973da..4b9bac87d16 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -274,7 +274,7 @@ return FALSE var/obj/item/bodypart/chest/mob_chest = new_limb_owner.get_bodypart(BODY_ZONE_CHEST) - if(mob_chest && !(mob_chest.acceptable_bodytype & bodytype) && !special) + if(mob_chest && !(mob_chest.acceptable_bodytype & bodytype) && !(mob_chest.acceptable_bodyshape & bodyshape) && !(mob_chest.acceptable_bodyshape & bodyshape) && !special) return FALSE return TRUE diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index eb9a9f56df5..1defeecafe6 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -234,7 +234,7 @@ husk_type = "monkey" icon_state = "default_monkey_head" limb_id = SPECIES_MONKEY - bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_MONKEY should_draw_greyscale = FALSE dmg_overlay_type = SPECIES_MONKEY is_dimorphic = FALSE @@ -251,7 +251,8 @@ px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE max_damage = LIMB_MAX_HP_ALIEN_CORE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_HUMANOID /obj/item/bodypart/head/larva icon = 'icons/mob/human/species/alien/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 52671b5fbc1..126bd3db33a 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -179,6 +179,16 @@ bodytype = all_limb_flags +/// Makes sure that the owner's bodyshape flags match the flags of all of it's parts and organs +/mob/living/carbon/proc/synchronize_bodyshapes() + var/all_limb_flags = NONE + for(var/obj/item/bodypart/limb as anything in bodyparts) + for(var/obj/item/organ/external/ext_organ in limb) + all_limb_flags |= ext_organ.external_bodyshapes + all_limb_flags |= limb.bodyshape + + bodyshape = all_limb_flags + /proc/skintone2hex(skin_tone) . = 0 switch(skin_tone) diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index e13fef576ec..ead03aa0f70 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -13,8 +13,10 @@ grind_results = null wound_resistance = 10 bodypart_trait_source = CHEST_TRAIT + ///The bodyshape(s) allowed to attach to this chest. + var/acceptable_bodyshape = BODYSHAPE_HUMANOID ///The bodytype(s) allowed to attach to this chest. - var/acceptable_bodytype = BODYTYPE_HUMANOID + var/acceptable_bodytype = ALL var/obj/item/cavity_item @@ -78,8 +80,8 @@ should_draw_greyscale = FALSE is_dimorphic = FALSE wound_resistance = -10 - bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC - acceptable_bodytype = BODYTYPE_MONKEY + bodyshape = BODYSHAPE_MONKEY + acceptable_bodyshape = BODYSHAPE_MONKEY dmg_overlay_type = SPECIES_MONKEY /obj/item/bodypart/chest/alien @@ -87,12 +89,13 @@ icon_static = 'icons/mob/human/species/alien/bodyparts.dmi' icon_state = "alien_chest" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_HUMANOID is_dimorphic = FALSE should_draw_greyscale = FALSE bodypart_flags = BODYPART_UNREMOVABLE max_damage = LIMB_MAX_HP_ALIEN_CORE - acceptable_bodytype = BODYTYPE_HUMANOID + acceptable_bodyshape = BODYSHAPE_HUMANOID wing_types = NONE /obj/item/bodypart/chest/larva @@ -245,7 +248,7 @@ icon_state = "default_monkey_l_arm" limb_id = SPECIES_MONKEY should_draw_greyscale = FALSE - bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_MONKEY wound_resistance = -10 px_x = -5 px_y = -3 @@ -260,7 +263,8 @@ icon_static = 'icons/mob/human/species/alien/bodyparts.dmi' icon_state = "alien_l_arm" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_HUMANOID px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -341,7 +345,7 @@ husk_type = "monkey" icon_state = "default_monkey_r_arm" limb_id = SPECIES_MONKEY - bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_MONKEY should_draw_greyscale = FALSE wound_resistance = -10 px_x = 5 @@ -357,7 +361,8 @@ icon_static = 'icons/mob/human/species/alien/bodyparts.dmi' icon_state = "alien_r_arm" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_HUMANOID px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -457,7 +462,7 @@ icon_state = "default_monkey_l_leg" limb_id = SPECIES_MONKEY should_draw_greyscale = FALSE - bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_MONKEY wound_resistance = -10 px_y = 4 dmg_overlay_type = SPECIES_MONKEY @@ -471,7 +476,8 @@ icon_static = 'icons/mob/human/species/alien/bodyparts.dmi' icon_state = "alien_l_leg" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_HUMANOID px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -547,7 +553,7 @@ icon_state = "default_monkey_r_leg" limb_id = SPECIES_MONKEY should_draw_greyscale = FALSE - bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_MONKEY wound_resistance = -10 px_y = 4 dmg_overlay_type = SPECIES_MONKEY @@ -561,7 +567,8 @@ icon_static = 'icons/mob/human/species/alien/bodyparts.dmi' icon_state = "alien_r_leg" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_HUMANOID px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm index 33b32778754..cdd92df7b88 100644 --- a/code/modules/surgery/bodyparts/robot_bodyparts.dm +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -23,7 +23,8 @@ icon_state = "borg_l_arm" is_dimorphic = FALSE should_draw_greyscale = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC + bodytype = BODYTYPE_ROBOTIC + bodyshape = BODYSHAPE_HUMANOID change_exempt_flags = BP_BLOCK_CHANGE_SPECIES dmg_overlay_type = "robotic" @@ -56,7 +57,8 @@ icon_state = "borg_r_arm" is_dimorphic = FALSE should_draw_greyscale = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC + bodytype = BODYTYPE_ROBOTIC + bodyshape = BODYSHAPE_HUMANOID change_exempt_flags = BP_BLOCK_CHANGE_SPECIES dmg_overlay_type = "robotic" @@ -90,7 +92,8 @@ icon_state = "borg_l_leg" is_dimorphic = FALSE should_draw_greyscale = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC + bodytype = BODYTYPE_ROBOTIC + bodyshape = BODYSHAPE_HUMANOID change_exempt_flags = BP_BLOCK_CHANGE_SPECIES dmg_overlay_type = "robotic" @@ -137,7 +140,8 @@ icon_state = "borg_r_leg" is_dimorphic = FALSE should_draw_greyscale = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC + bodytype = BODYTYPE_ROBOTIC + bodyshape = BODYSHAPE_HUMANOID change_exempt_flags = BP_BLOCK_CHANGE_SPECIES dmg_overlay_type = "robotic" @@ -183,7 +187,8 @@ icon_state = "borg_chest" is_dimorphic = FALSE should_draw_greyscale = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC + bodytype = BODYTYPE_ROBOTIC + bodyshape = BODYSHAPE_HUMANOID change_exempt_flags = BP_BLOCK_CHANGE_SPECIES dmg_overlay_type = "robotic" @@ -361,7 +366,8 @@ icon_state = "borg_head" is_dimorphic = FALSE should_draw_greyscale = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC + bodytype = BODYTYPE_ROBOTIC + bodyshape = BODYSHAPE_HUMANOID change_exempt_flags = BP_BLOCK_CHANGE_SPECIES dmg_overlay_type = "robotic" diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index 6cd42665d45..ec60375c8d1 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -46,7 +46,7 @@ /obj/item/bodypart/leg/left/digitigrade icon_greyscale = 'icons/mob/human/species/lizard/bodyparts.dmi' limb_id = BODYPART_ID_DIGITIGRADE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodyshape = BODYSHAPE_HUMANOID | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/left/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE) . = ..() @@ -72,7 +72,7 @@ /obj/item/bodypart/leg/right/digitigrade icon_greyscale = 'icons/mob/human/species/lizard/bodyparts.dmi' limb_id = BODYPART_ID_DIGITIGRADE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodyshape = BODYSHAPE_HUMANOID | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/right/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE) . = ..() diff --git a/code/modules/surgery/organs/external/_external_organ.dm b/code/modules/surgery/organs/external/_external_organ.dm index 23b74ef9b4e..645caa630d7 100644 --- a/code/modules/surgery/organs/external/_external_organ.dm +++ b/code/modules/surgery/organs/external/_external_organ.dm @@ -25,6 +25,8 @@ var/use_mob_sprite_as_obj_sprite = FALSE ///Does this organ have any bodytypes to pass to it's bodypart_owner? var/external_bodytypes = NONE + ///Does this organ have any bodyshapes to pass to it's bodypart_owner? + var/external_bodyshapes = NONE ///Which flags does a 'modification tool' need to have to restyle us, if it all possible (located in code/_DEFINES/mobs) var/restyle_flags = NONE @@ -87,12 +89,15 @@ if(external_bodytypes) receiver.synchronize_bodytypes() + if(external_bodyshapes) + receiver.synchronize_bodyshapes() receiver.update_body_parts() /obj/item/organ/external/mob_remove(mob/living/carbon/organ_owner, special, moving) if(!special) organ_owner.synchronize_bodytypes() + organ_owner.synchronize_bodyshapes() organ_owner.update_body_parts() return ..() @@ -223,7 +228,7 @@ slot = ORGAN_SLOT_EXTERNAL_SNOUT preference = "feature_lizard_snout" - external_bodytypes = BODYTYPE_SNOUTED + external_bodyshapes = BODYSHAPE_SNOUTED //dna_block = DNA_SNOUT_BLOCK // NOVA EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_FLESH diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index 4b285d161bb..818c7a788d9 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -55,7 +55,7 @@ if(ishuman(target)) var/mob/living/carbon/human/human_target = target var/obj/item/bodypart/chest/target_chest = human_target.get_bodypart(BODY_ZONE_CHEST) - if(!(bodypart_to_attach.bodytype & target_chest.acceptable_bodytype)) + if((!(bodypart_to_attach.bodyshape & target_chest.acceptable_bodyshape)) && (!(bodypart_to_attach.bodytype & target_chest.acceptable_bodytype))) to_chat(user, span_warning("[bodypart_to_attach] doesn't match the patient's morphology.")) return SURGERY_STEP_FAIL if(bodypart_to_attach.check_for_frankenstein(target)) diff --git a/config/nova/config_nova.txt b/config/nova/config_nova.txt index deb7f925ea8..31f620888d9 100644 --- a/config/nova/config_nova.txt +++ b/config/nova/config_nova.txt @@ -146,3 +146,6 @@ VETERAN_LEGACY_SYSTEM ## How much time arrivals shuttle should stay at station after its engines recharged before returning to interlink. In deciseconds. 150 - 15 seconds. 0 - disables autoreturn. ARRIVALS_WAIT 150 + +## Uncomment to completely disable the opt-in system, which is a system that forces objectives to only roll on individuals who consent to it. +#DISABLE_ANTAG_OPT_IN_PREFERENCES diff --git a/html/changelogs/AutoChangeLog-pr-1891.yml b/html/changelogs/AutoChangeLog-pr-1891.yml new file mode 100644 index 00000000000..0c0adbabea4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1891.yml @@ -0,0 +1,4 @@ +author: "nikothedude" +delete-after: True +changes: + - rscadd: "Added antagonist opt-in! Brave crewmates wishing to be the target of nefarious evildoers now may indicate this desire in their character preferences." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2130.yml b/html/changelogs/AutoChangeLog-pr-2130.yml new file mode 100644 index 00000000000..d65d654f6d1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2130.yml @@ -0,0 +1,4 @@ +author: "13spacemen" +delete-after: True +changes: + - refactor: "Bodytypes to do with character sprite shape now have their own bodyshape var, all sprite handling is done with bodyshape and not bodytype anymore" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2137.yml b/html/changelogs/AutoChangeLog-pr-2137.yml deleted file mode 100644 index ab75566b57e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2137.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "13spacemen" -delete-after: True -changes: - - bugfix: "Blood overlays on items no longer leak onto other objects" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2138.yml b/html/changelogs/AutoChangeLog-pr-2138.yml deleted file mode 100644 index 853a56fb32e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2138.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Ben10Omintrix" -delete-after: True -changes: - - bugfix: "fixes pokemon ai still being active when inside the pokeball" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2144.yml b/html/changelogs/AutoChangeLog-pr-2144.yml deleted file mode 100644 index fdd83662978..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2144.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Melbert" -delete-after: True -changes: - - bugfix: "The Paddy's Claw should be properly unusable in situations which it should be properly unusable." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2145.yml b/html/changelogs/AutoChangeLog-pr-2145.yml deleted file mode 100644 index 9ed33509a78..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2145.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "yooriss" -delete-after: True -changes: - - rscadd: "The Entombed quirk has been added, allowing characters to start off with a permanently unremovable low-end MODsuit stuck to their back slot. Letting the suit's charge run low will eventually kill you, and the quirk has special interactions with both Ethereals and Plasmamen!" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2146.yml b/html/changelogs/AutoChangeLog-pr-2146.yml deleted file mode 100644 index 80cd9c987c3..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2146.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Absolucy" -delete-after: True -changes: - - qol: "Constructs now reuse the victim's mind instead of just moving their client" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2147.yml b/html/changelogs/AutoChangeLog-pr-2147.yml deleted file mode 100644 index a12ae26b8d3..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2147.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "SyncIt21" -delete-after: True -changes: - - qol: "adds examines & screentips for building & deconstructing both machine & computer frames." - - qol: "Adding a circuitboard from a rped to n computer frame will automatically screw it in place like before." - - code_imp: "merged procs for computer & machine frames. autodocs them where possible." - - code_imp: "moved code for machine frame into its own file." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2148.yml b/html/changelogs/AutoChangeLog-pr-2148.yml deleted file mode 100644 index 5157e6ceeb2..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2148.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "IndieanaJones" -delete-after: True -changes: - - balance: "Gorillas are faster, stronger, but not bigger too. Note while holding an item, they are the same speed as they were prior." - - balance: "Gorillas now have the understanding of languages as monkeys do." - - balance: "The Gorilla Cube Box for traitors has been replaced with a singular gorilla cube. Due to the aforementioned changes, this singular gorilla should be as scary if not scarier than 3 gorillas were prior." - - balance: " Magillitis Serum Autoinjector now grants the resulting gorilla a slow passive regeneration effect which kicks in after not taking damage for 12 seconds." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2149.yml b/html/changelogs/AutoChangeLog-pr-2149.yml deleted file mode 100644 index 84bf337648e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2149.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TJatPBnJ" -delete-after: True -changes: - - balance: "Power crepes are now finger food" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2150.yml b/html/changelogs/AutoChangeLog-pr-2150.yml deleted file mode 100644 index f8a4bc7cfea..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2150.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SyncIt21" -delete-after: True -changes: - - bugfix: "RCD converts miscellaneous turfs like basalt, sand, beach etc to plating first & not put a wall directly on top of them" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2151.yml b/html/changelogs/AutoChangeLog-pr-2151.yml deleted file mode 100644 index d7c9aa58f9c..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2151.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "mc-oofert" -delete-after: True -changes: - - rscadd: "Added an option to deathmatch loadout dropdown that allows you to pick a random loadout" - - bugfix: "In deathmatch, plasmamen are made humans and the UI supports more players" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2152.yml b/html/changelogs/AutoChangeLog-pr-2152.yml deleted file mode 100644 index c6d7b9e4633..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2152.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "00-Steven" -delete-after: True -changes: - - bugfix: "Newscasters no longer say \"No wanted issue posted. Have a secure day.\" when there is, in fact, an active wanted issue currently posted." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2157.yml b/html/changelogs/AutoChangeLog-pr-2157.yml deleted file mode 100644 index d88f979677a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2157.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Knouli" -delete-after: True -changes: - - balance: "DeForest brand Civil Defense Medical Kits may now be repurposed to carry a limited selection of field-portable cheese rations." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2158.yml b/html/changelogs/AutoChangeLog-pr-2158.yml deleted file mode 100644 index 1e735fde359..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2158.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "00-Steven" -delete-after: True -changes: - - bugfix: "Medical/security records now show an icon based on the registered trim, rather than showing a question mark for records with customized titles." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2163.yml b/html/changelogs/AutoChangeLog-pr-2163.yml deleted file mode 100644 index ab0c85d5fd7..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2163.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "softcerv" -delete-after: True -changes: - - code_imp: "TRAIT_DEAF now works on non-carbon mobs" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2164.yml b/html/changelogs/AutoChangeLog-pr-2164.yml deleted file mode 100644 index 89d09d1d7bc..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2164.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "PapaMichael" -delete-after: True -changes: - - balance: "Fugitive hunters will spawn early if the emergency shuttle is called." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2165.yml b/html/changelogs/AutoChangeLog-pr-2165.yml deleted file mode 100644 index 0acb3c6a1bb..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2165.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "JohnFulpWillard" -delete-after: True -changes: - - qol: "Intelligent monkeys now punch people instead of biting them." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2166.yml b/html/changelogs/AutoChangeLog-pr-2166.yml deleted file mode 100644 index a100278dc54..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2166.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Iamgoofball" -delete-after: True -changes: - - balance: "xenomorph stomachs will no longer destroy items directly, refactored it to use acid_act()" - - bugfix: "fixes xenomorph vore accidentally destroying mobs it wasn't supposed to destroy, im thinking this was modified list in place shenanigans" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2167.yml b/html/changelogs/AutoChangeLog-pr-2167.yml deleted file mode 100644 index fb9957e2adb..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2167.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "LT3" -delete-after: True -changes: - - code_imp: "Tram throwing now breaks grilles consistently" - - code_imp: "Tram malfunction lethality/throw chance are now a multiplier instead of flat value" - - code_imp: "Tram throw chance can be adjusted" - - code_imp: "Unlucky trait is now used in tram throw calculation" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2170.yml b/html/changelogs/AutoChangeLog-pr-2170.yml deleted file mode 100644 index cced53083f0..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2170.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ArcaneMusic" -delete-after: True -changes: - - image: "New sprites for plant grafts!" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2171.yml b/html/changelogs/AutoChangeLog-pr-2171.yml deleted file mode 100644 index 60612d931ef..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2171.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "KingkumaArt" -delete-after: True -changes: - - rscadd: "a list of items called vendor_nocrush that vendors dont deal integrity damage to upon hitting them." - - bugfix: "Makes vending machines no longer crush chairs and conveyors." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2173.yml b/html/changelogs/AutoChangeLog-pr-2173.yml deleted file mode 100644 index 3e42a3e26b6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2173.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Ghommie" -delete-after: True -changes: - - balance: "\"Freshness Jars full of Natural Bait\" is now a goodie and costs 200 credits instead of 2000" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2174.yml b/html/changelogs/AutoChangeLog-pr-2174.yml deleted file mode 100644 index 086180971c5..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2174.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "A.C.M.O." -delete-after: True -changes: - - bugfix: "Fixed the AI hologram's ability to copy the appearance of crew members." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2177.yml b/html/changelogs/AutoChangeLog-pr-2177.yml deleted file mode 100644 index bf9c3e68fa1..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2177.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "mc-oofert" -delete-after: True -changes: - - bugfix: "Grilles dont break by just walking into them under any circumstances" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2180.yml b/html/changelogs/AutoChangeLog-pr-2180.yml deleted file mode 100644 index bd5f7934fc9..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2180.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "necromanceranne" -delete-after: True -changes: - - bugfix: "Being in a Swat Suit appropriately protects you from collisions with a body, rather than the body thrown at you having these protections protecting YOU, the victim of the collision." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2181.yml b/html/changelogs/AutoChangeLog-pr-2181.yml new file mode 100644 index 00000000000..8dc7d10cbad --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2181.yml @@ -0,0 +1,4 @@ +author: "vinylspiders" +delete-after: True +changes: + - bugfix: "synths should now always drop their brains when gibbed" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2182.yml b/html/changelogs/AutoChangeLog-pr-2182.yml deleted file mode 100644 index 6814b22e910..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2182.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SyncIt21" -delete-after: True -changes: - - bugfix: "Cryostylane reaction now has a moderate & not extreme cooling effect. Helps you achieve more pure amounts of Cryostylane" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2183.yml b/html/changelogs/AutoChangeLog-pr-2183.yml deleted file mode 100644 index 8da2a1db267..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2183.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "13spacemen" -delete-after: True -changes: - - bugfix: "You can build material airlocks again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2184.yml b/html/changelogs/AutoChangeLog-pr-2184.yml deleted file mode 100644 index 797744dae8e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2184.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "LT3" -delete-after: True -changes: - - qol: "Airlocks don't flash constantly on engineering override, override/overlay added for fire alarm" - - bugfix: "Airlock lighting should no longer render on top of player characters" - - bugfix: "Airlock emissives no longer overlap firedoors" - - bugfix: "Fixed missing overlays on various airlock types" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2186.yml b/html/changelogs/AutoChangeLog-pr-2186.yml deleted file mode 100644 index 85148425f8b..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2186.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "yooriss" -delete-after: True -changes: - - rscadd: "A new form of emoting is available called 'Do', accessible via the K and Ctrl-K keybinds by default (as well as the 'Do' verb). Do doesn't put your character name first and instead includes it in brackets at the end, so you can use it to write better prose and even narrate things in the environment around you with less clunkiness! Try it out today." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2189.yml b/html/changelogs/AutoChangeLog-pr-2189.yml deleted file mode 100644 index b0db2178347..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2189.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TheVekter" -delete-after: True -changes: - - rscadd: "Added a new law to the Artist lawset in order to encourage Artist AIs to build an audience." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2191.yml b/html/changelogs/AutoChangeLog-pr-2191.yml deleted file mode 100644 index 09158f9debd..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2191.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Melbert" -delete-after: True -changes: - - bugfix: "Fixes grabbing yourself when you tackle someone." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2192.yml b/html/changelogs/AutoChangeLog-pr-2192.yml new file mode 100644 index 00000000000..67763b4fb43 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2192.yml @@ -0,0 +1,5 @@ +author: "IndieanaJones" +delete-after: True +changes: + - rscadd: "New Changeling Ability: Hive Head" + - bugfix: "Fixed bees having an improper sprite offset" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-2195.yml b/html/changelogs/AutoChangeLog-pr-2195.yml deleted file mode 100644 index 57316c6d837..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2195.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TheSmallBlue" -delete-after: True -changes: - - qol: "added an HUD button to go up and down floors" \ No newline at end of file diff --git a/html/changelogs/archive/2024-03.yml b/html/changelogs/archive/2024-03.yml new file mode 100644 index 00000000000..1a02199135c --- /dev/null +++ b/html/changelogs/archive/2024-03.yml @@ -0,0 +1,112 @@ +2024-03-01: + 00-Steven: + - bugfix: Medical/security records now show an icon based on the registered trim, + rather than showing a question mark for records with customized titles. + - bugfix: Newscasters no longer say "No wanted issue posted. Have a secure day." + when there is, in fact, an active wanted issue currently posted. + 13spacemen: + - bugfix: You can build material airlocks again + - bugfix: Blood overlays on items no longer leak onto other objects + A.C.M.O.: + - bugfix: Fixed the AI hologram's ability to copy the appearance of crew members. + Absolucy: + - qol: Constructs now reuse the victim's mind instead of just moving their client + ArcaneMusic: + - image: New sprites for plant grafts! + Ben10Omintrix: + - bugfix: fixes pokemon ai still being active when inside the pokeball + Ghommie: + - balance: '"Freshness Jars full of Natural Bait" is now a goodie and costs 200 + credits instead of 2000' + Iamgoofball: + - balance: xenomorph stomachs will no longer destroy items directly, refactored + it to use acid_act() + - bugfix: fixes xenomorph vore accidentally destroying mobs it wasn't supposed to + destroy, im thinking this was modified list in place shenanigans + IndieanaJones: + - balance: Gorillas are faster, stronger, but not bigger too. Note while holding + an item, they are the same speed as they were prior. + - balance: Gorillas now have the understanding of languages as monkeys do. + - balance: The Gorilla Cube Box for traitors has been replaced with a singular gorilla + cube. Due to the aforementioned changes, this singular gorilla should be as + scary if not scarier than 3 gorillas were prior. + - balance: ' Magillitis Serum Autoinjector now grants the resulting gorilla a slow + passive regeneration effect which kicks in after not taking damage for 12 seconds.' + JohnFulpWillard: + - qol: Intelligent monkeys now punch people instead of biting them. + KingkumaArt: + - rscadd: a list of items called vendor_nocrush that vendors dont deal integrity + damage to upon hitting them. + - bugfix: Makes vending machines no longer crush chairs and conveyors. + Knouli: + - balance: DeForest brand Civil Defense Medical Kits may now be repurposed to carry + a limited selection of field-portable cheese rations. + LT3: + - code_imp: Tram throwing now breaks grilles consistently + - code_imp: Tram malfunction lethality/throw chance are now a multiplier instead + of flat value + - code_imp: Tram throw chance can be adjusted + - code_imp: Unlucky trait is now used in tram throw calculation + - qol: Airlocks don't flash constantly on engineering override, override/overlay + added for fire alarm + - bugfix: Airlock lighting should no longer render on top of player characters + - bugfix: Airlock emissives no longer overlap firedoors + - bugfix: Fixed missing overlays on various airlock types + Melbert: + - bugfix: The Paddy's Claw should be properly unusable in situations which it should + be properly unusable. + - bugfix: Fixes grabbing yourself when you tackle someone. + PapaMichael: + - balance: Fugitive hunters will spawn early if the emergency shuttle is called. + SyncIt21: + - qol: adds examines & screentips for building & deconstructing both machine & computer + frames. + - qol: Adding a circuitboard from a rped to n computer frame will automatically + screw it in place like before. + - code_imp: merged procs for computer & machine frames. autodocs them where possible. + - code_imp: moved code for machine frame into its own file. + - bugfix: RCD converts miscellaneous turfs like basalt, sand, beach etc to plating + first & not put a wall directly on top of them + - bugfix: Cryostylane reaction now has a moderate & not extreme cooling effect. + Helps you achieve more pure amounts of Cryostylane + TJatPBnJ: + - balance: Power crepes are now finger food + TheSmallBlue: + - qol: added an HUD button to go up and down floors + TheVekter: + - rscadd: Added a new law to the Artist lawset in order to encourage Artist AIs + to build an audience. + mc-oofert: + - rscadd: Added an option to deathmatch loadout dropdown that allows you to pick + a random loadout + - bugfix: In deathmatch, plasmamen are made humans and the UI supports more players + - bugfix: Grilles dont break by just walking into them under any circumstances + necromanceranne: + - bugfix: Being in a Swat Suit appropriately protects you from collisions with a + body, rather than the body thrown at you having these protections protecting + YOU, the victim of the collision. + softcerv: + - code_imp: TRAIT_DEAF now works on non-carbon mobs + yooriss: + - qol: 'The telepathy genetics mutation has had significant usability improvements: + it is now point-targeting based, and right-clicking the power allows for quick + resending to the same target, a feature mirrored by the new *treply emote. Telepathy + now also shows runechat messages.' + - rscadd: The Telepathic quirk has been added, allowing characters to start with + an unremovable (or activated) telepathy mutation. + - rscadd: A new form of emoting is available called 'Do', accessible via the K and + Ctrl-K keybinds by default (as well as the 'Do' verb). Do doesn't put your character + name first and instead includes it in brackets at the end, so you can use it + to write better prose and even narrate things in the environment around you + with less clunkiness! Try it out today. + - rscadd: The Underworld Connections quirk has been added, allowing dodgy characters + (including silicons!) to gain access to exploitable information at roundstart. + Non-silicons also receive a fully customizable black market uplink, too. + - qol: Prices at the galactic Black Market have now fallen drastically to be more + in line with general cargo costs, give or take, and should now be vastly more + affordable for most people. Pick up one and order some spuriously legal things + for you and your friends today! + - rscadd: The Entombed quirk has been added, allowing characters to start off with + a permanently unremovable low-end MODsuit stuck to their back slot. Letting + the suit's charge run low will eventually kill you, and the quirk has special + interactions with both Ethereals and Plasmamen! diff --git a/icons/mob/actions/actions_changeling.dmi b/icons/mob/actions/actions_changeling.dmi index bb3634a1dde..25a4e10aa57 100644 Binary files a/icons/mob/actions/actions_changeling.dmi and b/icons/mob/actions/actions_changeling.dmi differ diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi index 5b30ae65b8f..49edcf8422f 100644 Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ diff --git a/icons/obj/clothing/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi index d9f02085e73..94d11e6b820 100644 Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ diff --git a/modular_nova/master_files/code/modules/cargo/markets/market_items/weapons.dm b/modular_nova/master_files/code/modules/cargo/markets/market_items/weapons.dm index 40ad5def7a4..64a09914c83 100644 --- a/modular_nova/master_files/code/modules/cargo/markets/market_items/weapons.dm +++ b/modular_nova/master_files/code/modules/cargo/markets/market_items/weapons.dm @@ -6,3 +6,8 @@ price_max = CARGO_CRATE_VALUE * 4 stock_max = 3 availability_prob = 80 + +// Makes this even more expensive +/datum/market_item/weapon/dimensional_bomb + price_min = CARGO_CRATE_VALUE * 180 + price_max = CARGO_CRATE_VALUE * 200 diff --git a/modular_nova/master_files/code/modules/client/preferences/mutant_parts.dm b/modular_nova/master_files/code/modules/client/preferences/mutant_parts.dm index 57c26e4dd37..b7d0f183f41 100644 --- a/modular_nova/master_files/code/modules/client/preferences/mutant_parts.dm +++ b/modular_nova/master_files/code/modules/client/preferences/mutant_parts.dm @@ -168,9 +168,9 @@ return if(.) - our_head.bodytype |= BODYTYPE_SNOUTED + our_head.bodyshape |= BODYSHAPE_SNOUTED else - our_head.bodytype &= ~BODYTYPE_SNOUTED + our_head.bodyshape &= ~BODYSHAPE_SNOUTED target.synchronize_bodytypes() /datum/preference/tri_color/snout diff --git a/modular_nova/master_files/code/modules/clothing/base_clothes.dm b/modular_nova/master_files/code/modules/clothing/base_clothes.dm index fbcdad4e997..f1e1bff17da 100644 --- a/modular_nova/master_files/code/modules/clothing/base_clothes.dm +++ b/modular_nova/master_files/code/modules/clothing/base_clothes.dm @@ -32,7 +32,7 @@ var/greyscale_config_worn_taur_paw var/greyscale_config_worn_taur_hoof - /// Used for BODYTYPE_CUSTOM: Needs to follow this syntax: a list() with the x and y coordinates of the pixel you want to get the color from. Colors are filled in as GAGs values for fallback. + /// Used for BODYSHAPE_CUSTOM: Needs to follow this syntax: a list() with the x and y coordinates of the pixel you want to get the color from. Colors are filled in as GAGs values for fallback. var/list/species_clothing_color_coords[3] /obj/item/clothing/head diff --git a/modular_nova/master_files/code/modules/clothing/glasses/_glasses.dm b/modular_nova/master_files/code/modules/clothing/glasses/_glasses.dm index 4b9ad40e929..b151b366d47 100644 --- a/modular_nova/master_files/code/modules/clothing/glasses/_glasses.dm +++ b/modular_nova/master_files/code/modules/clothing/glasses/_glasses.dm @@ -4,7 +4,7 @@ if(!ishuman(user)) return if(slot & ITEM_SLOT_EYES) - if(!(user.bodytype & BODYTYPE_ALT_FACEWEAR_LAYER)) + if(!(user.bodyshape & BODYSHAPE_ALT_FACEWEAR_LAYER)) return if(!isnull(alternate_worn_layer) && alternate_worn_layer < BODY_FRONT_LAYER) // if the alternate worn layer was already lower than snouts then leave it be return diff --git a/modular_nova/master_files/code/modules/clothing/head/_head.dm b/modular_nova/master_files/code/modules/clothing/head/_head.dm index f022fc99ac8..047abec8cd3 100644 --- a/modular_nova/master_files/code/modules/clothing/head/_head.dm +++ b/modular_nova/master_files/code/modules/clothing/head/_head.dm @@ -9,7 +9,7 @@ if(slot & ITEM_SLOT_HEAD) if(user.ears && (flags_inv & HIDEEARS)) user.update_inv_ears() - if(!(user.bodytype & BODYTYPE_ALT_FACEWEAR_LAYER)) + if(!(user.bodyshape & BODYSHAPE_ALT_FACEWEAR_LAYER)) return if(!isnull(alternate_worn_layer) && alternate_worn_layer < BODY_FRONT_LAYER) // if the alternate worn layer was already lower than snouts then leave it be return diff --git a/modular_nova/master_files/code/modules/clothing/masks/_masks.dm b/modular_nova/master_files/code/modules/clothing/masks/_masks.dm index 46fd2adeeed..8d29816c4fd 100644 --- a/modular_nova/master_files/code/modules/clothing/masks/_masks.dm +++ b/modular_nova/master_files/code/modules/clothing/masks/_masks.dm @@ -4,7 +4,7 @@ if(!ishuman(user)) return if(slot & ITEM_SLOT_MASK) - if(!(user.bodytype & BODYTYPE_ALT_FACEWEAR_LAYER)) + if(!(user.bodyshape & BODYSHAPE_ALT_FACEWEAR_LAYER)) return if(!isnull(alternate_worn_layer) && alternate_worn_layer < BODY_FRONT_LAYER) // if the alternate worn layer was already lower than snouts then leave it be return diff --git a/modular_nova/master_files/code/modules/mob/living/examine_tgui.dm b/modular_nova/master_files/code/modules/mob/living/examine_tgui.dm index 5648dda48d3..de181c91ffc 100644 --- a/modular_nova/master_files/code/modules/mob/living/examine_tgui.dm +++ b/modular_nova/master_files/code/modules/mob/living/examine_tgui.dm @@ -54,19 +54,30 @@ var/custom_species_lore var/obscured var/ooc_notes = "" + var/ideal_antag_optin_status + var/current_antag_optin_status var/headshot = "" // Handle OOC notes first - if(preferences && preferences.read_preference(/datum/preference/toggle/master_erp_preferences)) - var/e_prefs = preferences.read_preference(/datum/preference/choiced/erp_status) - var/e_prefs_nc = preferences.read_preference(/datum/preference/choiced/erp_status_nc) - var/e_prefs_v = preferences.read_preference(/datum/preference/choiced/erp_status_v) - var/e_prefs_mechanical = preferences.read_preference(/datum/preference/choiced/erp_status_mechanics) - ooc_notes += "ERP: [e_prefs]\n" - ooc_notes += "Non-Con: [e_prefs_nc]\n" - ooc_notes += "Vore: [e_prefs_v]\n" - ooc_notes += "ERP Mechanics: [e_prefs_mechanical]\n" - ooc_notes += "\n" + if(preferences) + if(preferences.read_preference(/datum/preference/toggle/master_erp_preferences)) + var/e_prefs = preferences.read_preference(/datum/preference/choiced/erp_status) + var/e_prefs_nc = preferences.read_preference(/datum/preference/choiced/erp_status_nc) + var/e_prefs_v = preferences.read_preference(/datum/preference/choiced/erp_status_v) + var/e_prefs_mechanical = preferences.read_preference(/datum/preference/choiced/erp_status_mechanics) + ooc_notes += "ERP: [e_prefs]\n" + ooc_notes += "Non-Con: [e_prefs_nc]\n" + ooc_notes += "Vore: [e_prefs_v]\n" + ooc_notes += "ERP Mechanics: [e_prefs_mechanical]\n" + ooc_notes += "\n" + + if(!CONFIG_GET(flag/disable_antag_opt_in_preferences)) + var/antag_prefs = holder.mind?.ideal_opt_in_level + var/effective_opt_in_level = holder.mind?.get_effective_opt_in_level() + if(isnull(antag_prefs)) + antag_prefs = preferences.read_preference(/datum/preference/choiced/antag_opt_in_status) + current_antag_optin_status = GLOB.antag_opt_in_strings[num2text(effective_opt_in_level)] + ideal_antag_optin_status = GLOB.antag_opt_in_strings[num2text(antag_prefs)] // Now we handle silicon and/or human, order doesn't really matter // If other variants of mob/living need to be handled at some point, put them here @@ -97,4 +108,14 @@ data["custom_species"] = custom_species data["custom_species_lore"] = custom_species_lore data["headshot"] = headshot + + data["ideal_antag_optin_status"] = ideal_antag_optin_status + data["current_antag_optin_status"] = current_antag_optin_status + return data + +/datum/examine_panel/ui_static_data(mob/user) + var/list/data = list() + + data["opt_in_colors"] = GLOB.antag_opt_in_colors + return data diff --git a/modular_nova/master_files/code/modules/mod/modules/_module.dm b/modular_nova/master_files/code/modules/mod/modules/_module.dm index 36ad7fb64c4..9997e2975cf 100644 --- a/modular_nova/master_files/code/modules/mod/modules/_module.dm +++ b/modular_nova/master_files/code/modules/mod/modules/_module.dm @@ -47,10 +47,10 @@ if(is_module_hidden()) // retracted modules can hide parts that aren't usable when inactive return - if(mod.chestplate && (mod.chestplate.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) && (mod.wearer.bodytype & BODYTYPE_DIGITIGRADE)) + if(mod.chestplate && (mod.chestplate.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) && (mod.wearer.bodyshape & BODYSHAPE_DIGITIGRADE)) suit_supports_variations_flags |= CLOTHING_DIGITIGRADE_VARIATION - if(mod.helmet && (mod.helmet.supports_variations_flags & CLOTHING_SNOUTED_VARIATION) && mod.wearer.bodytype & BODYTYPE_SNOUTED) + if(mod.helmet && (mod.helmet.supports_variations_flags & CLOTHING_SNOUTED_VARIATION) && mod.wearer.bodyshape & BODYSHAPE_SNOUTED) suit_supports_variations_flags |= CLOTHING_SNOUTED_VARIATION is_new_vox = isvoxprimalis(mod.wearer) is_old_vox = isvox(mod.wearer) diff --git a/modular_nova/modules/antag_opt_in/code/antag_optin_config.dm b/modular_nova/modules/antag_opt_in/code/antag_optin_config.dm new file mode 100644 index 00000000000..bff8c325131 --- /dev/null +++ b/modular_nova/modules/antag_opt_in/code/antag_optin_config.dm @@ -0,0 +1,2 @@ +/datum/config_entry/flag/disable_antag_opt_in_preferences + default = FALSE diff --git a/modular_nova/modules/antag_opt_in/code/antag_optin_preferences.dm b/modular_nova/modules/antag_opt_in/code/antag_optin_preferences.dm new file mode 100644 index 00000000000..eb6038e62e8 --- /dev/null +++ b/modular_nova/modules/antag_opt_in/code/antag_optin_preferences.dm @@ -0,0 +1,33 @@ +/datum/preference/choiced/antag_opt_in_status + category = PREFERENCE_CATEGORY_NON_CONTEXTUAL + savefile_identifier = PREFERENCE_CHARACTER + savefile_key = "antag_opt_in_status_pref" + +/datum/preference/choiced/antag_opt_in_status/init_possible_values() + return list(OPT_IN_YES_TEMP, OPT_IN_YES_KILL, OPT_IN_YES_ROUND_REMOVE, OPT_IN_NOT_TARGET) + +/datum/preference/choiced/antag_opt_in_status/create_default_value() + return OPT_IN_DEFAULT_LEVEL + +/datum/preference/choiced/antag_opt_in_status/is_accessible(datum/preferences/preferences) + if (!..(preferences)) + return FALSE + + return !(CONFIG_GET(flag/disable_antag_opt_in_preferences)) + +/datum/preference/choiced/antag_opt_in_status/deserialize(input, datum/preferences/preferences) + if(CONFIG_GET(flag/disable_antag_opt_in_preferences)) + return OPT_IN_DEFAULT_LEVEL + + return ..() + +/datum/preference/choiced/antag_opt_in_status/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return FALSE + +/datum/preference/choiced/antag_opt_in_status/compile_constant_data() + var/list/data = ..() + + // An assoc list of values to display names so we don't show players numbers in their settings! + data[CHOICED_PREFERENCE_DISPLAY_NAMES] = GLOB.antag_opt_in_strings + + return data diff --git a/modular_nova/modules/antag_opt_in/code/job.dm b/modular_nova/modules/antag_opt_in/code/job.dm new file mode 100644 index 00000000000..1eb819d5c99 --- /dev/null +++ b/modular_nova/modules/antag_opt_in/code/job.dm @@ -0,0 +1,72 @@ +/datum/job + /// The minimum antag opt-in any holder of this job must use. If null, will defer to the mind's opt in level. + var/minimum_opt_in_level + /// Can this job be targetted as a heretic sacrifice target? + var/heretic_sac_target + /// Is this job targetable by contractors? + var/contractable + +/// Updates [minimum_opt_in_level] [heretic_sac_target] and [contractable]. +/datum/job/proc/update_opt_in_vars() + if(CONFIG_GET(flag/disable_antag_opt_in_preferences)) + return + + if(isnull(minimum_opt_in_level)) + minimum_opt_in_level = get_initial_opt_in_level() + if(isnull(heretic_sac_target)) + heretic_sac_target = initialize_heretic_target_status() + if(isnull(contractable)) + contractable = initialize_contractable_status() + + update_opt_in_desc_suffix() + +/// Returns this job's initial opt in level, taking into account departmental bitflags. +/datum/job/proc/get_initial_opt_in_level() + if (departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY)) + return SECURITY_OPT_IN_LEVEL + if (departments_bitflags & (DEPARTMENT_BITFLAG_COMMAND)) + return COMMAND_OPT_IN_LEVEL + +/// Determines if this job should be sacrificable by heretics. +/datum/job/proc/initialize_heretic_target_status() + if (departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY | DEPARTMENT_BITFLAG_COMMAND)) + return TRUE + + return FALSE + +/// Determines if this job should be targetable by contractors. +/datum/job/proc/initialize_contractable_status() + if (departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY | DEPARTMENT_BITFLAG_COMMAND)) + return TRUE + + return FALSE + +/// Generates and sets a suffix appended to our description detailing our opt-in variables. +/datum/job/proc/update_opt_in_desc_suffix() + var/list/suffixes = list() + + if (minimum_opt_in_level) + suffixes += " Forces a minimum of [GLOB.antag_opt_in_strings["[minimum_opt_in_level]"]] antag opt-in." + if (contractable) + suffixes += " Targetable by contractors." + if (heretic_sac_target) + suffixes += " Targetable by heretics." + if (length(suffixes)) + var/suffix = jointext(suffixes, "") + set_opt_in_desc_suffix(suffix) + +/// Setter for [new_suffix]. Resets desc then appends the new suffix. +/datum/job/proc/set_opt_in_desc_suffix(new_suffix) + description = initial(description) + + if (new_suffix) + description += new_suffix + +/datum/controller/subsystem/job/SetupOccupations() + . = ..() + + if(CONFIG_GET(flag/disable_antag_opt_in_preferences)) + return + + for(var/datum/job/job as anything in all_occupations) + job.update_opt_in_vars() diff --git a/modular_nova/modules/antag_opt_in/code/mind.dm b/modular_nova/modules/antag_opt_in/code/mind.dm new file mode 100644 index 00000000000..91224664bf5 --- /dev/null +++ b/modular_nova/modules/antag_opt_in/code/mind.dm @@ -0,0 +1,92 @@ +/// If a player has any of these enabled, they are forced to use a minimum of OPT_IN_ANTAG_ENABLED_LEVEL antag optin. Dynamic - checked on the fly, not cached. +GLOBAL_LIST_INIT(optin_forcing_midround_antag_categories, list( + ROLE_CHANGELING_MIDROUND, + ROLE_MALF_MIDROUND, + ROLE_OBSESSED, + ROLE_SLEEPER_AGENT, +)) + +/// If a player has any of these enabled ON SPAWN, they are forced to use a minimum of OPT_IN_ANTAG_ENABLED_LEVEL antag optin for the rest of the round. +GLOBAL_LIST_INIT(optin_forcing_on_spawn_antag_categories, list( + ROLE_BROTHER, + ROLE_CHANGELING, + ROLE_CULTIST, + ROLE_HERETIC, + ROLE_MALF, + ROLE_OPERATIVE, + ROLE_TRAITOR, + ROLE_WIZARD, + ROLE_ASSAULT_OPERATIVE, + ROLE_CLOWN_OPERATIVE, + ROLE_NUCLEAR_OPERATIVE, + ROLE_HERETIC_SMUGGLER, + ROLE_PROVOCATEUR, + ROLE_STOWAWAY_CHANGELING, + ROLE_SYNDICATE_INFILTRATOR, +)) + +/datum/mind + /// The optin level set by preferences. + var/ideal_opt_in_level = OPT_IN_DEFAULT_LEVEL + /// Set on the FIRST mob login. Set by on-spawn antags (e.g. if you have traitor on and spawn, this will be set to OPT_IN_ANTAG_ENABLED_LEVEL and cannot change) + var/on_spawn_antag_opt_in_level = OPT_IN_NOT_TARGET + /// Set to TRUE on a successful transfer_mind() call. If TRUE, transfer_mind() will not refresh opt in. + var/opt_in_initialized + +/mob/living/Login() + . = ..() + + if (isnull(mind)) + return + if (isnull(client?.prefs)) + return + if (!mind.opt_in_initialized) + mind.update_opt_in(client.prefs) + mind.send_antag_optin_reminder() + mind.opt_in_initialized = TRUE + +/// Refreshes our ideal/on spawn antag opt in level by accessing preferences. +/datum/mind/proc/update_opt_in(datum/preferences/preference_instance = GLOB.preferences_datums[lowertext(key)]) + if (isnull(preference_instance)) + return + + ideal_opt_in_level = preference_instance.read_preference(/datum/preference/choiced/antag_opt_in_status) + + if (preference_instance.read_preference(/datum/preference/toggle/be_antag)) + for (var/antag_category in GLOB.optin_forcing_on_spawn_antag_categories) + if (antag_category in preference_instance.be_special) + on_spawn_antag_opt_in_level = OPT_IN_ANTAG_ENABLED_LEVEL + break + +/// Sends a bold message to our holder, telling them if their optin setting has been set to a minimum due to their antag preferences. +/datum/mind/proc/send_antag_optin_reminder() + var/datum/preferences/preference_instance = GLOB.preferences_datums[lowertext(key)] + var/client/our_client = preference_instance?.parent // that moment when /mind doesnt have a ref to client :) + if (our_client) + var/antag_level = get_antag_opt_in_level() + if (antag_level <= OPT_IN_NOT_TARGET) + return + var/stringified_level = GLOB.antag_opt_in_strings["[antag_level]"] + to_chat(our_client, span_boldnotice("Due to your antag preferences, your antag-optin status has been set to a minimum of [stringified_level].")) + +/// Gets the actual opt-in level used for determining targets. +/datum/mind/proc/get_effective_opt_in_level() + var/step_1 = max(ideal_opt_in_level, get_job_opt_in_level()) + var/step_2 = max(step_1, get_antag_opt_in_level()) + return step_2 + +/// Returns the opt in level of our job. +/datum/mind/proc/get_job_opt_in_level() + return assigned_role?.minimum_opt_in_level || OPT_IN_NOT_TARGET + +/// If we have any antags enabled in GLOB.optin_forcing_midround_antag_categories, returns OPT_IN_ANTAG_ENABLED_LEVEL. OPT_IN_NOT_TARGET otherwise. +/datum/mind/proc/get_antag_opt_in_level() + if (on_spawn_antag_opt_in_level > OPT_IN_NOT_TARGET) + return on_spawn_antag_opt_in_level + + var/datum/preferences/preference_instance = GLOB.preferences_datums[lowertext(key)] + if (!isnull(preference_instance) && preference_instance.read_preference(/datum/preference/toggle/be_antag)) + for (var/antag_category in GLOB.optin_forcing_midround_antag_categories) + if (antag_category in preference_instance.be_special) + return OPT_IN_ANTAG_ENABLED_LEVEL + return OPT_IN_NOT_TARGET diff --git a/modular_nova/modules/antag_opt_in/code/objective.dm b/modular_nova/modules/antag_opt_in/code/objective.dm new file mode 100644 index 00000000000..1c806b04957 --- /dev/null +++ b/modular_nova/modules/antag_opt_in/code/objective.dm @@ -0,0 +1,74 @@ +/datum/objective + /// The default opt in level of this objective. Only targets with opt in above or at this will be considered for this objective. + var/default_opt_in_level = OPT_IN_YES_KILL + +/// Simple getter for [default_opt_in_level]. Use for custom behavior. +/datum/objective/proc/get_opt_in_level(datum/mind/target_mind) + return default_opt_in_level + +/// Returns whether or not our opt in levels/variables are correct for the target. If true, they can be picked as a target. +/datum/objective/proc/opt_in_valid(datum/mind/target_mind) + return (get_opt_in_level(target_mind) <= target_mind.get_effective_opt_in_level()) + +// ROUND REMOVE +/datum/objective/maroon + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +/datum/objective/assassinate/paradox_clone + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +/datum/objective/capture + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +/datum/objective/absorb + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +/datum/objective/absorb_changeling + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +/datum/objective/sacrifice + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +/datum/objective/debrain + default_opt_in_level = OPT_IN_YES_ROUND_REMOVE + +// KILL + +/datum/objective/assassinate + default_opt_in_level = OPT_IN_YES_KILL + +/datum/objective/destroy + default_opt_in_level = OPT_IN_YES_KILL + +/datum/objective/mutiny + default_opt_in_level = OPT_IN_YES_KILL + +// TEMP + +/datum/objective/protect + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/protect/nonhuman + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/steal_n_of_type + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/steal + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/escape/escape_with_identity + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/jailbreak + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/contract + default_opt_in_level = OPT_IN_YES_TEMP + +/datum/objective/contract/opt_in_valid(datum/mind/target_mind) + var/datum/job/target_job = target_mind.assigned_role + if (!target_job?.contractable) + return FALSE + + return ..() diff --git a/modular_nova/modules/antag_opt_in/code/objective_item.dm b/modular_nova/modules/antag_opt_in/code/objective_item.dm new file mode 100644 index 00000000000..32c89aa9238 --- /dev/null +++ b/modular_nova/modules/antag_opt_in/code/objective_item.dm @@ -0,0 +1,20 @@ +/datum/objective_item + /// The opt in level all owners of the item must meet for this to be eligible as an objective target. + var/opt_in_level = OPT_IN_YES_TEMP + +/// Returns TRUE if we have no owners, or all owners's effective opt in level is above [opt_in_level]. FALSE otherwise. +/datum/objective_item/proc/owner_opted_in() + if (!length(item_owner)) + return TRUE + for (var/mob/living/player as anything in GLOB.player_list) + if ((player.mind?.assigned_role.title in item_owner) && player.stat != DEAD && !is_centcom_level(player.z)) // is an owner, copypasted from objective_items.dm owner_exists() + if (player.mind.get_effective_opt_in_level() < opt_in_level) + return FALSE + return TRUE + +/datum/objective_item/valid_objective_for(list/potential_thieves, require_owner) + var/opt_in_disabled = CONFIG_GET(flag/disable_antag_opt_in_preferences) + if (!opt_in_disabled && require_owner && !owner_opted_in()) + return FALSE + + return ..() diff --git a/modular_nova/modules/antag_opt_in/readme.md b/modular_nova/modules/antag_opt_in/readme.md new file mode 100644 index 00000000000..de41e00958b --- /dev/null +++ b/modular_nova/modules/antag_opt_in/readme.md @@ -0,0 +1,33 @@ +https://github.com/NovaSector/NovaSector/pull/121 + +## \ + +Module ID: ANTAG_OPTIN + +### Description: + + +Adds functionality to allow players to 'opt-in' to being an antagonist's mechanical target, with three different levels of involvement - being temporarily inconvenienced, killed, and round removed. Command roles & security are automatically opted-in to at least 'KILL' level. Additionally, contractor & heretic have their objectives adjusted to only have command staff & security as their targets + +### TG Proc/File Changes: + +- Changes in several antag files (will list later) +- examine_tgui.dm (Adds opt in info to OOC examine info) +- objective.dm (target selection stuff) + +### Modular Overrides: + +- N/A + +### Defines: + +- antag_opt_in - lives in ~skyrat_defines located in __DEFINES folder. Defines named OPT_IN_YES_KILL, OPT_IN_YES_TEMP, OPT_IN_YES_ROUND_REMOVE, and OPT_IN_OPT_IN_NOT_TARGET - used for managing opt in stuff. + +### Included files that are not contained in this module: + +- tgui\packages\tgui\interfaces\PreferencesMenu\preferences\features\character_preferences\skyrat\antag_optin.tsx + +### Credits: + +- niko - for doing stuff and taking over +- plum - the original author diff --git a/modular_nova/modules/better_vox/code/vox_bodyparts.dm b/modular_nova/modules/better_vox/code/vox_bodyparts.dm index 543443dd087..882784cb01b 100644 --- a/modular_nova/modules/better_vox/code/vox_bodyparts.dm +++ b/modular_nova/modules/better_vox/code/vox_bodyparts.dm @@ -4,7 +4,7 @@ icon_greyscale = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon_state = "vox_primalis_head" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM | BODYTYPE_SNOUTED + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM is_dimorphic = FALSE should_draw_greyscale = FALSE limb_id = SPECIES_VOX_PRIMALIS @@ -14,7 +14,7 @@ icon_greyscale = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon_state = "vox_primalis_chest" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM is_dimorphic = FALSE should_draw_greyscale = FALSE limb_id = SPECIES_VOX_PRIMALIS @@ -24,7 +24,7 @@ icon_greyscale = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon_state = "vox_primalis_l_arm" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM should_draw_greyscale = FALSE limb_id = SPECIES_VOX_PRIMALIS @@ -33,7 +33,7 @@ icon_greyscale = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon_state = "vox_primalis_r_arm" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM should_draw_greyscale = FALSE limb_id = SPECIES_VOX_PRIMALIS @@ -42,7 +42,7 @@ icon_greyscale = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon_state = "vox_primalis_l_leg" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM should_draw_greyscale = FALSE limb_id = SPECIES_VOX_PRIMALIS @@ -51,7 +51,7 @@ icon_greyscale = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon = 'modular_nova/modules/better_vox/icons/bodyparts/vox_bodyparts.dmi' icon_state = "vox_primalis_r_leg" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM should_draw_greyscale = FALSE limb_id = SPECIES_VOX_PRIMALIS diff --git a/modular_nova/modules/bodyparts/code/_mutant_bodyparts.dm b/modular_nova/modules/bodyparts/code/_mutant_bodyparts.dm index aa857535cf4..02a3248ef37 100644 --- a/modular_nova/modules/bodyparts/code/_mutant_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/_mutant_bodyparts.dm @@ -24,7 +24,6 @@ /obj/item/bodypart/head/mutant icon_greyscale = BODYPART_ICON_MAMMAL limb_id = SPECIES_MAMMAL - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/mutant @@ -61,7 +60,7 @@ /obj/item/bodypart/leg/left/digitigrade icon_greyscale = BODYPART_ICON_MAMMAL limb_id = "digitigrade" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE base_limb_id = "digitigrade" /obj/item/bodypart/leg/left/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE) @@ -71,7 +70,7 @@ /obj/item/bodypart/leg/right/digitigrade icon_greyscale = BODYPART_ICON_MAMMAL limb_id = "digitigrade" - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE base_limb_id = "digitigrade" /obj/item/bodypart/leg/right/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE) diff --git a/modular_nova/modules/bodyparts/code/akula_bodyparts.dm b/modular_nova/modules/bodyparts/code/akula_bodyparts.dm index afb1233b783..cd2c611d2e6 100644 --- a/modular_nova/modules/bodyparts/code/akula_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/akula_bodyparts.dm @@ -2,7 +2,7 @@ /obj/item/bodypart/head/mutant/akula icon_greyscale = BODYPART_ICON_AKULA limb_id = SPECIES_AKULA - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED /obj/item/bodypart/chest/mutant/akula icon_greyscale = BODYPART_ICON_AKULA diff --git a/modular_nova/modules/bodyparts/code/aquatic_bodyparts.dm b/modular_nova/modules/bodyparts/code/aquatic_bodyparts.dm index 4cbd97838c9..64c454f543f 100644 --- a/modular_nova/modules/bodyparts/code/aquatic_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/aquatic_bodyparts.dm @@ -2,7 +2,7 @@ /obj/item/bodypart/head/mutant/aquatic icon_greyscale = BODYPART_ICON_AQUATIC limb_id = SPECIES_AQUATIC - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED /obj/item/bodypart/chest/mutant/aquatic icon_greyscale = BODYPART_ICON_AQUATIC diff --git a/modular_nova/modules/bodyparts/code/lizard_bodyparts.dm b/modular_nova/modules/bodyparts/code/lizard_bodyparts.dm index 8ec2ee74414..e6a5cbd5a08 100644 --- a/modular_nova/modules/bodyparts/code/lizard_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/lizard_bodyparts.dm @@ -1,6 +1,5 @@ /obj/item/bodypart/head/lizard icon_greyscale = BODYPART_ICON_LIZARD - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC // You're too slow Kapu, I did it myself ;) head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/lizard diff --git a/modular_nova/modules/bodyparts/code/taur_bodyparts.dm b/modular_nova/modules/bodyparts/code/taur_bodyparts.dm index 6ae3775f0a7..47a686253c9 100644 --- a/modular_nova/modules/bodyparts/code/taur_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/taur_bodyparts.dm @@ -3,7 +3,7 @@ limb_id = LIMBS_TAUR bodypart_flags = BODYPART_UNREMOVABLE can_be_surgically_removed = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_TAUR + bodyshape = parent_type::bodyshape | BODYSHAPE_TAUR /obj/item/bodypart/leg/right/taur/generate_icon_key() @@ -17,7 +17,7 @@ limb_id = LIMBS_TAUR bodypart_flags = BODYPART_UNREMOVABLE can_be_surgically_removed = FALSE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_TAUR + bodyshape = parent_type::bodyshape | BODYSHAPE_TAUR /obj/item/bodypart/leg/left/taur/generate_icon_key() @@ -26,9 +26,9 @@ return list("taur") /obj/item/bodypart/leg/right/robot/synth/taur - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_TAUR + bodyshape = parent_type::bodyshape | BODYSHAPE_TAUR damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT) /obj/item/bodypart/leg/left/robot/synth/taur - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_TAUR + bodyshape = parent_type::bodyshape | BODYSHAPE_TAUR damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT) diff --git a/modular_nova/modules/bodyparts/code/teshari_bodyparts.dm b/modular_nova/modules/bodyparts/code/teshari_bodyparts.dm index 2127353beff..b816f59867f 100644 --- a/modular_nova/modules/bodyparts/code/teshari_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/teshari_bodyparts.dm @@ -6,7 +6,7 @@ // teshari! /obj/item/bodypart/head/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_TESHARI brute_modifier = TESHARI_BRUTE_MODIFIER burn_modifier = TESHARI_BURN_MODIFIER @@ -34,7 +34,7 @@ /obj/item/bodypart/chest/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_TESHARI brute_modifier = TESHARI_BRUTE_MODIFIER burn_modifier = TESHARI_BURN_MODIFIER @@ -72,7 +72,7 @@ /obj/item/bodypart/arm/left/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_TESHARI unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -82,7 +82,7 @@ /obj/item/bodypart/arm/right/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_TESHARI unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -92,7 +92,7 @@ /obj/item/bodypart/leg/left/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_TESHARI digitigrade_type = /obj/item/bodypart/leg/left/digitigrade/teshari brute_modifier = TESHARI_BRUTE_MODIFIER @@ -100,7 +100,7 @@ /obj/item/bodypart/leg/right/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_TESHARI digitigrade_type = /obj/item/bodypart/leg/right/digitigrade/teshari brute_modifier = TESHARI_BRUTE_MODIFIER @@ -108,14 +108,14 @@ /obj/item/bodypart/leg/left/digitigrade/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM base_limb_id = SPECIES_TESHARI brute_modifier = TESHARI_BRUTE_MODIFIER burn_modifier = TESHARI_BURN_MODIFIER /obj/item/bodypart/leg/right/digitigrade/teshari icon_greyscale = BODYPART_ICON_TESHARI - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM base_limb_id = SPECIES_TESHARI brute_modifier = TESHARI_BRUTE_MODIFIER burn_modifier = TESHARI_BURN_MODIFIER diff --git a/modular_nova/modules/bodyparts/code/vox_bodyparts.dm b/modular_nova/modules/bodyparts/code/vox_bodyparts.dm index 81753b988a8..7ac3fc59906 100644 --- a/modular_nova/modules/bodyparts/code/vox_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/vox_bodyparts.dm @@ -1,42 +1,42 @@ // voxs! /obj/item/bodypart/head/mutant/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM limb_id = SPECIES_VOX /obj/item/bodypart/chest/mutant/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM limb_id = SPECIES_VOX /obj/item/bodypart/arm/left/mutant/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM limb_id = SPECIES_VOX /obj/item/bodypart/arm/right/mutant/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM limb_id = SPECIES_VOX /obj/item/bodypart/leg/left/mutant/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM limb_id = SPECIES_VOX digitigrade_type = /obj/item/bodypart/leg/left/digitigrade/vox /obj/item/bodypart/leg/right/mutant/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM limb_id = SPECIES_VOX digitigrade_type = /obj/item/bodypart/leg/right/digitigrade/vox /obj/item/bodypart/leg/left/digitigrade/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM base_limb_id = SPECIES_VOX /obj/item/bodypart/leg/right/digitigrade/vox icon_greyscale = BODYPART_ICON_VOX - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_SNOUTED | BODYSHAPE_CUSTOM base_limb_id = SPECIES_VOX diff --git a/modular_nova/modules/customization/modules/jobs/_job.dm b/modular_nova/modules/customization/modules/jobs/_job.dm index 189e643e2ff..f053abc3390 100644 --- a/modular_nova/modules/customization/modules/jobs/_job.dm +++ b/modular_nova/modules/customization/modules/jobs/_job.dm @@ -117,7 +117,7 @@ banned_augments = list(HEAD_RESTRICTED_AUGMENTS) /datum/job/quartermaster - banned_quirks = list(HEAD_RESTRICTED_QUIRKS) + banned_quirks = list(HEAD_RESTRICTED_QUIRKS_QM) banned_augments = list(HEAD_RESTRICTED_AUGMENTS) //Silicon @@ -142,6 +142,7 @@ /datum/job/prisoner required_languages = null + banned_quirks = list(PRISONER_RESTRICTED_QUIRKS) /datum/job/orderly banned_quirks = list(GUARD_RESTRICTED_QUIRKS) diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm index 9eb7da1b4dd..010610b382f 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm @@ -17,7 +17,7 @@ /obj/item/organ/external/snout mutantpart_key = "snout" mutantpart_info = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) - external_bodytypes = NONE // We don't actually want this to have BODYTYPE_SNOUTED by default, since some of them don't apply that. + external_bodyshapes = NONE // We don't actually want this to have by default, since some of them don't apply that. preference = "feature_snout" /datum/bodypart_overlay/mutant/snout @@ -32,9 +32,9 @@ /obj/item/organ/external/snout/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_USE_MUZZLED_SPRITE) - external_bodytypes |= BODYTYPE_SNOUTED + external_bodyshapes |= BODYSHAPE_SNOUTED if(sprite_accessory_flags & SPRITE_ACCESSORY_USE_ALT_FACEWEAR_LAYER) - external_bodytypes |= BODYTYPE_ALT_FACEWEAR_LAYER + external_bodyshapes |= BODYSHAPE_ALT_FACEWEAR_LAYER return ..() diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm index f3ce6b8b109..d5b07bc60ed 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm @@ -52,7 +52,7 @@ GLOB.species_clothing_fallback_cache[name]["[file_to_use]-[state_to_use]-[meta]"] = cached_value /** - * Allow for custom clothing icon generation. Only called if the species is BODYTYPE_CUSTOM + * Allow for custom clothing icon generation. Only called if the species is BODYSHAPE_CUSTOM * If null is returned, use default human icon. * Arguments: * * item_slot: The slot we're updating. One of LOADOUT_ITEM_HEAD, etc. diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm index e7ba998c769..c941415cf65 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm @@ -23,7 +23,7 @@ GLOBAL_LIST_EMPTY(customizable_races) var/veteran_only = FALSE ///Flavor text of the species displayed on character creation screeen var/flavor_text = "No description." - ///Path to BODYTYPE_CUSTOM species worn icons. An assoc list of ITEM_SLOT_X => /icon + ///Path to BODYSHAPE_CUSTOM species worn icons. An assoc list of ITEM_SLOT_X => /icon var/list/custom_worn_icons = list() ///Is this species restricted from changing their body_size in character creation? var/body_size_restricted = FALSE @@ -147,7 +147,7 @@ GLOBAL_LIST_EMPTY(customizable_races) var/female_sprite_flags = FEMALE_UNIFORM_FULL // the default gender shaping if(underwear) var/icon_state = underwear.icon_state - if(underwear.has_digitigrade && (species_human.bodytype & BODYTYPE_DIGITIGRADE)) + if(underwear.has_digitigrade && (species_human.bodyshape & BODYSHAPE_DIGITIGRADE)) icon_state += "_d" female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY // for digi gender shaping if(species_human.dna.species.sexes && species_human.physique == FEMALE && (underwear.gender == MALE)) @@ -189,7 +189,7 @@ GLOBAL_LIST_EMPTY(customizable_races) if(socks) var/mutable_appearance/socks_overlay var/icon_state = socks.icon_state - if((species_human.bodytype & BODYTYPE_DIGITIGRADE)) + if((species_human.bodyshape & BODYSHAPE_DIGITIGRADE)) icon_state += "_d" socks_overlay = mutable_appearance(socks.icon, icon_state, -BODY_LAYER) if(!socks.use_static) diff --git a/modular_nova/modules/customization/modules/mob/living/silicon/examine.dm b/modular_nova/modules/customization/modules/mob/living/silicon/examine.dm index 3eb789b6a28..f83c5843116 100644 --- a/modular_nova/modules/customization/modules/mob/living/silicon/examine.dm +++ b/modular_nova/modules/customization/modules/mob/living/silicon/examine.dm @@ -17,6 +17,13 @@ var/erp_status_pref = client.prefs.read_preference(/datum/preference/choiced/erp_status) if(erp_status_pref && !CONFIG_GET(flag/disable_erp_preferences)) . += span_notice("ERP STATUS: [erp_status_pref]") + + if (!CONFIG_GET(flag/disable_antag_opt_in_preferences)) + var/opt_in_status = mind?.get_effective_opt_in_level() + if (!isnull(opt_in_status)) + var/stringified_optin = GLOB.antag_opt_in_strings["[opt_in_status]"] + . += span_notice("Antag Opt-in Status: <b><font color='[GLOB.antag_opt_in_colors[stringified_optin]]'>[stringified_optin]</font></b>") + if(temporary_flavor_text) if(length_char(temporary_flavor_text) <= 40) . += span_notice("<b>They look different than usual:</b> [temporary_flavor_text]") diff --git a/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm b/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm index 81b842a1af6..147c6b39fe6 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm @@ -2,7 +2,7 @@ name = "taur body" zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_EXTERNAL_TAUR - external_bodytypes = BODYTYPE_TAUR + external_bodyshapes = BODYSHAPE_TAUR use_mob_sprite_as_obj_sprite = TRUE preference = "feature_taur" @@ -33,7 +33,7 @@ /obj/item/organ/external/taur_body/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_HIDE_SHOES) - external_bodytypes |= BODYTYPE_HIDE_SHOES + external_bodyshapes |= BODYSHAPE_HIDE_SHOES old_right_leg = reciever.get_bodypart(BODY_ZONE_R_LEG) old_left_leg = reciever.get_bodypart(BODY_ZONE_L_LEG) @@ -49,12 +49,12 @@ new_right_leg = new /obj/item/bodypart/leg/right/robot/synth/taur() - new_left_leg.bodytype |= external_bodytypes + new_left_leg.bodyshape |= external_bodyshapes new_left_leg.replace_limb(reciever, TRUE) if(old_left_leg) old_left_leg.forceMove(src) - new_right_leg.bodytype |= external_bodytypes + new_right_leg.bodyshape |= external_bodyshapes new_right_leg.replace_limb(reciever, TRUE) if(old_right_leg) old_right_leg.forceMove(src) @@ -86,7 +86,7 @@ old_right_leg.replace_limb(organ_owner, TRUE) old_right_leg = null - // We don't call `synchronize_bodytypes()` here, because it's already going to get called in the parent because `external_bodytypes` has a value. + // We don't call `synchronize_bodytypes()` here, because it's already going to get called in the parent because `external_bodyshapes` has a value. return ..() diff --git a/modular_nova/modules/digitigrade_cybernetics/code/robot_bodyparts.dm b/modular_nova/modules/digitigrade_cybernetics/code/robot_bodyparts.dm index 14a78961450..c1933c808e3 100644 --- a/modular_nova/modules/digitigrade_cybernetics/code/robot_bodyparts.dm +++ b/modular_nova/modules/digitigrade_cybernetics/code/robot_bodyparts.dm @@ -5,34 +5,34 @@ name = "cyborg digitigrade right leg" icon_static = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' icon = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/left/robot/digi name = "cyborg digitigrade left leg" icon_static = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' icon = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/right/robot/surplus/digi name = "prosthetic digitigrade right leg" icon_static = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' icon = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/left/robot/surplus/digi name = "prosthetic digitigrade right leg" icon_static = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' icon = 'modular_nova/modules/digitigrade_cybernetics/icons/digitigrade_parts.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/right/robot/advanced/digi name = "advanced digitigrade right leg" icon_static = 'modular_nova/modules/digitigrade_cybernetics/icons/advanced_digitigrade_parts.dmi' icon = 'modular_nova/modules/digitigrade_cybernetics/icons/advanced_digitigrade_parts.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE /obj/item/bodypart/leg/left/robot/advanced/digi name = "advanced digitigrade right leg" icon_static = 'modular_nova/modules/digitigrade_cybernetics/icons/advanced_digitigrade_parts.dmi' icon = 'modular_nova/modules/digitigrade_cybernetics/icons/advanced_digitigrade_parts.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE diff --git a/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm b/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm index bef6ec5589d..ede2feb952c 100644 --- a/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm +++ b/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm @@ -15,10 +15,10 @@ if(ishuman(user)) //feet - if(!(human_user.bodytype & BODYTYPE_DIGITIGRADE) && !(human_user.dna.species.mutant_bodyparts["taur"])) + if(!(human_user.bodyshape & BODYSHAPE_DIGITIGRADE) && !(human_user.dna.species.mutant_bodyparts["taur"])) user.allowed_turfs += "footprint" - if((human_user.bodytype & BODYTYPE_DIGITIGRADE) || human_user.dna.species.mutant_bodyparts["taur"]) + if((human_user.bodyshape & BODYSHAPE_DIGITIGRADE) || human_user.dna.species.mutant_bodyparts["taur"]) user.allowed_turfs += list("pawprint", "hoofprint", "clawprint") //species & taurs diff --git a/modular_nova/modules/medical/code/wounds/medical.dm b/modular_nova/modules/medical/code/wounds/medical.dm index 5a3723fff4b..9d0e4ba2487 100644 --- a/modular_nova/modules/medical/code/wounds/medical.dm +++ b/modular_nova/modules/medical/code/wounds/medical.dm @@ -46,7 +46,7 @@ prefix = gauze_prefix var/suffix = gauzed_bodypart.body_zone - if(gauzed_bodypart.bodytype & BODYTYPE_DIGITIGRADE) + if(gauzed_bodypart.bodyshape & BODYSHAPE_DIGITIGRADE) suffix += "_digitigrade" return "[prefix]_[suffix]" diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm index 60980b35b60..b248a0aca88 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm @@ -149,7 +149,7 @@ //stuff to apply processing on equip and add mood event for perverts /obj/item/clothing/under/shibari/groin/equipped(mob/living/user, slot) var/mob/living/carbon/human/hooman = user - slowdown = hooman?.bodytype & BODYTYPE_TAUR ? 4 : 0 + slowdown = hooman?.bodyshape & BODYSHAPE_TAUR ? 4 : 0 return..() //processing stuff diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_items/shibari.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_items/shibari.dm index d87c9549ef2..cefff5e5fae 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_items/shibari.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_items/shibari.dm @@ -141,7 +141,7 @@ return var/obj/item/stack/shibari_rope/split_rope = null var/slow = 0 - if(them.bodytype & BODYTYPE_TAUR) + if(them.bodyshape & BODYSHAPE_TAUR) split_rope = split_stack(null, 2) slow = 4 else @@ -218,7 +218,7 @@ if(them.shoes) to_chat(user, span_warning("They're already wearing something on this slot!")) return - if(them.bodytype & BODYTYPE_TAUR) + if(them.bodyshape & BODYSHAPE_TAUR) to_chat(user, span_warning("You can't tie their feet, they're a taur!")) return them.visible_message(span_warning("[user] starts tying [them]'s feet!"),\ @@ -250,7 +250,7 @@ if(!do_after(user, HAS_TRAIT(user, TRAIT_RIGGER) ? 20 : 60, them)) return var/slow = 0 - if(them.bodytype & BODYTYPE_TAUR) + if(them.bodyshape & BODYSHAPE_TAUR) slow = 4 var/obj/item/stack/shibari_rope/split_rope = split_stack(null, 1) if(split_rope) @@ -283,7 +283,7 @@ return var/obj/item/stack/shibari_rope/split_rope = null var/slow = 0 - if(them.bodytype & BODYTYPE_TAUR) + if(them.bodyshape & BODYSHAPE_TAUR) split_rope = split_stack(null, 2) slow = 4 else diff --git a/modular_nova/modules/opposing_force/code/opposing_force_datum.dm b/modular_nova/modules/opposing_force/code/opposing_force_datum.dm index 3f688332cb5..e6f3571a10a 100644 --- a/modular_nova/modules/opposing_force/code/opposing_force_datum.dm +++ b/modular_nova/modules/opposing_force/code/opposing_force_datum.dm @@ -216,6 +216,16 @@ ) data["selected_equipment"] += list(equipment_data) + data["current_crew"] = generate_optin_crew_list() + + return data + +/datum/opposing_force/ui_static_data(mob/user) + var/list/data = list() + + data["opt_in_colors"] = GLOB.antag_opt_in_colors + data["opt_in_enabled"] = (!CONFIG_GET(flag/disable_antag_opt_in_preferences)) + return data /datum/opposing_force/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) @@ -1021,3 +1031,25 @@ return opfor.ui_interact(usr) + +/proc/generate_optin_crew_list() + var/list/output = list() + + for (var/datum/record/locked/iterated_record as anything in GLOB.manifest.locked) + var/datum/mind/mind_datum = iterated_record.mind_ref.resolve() + if (!istype(mind_datum)) + continue + var/name = iterated_record.name + var/rank = iterated_record.rank + + var/opt_in_status = mind_datum.get_effective_opt_in_level() + var/ideal_opt_in_status = mind_datum.ideal_opt_in_level + + output += list(list( + "name" = name, + "rank" = rank, + "opt_in_status" = GLOB.antag_opt_in_strings["[opt_in_status]"], + "ideal_opt_in_status" = GLOB.antag_opt_in_strings["[ideal_opt_in_status]"] + )) + + return output diff --git a/modular_nova/modules/synths/code/bodyparts/limbs.dm b/modular_nova/modules/synths/code/bodyparts/limbs.dm index 1126295f1fe..a1a3506de08 100644 --- a/modular_nova/modules/synths/code/bodyparts/limbs.dm +++ b/modular_nova/modules/synths/code/bodyparts/limbs.dm @@ -6,7 +6,6 @@ icon_greyscale = BODYPART_ICON_IPC limb_id = SPECIES_SYNTH should_draw_greyscale = TRUE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC change_exempt_flags = NONE brute_modifier = SYNTH_BRUTE_MODIFIER burn_modifier = SYNTH_BURN_MODIFIER @@ -58,7 +57,7 @@ icon_greyscale = BODYPART_ICON_SYNTHLIZARD should_draw_greyscale = TRUE limb_id = BODYPART_ID_DIGITIGRADE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE base_limb_id = BODYPART_ID_DIGITIGRADE change_exempt_flags = NONE brute_modifier = SYNTH_BRUTE_MODIFIER @@ -72,7 +71,7 @@ icon_greyscale = BODYPART_ICON_SYNTHLIZARD should_draw_greyscale = TRUE limb_id = BODYPART_ID_DIGITIGRADE - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE + bodyshape = parent_type::bodyshape | BODYSHAPE_DIGITIGRADE base_limb_id = BODYPART_ID_DIGITIGRADE change_exempt_flags = NONE brute_modifier = SYNTH_BRUTE_MODIFIER diff --git a/modular_nova/modules/telepathy_quirk/code/telepathy_action.dm b/modular_nova/modules/telepathy_quirk/code/telepathy_action.dm new file mode 100644 index 00000000000..e2ab3ef5e32 --- /dev/null +++ b/modular_nova/modules/telepathy_quirk/code/telepathy_action.dm @@ -0,0 +1,125 @@ +/datum/mutation/human/telepathy + power_path = /datum/action/cooldown/spell/pointed/telepathy + +/datum/action/cooldown/spell/pointed/telepathy + name = "Telepathic Communication" + desc = "<b>Left click</b>: point target to project a thought to them. <b>Right click</b>: project to your last thought target, if in range." + button_icon = 'icons/mob/actions/actions_revenant.dmi' + button_icon_state = "r_transmit" + spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC + antimagic_flags = MAGIC_RESISTANCE_MIND + cooldown_time = 1 SECONDS + cast_range = 7 + /// What's the last mob we point-targeted with this ability? + var/datum/weakref/last_target_ref + /// The message we send + var/message + /// Are we blocking casts? + var/blocked = FALSE + +/datum/action/cooldown/spell/pointed/telepathy/is_valid_target(atom/cast_on) + . = ..() + if (!.) + return FALSE + + if (!isliving(cast_on)) + to_chat(owner, span_warning("Inanimate objects can't hear your thoughts.")) + owner.balloon_alert(owner, "not a thing with thoughts!") + return FALSE + + var/mob/living/living_target = cast_on + if (living_target.stat == DEAD) + to_chat(owner, span_warning("The disruptive noise of departed resonance inhibits your ability to communicate with the dead.")) + owner.balloon_alert(owner, "can't transmit to the dead!") + return FALSE + + if (get_dist(living_target, owner) > cast_range) + owner.balloon_alert(owner, "too far away!") + return FALSE + + return TRUE + +/datum/action/cooldown/spell/pointed/telepathy/before_cast(atom/cast_on) + . = ..() + if(. & SPELL_CANCEL_CAST || blocked) + return + + message = autopunct_bare(capitalize(tgui_input_text(owner, "What do you wish to whisper to [cast_on]?", "[src]"))) + if(QDELETED(src) || QDELETED(owner) || QDELETED(cast_on) || !can_cast_spell()) + return . | SPELL_CANCEL_CAST + + if(get_dist(cast_on, owner) > cast_range) + owner.balloon_alert(owner, "they're too far!") + return . | SPELL_CANCEL_CAST + + if(!message) + reset_spell_cooldown() + return . | SPELL_CANCEL_CAST + +/datum/action/cooldown/spell/pointed/telepathy/Trigger(trigger_flags, atom/target) + if (trigger_flags & TRIGGER_SECONDARY_ACTION) + var/mob/living/last_target = last_target_ref?.resolve() + + if(isnull(last_target)) + last_target_ref = null + owner.balloon_alert(owner, "last target is not available!") + return + else if(get_dist(last_target, owner) > cast_range) + owner.balloon_alert(owner, "[last_target] is too far away!") + return + + blocked = TRUE + + message = autopunct_bare(capitalize(tgui_input_text(owner, "What do you wish to whisper to [last_target]?", "[src]"))) + if(QDELETED(src) || QDELETED(owner) || QDELETED(last_target) || !can_cast_spell()) + blocked = FALSE + return + send_thought(owner, last_target, message) + src.StartCooldown() + blocked = FALSE + return + + . = ..() + +/datum/action/cooldown/spell/pointed/telepathy/cast(mob/living/cast_on) + . = ..() + send_thought(owner, cast_on, message) + +/datum/action/cooldown/spell/pointed/telepathy/proc/send_thought(mob/living/caster, mob/living/target, message) + log_directed_talk(caster, target, message, LOG_SAY, tag = "telepathy") + + last_target_ref = WEAKREF(target) + + to_chat(owner, span_boldnotice("You reach out and convey to [target]: \"[span_purple(message)]\"")) + // flub a runechat chat message, do something with the language later + if(owner.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat)) + owner.create_chat_message(owner, owner.get_selected_language(), message, list("italics")) + if(!target.can_block_magic(antimagic_flags, charge_cost = 0) && target.client) //make sure we've got a client before we bother sending anything + //different messaging if the target has the telepathy mutation themselves themselves + if (ishuman(target)) + var/mob/living/carbon/human/human_target = target + var/datum/mutation/human/telepathy/tele_mut = human_target.dna.get_mutation(/datum/mutation/human/telepathy) + + if (tele_mut) + to_chat(target, span_boldnotice("[caster]'s psychic presence resounds in your mind: \"[span_purple(message)]\"")) + else + to_chat(target, span_boldnotice("A voice echoes in your head: \"[span_purple(message)]\"")) + + if(target.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat)) + target.create_chat_message(target, target.get_selected_language(), message, list("italics")) // it appears over them since they hear it in their head + else + owner.balloon_alert(owner, "something blocks your thoughts!") + to_chat(owner, span_warning("Your mind encounters impassable resistance: the thought was blocked!")) + return + + // send to ghosts as well i guess + for(var/mob/dead/ghost as anything in GLOB.dead_mob_list) + if(!isobserver(ghost)) + continue + + var/from_link = FOLLOW_LINK(ghost, owner) + var/from_mob_name = span_boldnotice("[owner]") + var/to_link = FOLLOW_LINK(ghost, target) + var/to_mob_name = span_name("[target]") + + to_chat(ghost, "[from_link] " + span_purple("<b>\[Telepathy\]</b> [from_mob_name] transmits, \"[message]\"") + " to [to_mob_name] [to_link]") diff --git a/modular_nova/modules/telepathy_quirk/code/telepathy_quirk.dm b/modular_nova/modules/telepathy_quirk/code/telepathy_quirk.dm new file mode 100644 index 00000000000..5cbcfb275f6 --- /dev/null +++ b/modular_nova/modules/telepathy_quirk/code/telepathy_quirk.dm @@ -0,0 +1,34 @@ +/datum/quirk/telepathic + name = "Telepathic" + desc = "You are able to transmit your thoughts to other living creatures." + gain_text = span_purple("Your mind roils with psychic energy.") + lose_text = span_notice("Mundanity encroaches upon your thoughts once again.") + medical_record_text = "Patient has an unusually enlarged Broca's area visible in cerebral biology, and appears to be able to communicate via extrasensory means." + value = 0 + icon = FA_ICON_HEAD_SIDE_COUGH + /// Ref used to easily retrieve the action used when removing the quirk from silicons + var/datum/weakref/tele_action_ref + +/datum/quirk/telepathic/add(client/client_source) + if (iscarbon(quirk_holder)) + var/mob/living/carbon/human/human_holder = quirk_holder + + if (!human_holder.dna.activate_mutation(/datum/mutation/human/telepathy)) + human_holder.dna.add_mutation(/datum/mutation/human/telepathy, MUT_OTHER) + else if (issilicon(quirk_holder)) + var/mob/living/silicon/robot_holder = quirk_holder + var/datum/action/cooldown/spell/pointed/telepathy/tele_action = new + + tele_action.Grant(robot_holder) + tele_action_ref = WEAKREF(tele_action) + +/datum/quirk/telepathic/remove() + var/datum/action/cooldown/spell/pointed/telepathy/tele_action = tele_action_ref?.resolve() + if (isnull(tele_action)) + tele_action_ref = null + if (iscarbon(quirk_holder)) + var/mob/living/carbon/human/human_holder = quirk_holder + human_holder.dna.remove_mutation(/datum/mutation/human/telepathy) + else if (issilicon(quirk_holder) && !isnull(tele_action)) + QDEL_NULL(tele_action) + tele_action_ref = null diff --git a/modular_nova/modules/telepathy_quirk/code/telepathy_reply_emote.dm b/modular_nova/modules/telepathy_quirk/code/telepathy_reply_emote.dm new file mode 100644 index 00000000000..adf5e672599 --- /dev/null +++ b/modular_nova/modules/telepathy_quirk/code/telepathy_reply_emote.dm @@ -0,0 +1,17 @@ +/datum/emote/living/telepathy_reply + key = "treply" + key_third_person = "treply" + cooldown = 4 SECONDS + +/datum/emote/living/telepathy_reply/run_emote(mob/living/user, params, type_override, intentional) + if (ishuman(user) && intentional) + var/mob/living/carbon/human/human_user = user + var/datum/mutation/human/telepathy/mutation = human_user.dna.get_mutation(/datum/mutation/human/telepathy) + if (mutation) + var/datum/action/cooldown/spell/pointed/telepathy/tele_action = locate() in user.actions + // just straight up call the right-click action as is + if (tele_action) + tele_action.Trigger(TRIGGER_SECONDARY_ACTION) + tele_action.blocked = FALSE + + return ..() diff --git a/modular_nova/modules/tesh_augments/code/robot_bodyparts.dm b/modular_nova/modules/tesh_augments/code/robot_bodyparts.dm index d894847ed62..329d87c3356 100644 --- a/modular_nova/modules/tesh_augments/code/robot_bodyparts.dm +++ b/modular_nova/modules/tesh_augments/code/robot_bodyparts.dm @@ -21,7 +21,7 @@ desc = "A skeletal limb wrapped in pseudomuscles and membranous feathers, with a low-conductivity case." icon = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' icon_static = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -34,7 +34,7 @@ desc = "A skeletal limb wrapped in pseudomuscles and membranous feathers, with a low-conductivity case." icon_static = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -47,7 +47,7 @@ desc = "A skeletal limb wrapped in pseudomuscles and membranous feathers, with a low-conductivity case." icon_static = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -60,7 +60,7 @@ desc = "A skeletal limb wrapped in pseudomuscles and membranous feathers, with a low-conductivity case." icon_static = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -73,7 +73,7 @@ desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell, covered in a layer of membranous feathers." icon_static = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM brute_modifier = 1 burn_modifier = 0.9 @@ -85,7 +85,7 @@ desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals. A layer of membranous feathers covers the stark metal." icon_static = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW unarmed_damage_high = TESHARI_PUNCH_HIGH @@ -102,7 +102,7 @@ desc = "A skeletal, robotic wing. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 @@ -121,7 +121,7 @@ desc = "A skeletal, robotic wing. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -139,7 +139,7 @@ desc = "A skeletal, robotic hindlimb. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -157,7 +157,7 @@ desc = "A skeletal, robotic hindlimb. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -175,7 +175,7 @@ desc = "A skeletal, robotic wing. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -193,7 +193,7 @@ desc = "A skeletal, robotic wing. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -213,7 +213,7 @@ desc = "A skeletal, robotic hindlimb. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -232,7 +232,7 @@ desc = "A skeletal, robotic hindlimb. Outdated and fragile, but it's still better than nothing. A layer of membranous feathers hides the cheap assembly." icon_static = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/surplus_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 0.3 unarmed_damage_high = TESHARI_PUNCH_HIGH * 0.5 @@ -252,7 +252,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -270,7 +270,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -288,7 +288,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -306,7 +306,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -324,7 +324,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -342,7 +342,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -360,7 +360,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 @@ -378,7 +378,7 @@ desc = "An advanced robotic hindlimb. These designs are usually reserved for those still on the search for Avalon." icon_static = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' icon = 'modular_nova/modules/tesh_augments/icons/advanced_augments_teshari.dmi' - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM unarmed_damage_low = TESHARI_PUNCH_LOW * 2 unarmed_damage_high = TESHARI_PUNCH_HIGH * 3 diff --git a/modular_nova/modules/underworld_connections/code/black_market_uplink.dm b/modular_nova/modules/underworld_connections/code/black_market_uplink.dm new file mode 100644 index 00000000000..42a060cca60 --- /dev/null +++ b/modular_nova/modules/underworld_connections/code/black_market_uplink.dm @@ -0,0 +1,2 @@ +/obj/item/market_uplink + w_class = WEIGHT_CLASS_SMALL diff --git a/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm b/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm new file mode 100644 index 00000000000..9b13c31b9bf --- /dev/null +++ b/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm @@ -0,0 +1,222 @@ +// This file contains a WHOLE BUNCH of cost defuckulations to bring the ancient black market stuff back into line with our current cargo pricing. +// I've also taken the liberty of redoing a few descs because man they kinda suck. +// Some availability_probs have been upped considerably for items that I think should be core to the "dodgy" character archetype, like switchblades, science goggles and the various maintenance pills. + +// CLOTHING + +/datum/market_item/clothing/ninja_mask + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + +/datum/market_item/clothing/durathread_vest + desc = "Concerns about high asbestos content are completely unfounded. Note: may contain asbestos." + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/clothing/durathread_helmet + desc = "Smells faintly like an icewalker. Weird. Goes on your head and is vaguely armoured. Note: may contain asbestos." + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/clothing/full_spacesuit_set + desc = "Decommissioned thirty years ago, boxes of these ancient spaceproof relics keep showing up in warehouses somewhere. They're \"old style\"." + price_min = PAYCHECK_CREW * 6 + price_max = PAYCHECK_CREW * 12 + +/datum/market_item/clothing/chameleon_hat + desc = "Emulate the appearance of any hat in the sector! Warning: device not quality tested. \[REDACTED\] assumes no risk for malfunction or mortal injury." + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + +/datum/market_item/clothing/rocket_boots + price_min = PAYCHECK_CREW * 6 + price_max = PAYCHECK_CREW * 12 + +/datum/market_item/clothing/anti_sec_pin + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + availability_prob = 100 //it's funny so why not + +// CONSUMABLES +/datum/market_item/consumable/clown_tears + desc = "Wrung by force from ethically-sourced clowns by your local jester. 100% guaranteed baton free." + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/consumable/donk_pocket_box + price_min = PAYCHECK_CREW * 0.3 + price_max = PAYCHECK_CREW * 1 + availability_prob = 100 //you can always afford some (illegal) donkpockets. Donk Co loves you. + +/datum/market_item/consumable/suspicious_pills + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/consumable/floor_pill + desc = "Harvested daily by responsibly-paid assistants, this pill is guaranteed to a) have been on the floor, and b) is a pill. Good luck!" + price_min = PAYCHECK_CREW * 0.1 + price_max = PAYCHECK_CREW * 0.3 + availability_prob = 100 // no shortage of unmarked pills babyyyy + +/datum/market_item/consumable/pumpup + desc = "Clean-up crews sell off these things by the dozen after every shift - get your hands on some today! What could possibly go wrong with maintenance drugs?" + price_min = PAYCHECK_CREW * 0.2 + price_max = PAYCHECK_CREW * 0.4 + +// MISCELLANEOUS + +/datum/market_item/misc/Clear_PDA + desc = "Clearly show your appreciation for style with this limited edition clear PDA!" + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 2 + +/datum/market_item/misc/jade_Lantern + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW + +/datum/market_item/misc/cap_gun + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW + +/datum/market_item/misc/shoulder_holster + name = "Shoulder Holster" + //why in great googly moogly were these so expensive? what the fuck? + price_min = PAYCHECK_CREW * 0.2 + price_max = PAYCHECK_CREW * 0.6 + +/datum/market_item/misc/donk_recycler + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 4 + +/datum/market_item/misc/shove_blocker + // ok this is a seriously fucking good module so we'll make it cost a bit + price_min = PAYCHECK_CREW * 8 + price_max = PAYCHECK_CREW * 14 + +/datum/market_item/misc/holywater + desc = "The Spinward Independent Magicians assume no responsibility for the holy (or unholiness) of this magical reagent." + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + +/datum/market_item/misc/strange_seed + desc = "Exotic varieties of seed outlawed in most sectors, including this one. What's the worst that could happen?" + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW + +/datum/market_item/misc/smugglers_satchel + //inventory gamers... + price_min = PAYCHECK_CREW * 3 + price_max = PAYCHECK_CREW * 6 + +/datum/market_item/misc/roulette + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 6 // it's how the chips fall babyyy + +/datum/market_item/misc/jawed_hook + desc = "If you're struggling with the fishes, give 'em the jaws, see?" + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/misc/v8_engine + name = "Genuine V8 Engine (Preserved)" + price_min = PAYCHECK_CREW * 6 + price_max = PAYCHECK_CREW * 12 + +/datum/market_item/misc/fish + name = "Case of Smuggled Fish" + desc = "What makes these fish such hot products? We'd have to kill you if we told you." + +/datum/market_item/misc/giant_wrench_parts + name = "Comically-Large Wrench Parts" + desc = "They're searching every broadband transmission for the name of this wrench, alright? You're mad if you assemble this thing. Mad, we tell you." + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 + +// TOOLS +/datum/market_item/tool/caravan_wrench + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 // let's have all the experimental tools be always available, because why not? + +/datum/market_item/tool/caravan_wirecutters + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 + +/datum/market_item/tool/caravan_screwdriver + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 + +/datum/market_item/tool/caravan_crowbar + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 + +/datum/market_item/tool/binoculars + //we can roundstart with these so let's tone them way down + desc = "Offworld military surplus. They'll never see you coming." + price_min = PAYCHECK_CREW * 0.2 + price_max = PAYCHECK_CREW * 0.5 + +/datum/market_item/tool/riot_shield + desc = "Bloodstains not included." + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 + +/datum/market_item/tool/thermite_bottle + desc = "Thirty galactic units of an incendiary compound that will burn through just about anything." + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 6 + +/datum/market_item/tool/science_goggles + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 // for people who want to make illicit drugs in maint + +/datum/market_item/tool/fake_scanner + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + +/datum/market_item/tool/program_disk + name = "Bootleg PDA Data Disk" + desc = "Contains a random selection of limited PDA programs purloined by bitrunners from the FTU. Wait, we're not supposed to tell you that." + price_min = PAYCHECK_CREW * 1.5 + price_max = PAYCHECK_CREW * 3 + availability_prob = 100 // not every program is useful but some of these are and they're fun and hackery, so why not? + +// WEAPONS + +/datum/market_item/weapon/bear_trap + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 4 + +/datum/market_item/weapon/shotgun_dart + price_min = PAYCHECK_CREW * 0.1 + price_max = PAYCHECK_CREW * 0.3 + +/datum/market_item/weapon/bone_spear + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + +/datum/market_item/weapon/chainsaw + desc = "Once used to fell trees on Gaia worlds, the humble chainsaw has come into its own as the premiere anti-mold device of the sector. And you can have one right now for one easy payment!" + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 4 + availability_prob = 75 // USE CHAINSAWS FOR MOLDS MORE OH MY GOD + +/datum/market_item/weapon/switchblade + // This is force 20 like the sabre/shamshir so price it similarly. Also, make it always available so you can shank people in maints. + desc = "Standard-issue hardware for shifty goons sector-wide. Pointy and sharp." + price_min = PAYCHECK_CREW * 4.25 + price_max = PAYCHECK_CREW * 8 + availability_prob = 100 + +/datum/market_item/weapon/emp_grenade + desc = "The bane of synthetics and station-engineers everywhere." + price_min = PAYCHECK_CREW * 1.5 + price_max = PAYCHECK_CREW * 5 + +/datum/market_item/weapon/fisher + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 diff --git a/modular_nova/modules/underworld_connections/code/underworld_connections_quirk.dm b/modular_nova/modules/underworld_connections/code/underworld_connections_quirk.dm new file mode 100644 index 00000000000..f3d78d7df45 --- /dev/null +++ b/modular_nova/modules/underworld_connections/code/underworld_connections_quirk.dm @@ -0,0 +1,147 @@ +/datum/quirk/item_quirk/underworld_connections + name = "Underworld Connections" + desc = "You're in with the seedier elements of the galactic underworld, and can start with a customizable black market uplink, and access to information brokers with exploitable information about the crew. Security has suspicions about you, and you may struggle to obtain a weapons permit." + icon = FA_ICON_SUITCASE + value = 0 + gain_text = span_notice("Your contacts to the underworld are close at hand.") + lose_text = span_notice("Your contacts to the underworld have gone quiet.") + medical_record_text = "Patient records may have been tampered with in the past." + quirk_flags = QUIRK_HIDE_FROM_SCAN + mail_goodies = list(/obj/item/storage/briefcase/secure) + +/datum/quirk/item_quirk/underworld_connections/add_unique(client/client_source) + if (ishuman(quirk_holder)) + var/obj/item/market_uplink/blackmarket/roundstart_uplink = new + + //customize the goddamn uplink + var/uplink_skin = client_source?.prefs.read_preference(/datum/preference/choiced/uplink_skin) + var/list/uplink_skin_val = GLOB.possible_uplink_skins[uplink_skin] + if (uplink_skin_val) + roundstart_uplink.icon = uplink_skin_val[1] + roundstart_uplink.icon_state = uplink_skin_val[2] + + var/uplink_name = client_source?.prefs.read_preference(/datum/preference/text/uplink_name) + if (uplink_name) + roundstart_uplink.name = uplink_name + + var/uplink_desc = client_source?.prefs.read_preference(/datum/preference/text/uplink_desc) + if (uplink_desc) + roundstart_uplink.desc = uplink_desc + + give_item_to_holder( + roundstart_uplink, + list( + LOCATION_LPOCKET = ITEM_SLOT_LPOCKET, + LOCATION_RPOCKET = ITEM_SLOT_RPOCKET, + LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, + LOCATION_HANDS = ITEM_SLOT_HANDS, + ) + ) + +/datum/quirk/item_quirk/underworld_connections/post_add() + . = ..() + + // Make sure we've got a client/mind first (hence, post_add), then give us exploitables access + quirk_holder.mind.has_exploitables_override = TRUE + quirk_holder.mind.handle_exploitables() + + // Also let the user know that they need to OPFOR if they want to do heavy antagonism. Policy request. + to_chat(quirk_holder, span_boldwarning("REMEMBER: The Underworld Connections quirk does NOT make you an antagonist. Please make an OPFOR request if you intend to do serious criminal activity.")) + + // Set us as 'suspected' on HUDs at roundstart and leave a note about our dark and mysterious past. No permits for us! If we're human. + if (ishuman(quirk_holder)) + var/mob/living/carbon/human/human_holder = quirk_holder + var/datum/record/crew/our_record = find_record(human_holder.name) + if (our_record) + our_record.wanted_status = WANTED_SUSPECT + our_record.security_note += "DO NOT ISSUE WEAPON PERMITS. Subject has suspected links to covert criminal elements." + +/datum/quirk/item_quirk/underworld_connections/remove() + if (ishuman(quirk_holder)) + var/mob/living/carbon/human/human_holder = quirk_holder + var/datum/record/crew/our_record = find_record(human_holder.name) + if (our_record.security_note) + our_record.security_note = replacetext(our_record.security_note, "DO NOT ISSUE WEAPON PERMITS. Subject has suspected links to covert criminal elements.", "") + if (!length(our_record.security_note)) // that was the only thing in the notes + our_record.security_note = null + if (isnull(our_record.security_note) && our_record.wanted_status == WANTED_SUSPECT) // only clear this if the security notes contain nothing but the quirk-generated note, just to be certain we are not accidentally resetting the wanted status for an unrelated crime + our_record.wanted_status = WANTED_NONE + + quirk_holder.mind.has_exploitables_override = FALSE + quirk_holder.mind.handle_exploitables() + +/datum/quirk_constant_data/underworld_connections + associated_typepath = /datum/quirk/item_quirk/underworld_connections + customization_options = list(/datum/preference/choiced/uplink_skin, /datum/preference/text/uplink_name, /datum/preference/text/uplink_desc) + +/datum/preference/choiced/uplink_skin + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "underworld_uplink_skin" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + +/// List of uplink skins, associated list where the value is a list containing icon dmi and then icon_state +GLOBAL_LIST_INIT(possible_uplink_skins, list( + "Brick Phone" = list('icons/obj/antags/gang/cell_phone.dmi', "phone_off"), + "Default Black Market Uplink" = list('icons/obj/blackmarket.dmi', "uplink"), + "Generic Radio" = list('icons/obj/devices/voice.dmi', "radio"), + "Green Walkie Talkie" = list('icons/obj/devices/voice.dmi', "walkietalkie"), + "Inconspicious PDA" = list('icons/obj/modular_pda.dmi', "pda"), + "Mining Radio" = list('icons/obj/miningradio.dmi', "miningradio"), + "Red Analogue Phone" = list('icons/obj/devices/voice.dmi', "red_phone"), + "Red Walkie Talkie" = list('icons/obj/devices/voice.dmi', "nukietalkie"), + "Syndicate Suspicious Phone" = list('icons/obj/antags/syndicate_tools.dmi', "suspiciousphone"), + "Syndicate Tablet (Silicon)" = list('icons/obj/modular_pda.dmi', "tablet-silicon-syndicate"), +)) + +/datum/preference/choiced/uplink_skin/init_possible_values() + return assoc_to_keys(GLOB.possible_uplink_skins) + +/datum/preference/choiced/uplink_skin/create_default_value() + return "Default Black Market Uplink" + +/datum/preference/choiced/uplink_skin/is_accessible(datum/preferences/preferences) + if (!..()) + return FALSE + + return "Underworld Connections" in preferences.all_quirks + +/datum/preference/choiced/uplink_skin/apply_to_human(mob/living/carbon/human/target, value) + return + +/datum/preference/text/uplink_name + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "underworld_uplink_name" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + maximum_value_length = 32 + +/datum/preference/text/uplink_name/is_accessible(datum/preferences/preferences) + if (!..()) + return FALSE + + return "Underworld Connections" in preferences.all_quirks + +/datum/preference/text/uplink_name/serialize(input) + return htmlrendertext(input) + +/datum/preference/text/uplink_name/apply_to_human(mob/living/carbon/human/target, value) + return + +/datum/preference/text/uplink_desc + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "underworld_uplink_desc" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + +/datum/preference/text/uplink_desc/is_accessible(datum/preferences/preferences) + if (!..()) + return FALSE + + return "Underworld Connections" in preferences.all_quirks + +/datum/preference/text/uplink_desc/serialize(input) + return htmlrendertext(input) + +/datum/preference/text/uplink_desc/apply_to_human(mob/living/carbon/human/target, value) + return diff --git a/sound/creatures/bee_swarm.ogg b/sound/creatures/bee_swarm.ogg new file mode 100644 index 00000000000..7cf5a5a3d9f Binary files /dev/null and b/sound/creatures/bee_swarm.ogg differ diff --git a/tff_modular/modules/nabbers/code/nabber_bodyparts.dm b/tff_modular/modules/nabbers/code/nabber_bodyparts.dm index 0e5fbf238c7..7c040f01b81 100644 --- a/tff_modular/modules/nabbers/code/nabber_bodyparts.dm +++ b/tff_modular/modules/nabbers/code/nabber_bodyparts.dm @@ -7,7 +7,7 @@ /obj/item/bodypart/head/mutant/nabber icon_greyscale = BODYPART_ICON_NABBER - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_NABBER brute_modifier = NABBER_BRUTE_MODIFIER burn_modifier = NABBER_BURN_MODIFIER @@ -34,7 +34,7 @@ /obj/item/bodypart/chest/mutant/nabber icon_greyscale = BODYPART_ICON_NABBER - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_NABBER brute_modifier = NABBER_BRUTE_MODIFIER burn_modifier = NABBER_BURN_MODIFIER @@ -55,7 +55,7 @@ /obj/item/bodypart/arm/left/mutant/nabber icon_greyscale = BODYPART_ICON_NABBER - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_NABBER unarmed_damage_low = NABBER_PUNCH_LOW unarmed_damage_high = NABBER_PUNCH_HIGH @@ -64,7 +64,7 @@ /obj/item/bodypart/arm/right/mutant/nabber icon_greyscale = BODYPART_ICON_NABBER - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_NABBER unarmed_damage_low = NABBER_PUNCH_LOW unarmed_damage_high = NABBER_PUNCH_HIGH @@ -73,14 +73,14 @@ /obj/item/bodypart/leg/left/mutant/nabber icon_greyscale = BODYPART_ICON_NABBER - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_NABBER brute_modifier = NABBER_BRUTE_MODIFIER burn_modifier = NABBER_BURN_MODIFIER /obj/item/bodypart/leg/right/mutant/nabber icon_greyscale = BODYPART_ICON_NABBER - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + bodyshape = parent_type::bodyshape | BODYSHAPE_CUSTOM limb_id = SPECIES_NABBER brute_modifier = NABBER_BRUTE_MODIFIER burn_modifier = NABBER_BURN_MODIFIER diff --git a/tgstation.dme b/tgstation.dme index 3c46f9f6b60..725b5a9dca8 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -399,6 +399,7 @@ #include "code\__DEFINES\~nova_defines\admin.dm" #include "code\__DEFINES\~nova_defines\airlock.dm" #include "code\__DEFINES\~nova_defines\ammo_defines.dm" +#include "code\__DEFINES\~nova_defines\antag_optin_defines.dm" #include "code\__DEFINES\~nova_defines\antagonists.dm" #include "code\__DEFINES\~nova_defines\apc_defines.dm" #include "code\__DEFINES\~nova_defines\armaments.dm" @@ -6646,6 +6647,12 @@ #include "modular_nova\modules\alternative_job_titles\code\job.dm" #include "modular_nova\modules\ammo_workbench\code\ammo_workbench.dm" #include "modular_nova\modules\ammo_workbench\code\design_disks.dm" +#include "modular_nova\modules\antag_opt_in\code\antag_optin_config.dm" +#include "modular_nova\modules\antag_opt_in\code\antag_optin_preferences.dm" +#include "modular_nova\modules\antag_opt_in\code\job.dm" +#include "modular_nova\modules\antag_opt_in\code\mind.dm" +#include "modular_nova\modules\antag_opt_in\code\objective.dm" +#include "modular_nova\modules\antag_opt_in\code\objective_item.dm" #include "modular_nova\modules\apc_arcing\apc.dm" #include "modular_nova\modules\armaments\code\armament_component.dm" #include "modular_nova\modules\armaments\code\armament_entries.dm" @@ -8069,6 +8076,9 @@ #include "modular_nova\modules\tarkon\code\misc_fluff\research.dm" #include "modular_nova\modules\tarkon\code\misc_fluff\spawner.dm" #include "modular_nova\modules\tarkon\code\misc_fluff\tools.dm" +#include "modular_nova\modules\telepathy_quirk\code\telepathy_action.dm" +#include "modular_nova\modules\telepathy_quirk\code\telepathy_quirk.dm" +#include "modular_nova\modules\telepathy_quirk\code\telepathy_reply_emote.dm" #include "modular_nova\modules\tesh_augments\code\all_nodes.dm" #include "modular_nova\modules\tesh_augments\code\limbs.dm" #include "modular_nova\modules\tesh_augments\code\mechfabricator_designs.dm" @@ -8106,6 +8116,9 @@ #include "modular_nova\modules\trim_tokens\code\cards_ids.dm" #include "modular_nova\modules\trim_tokens\code\trim_tokens.dm" #include "modular_nova\modules\turretid\code\turret_id_system.dm" +#include "modular_nova\modules\underworld_connections\code\black_market_uplink.dm" +#include "modular_nova\modules\underworld_connections\code\underworld_connections_quirk.dm" +#include "modular_nova\modules\underworld_connections\code\markets\base_black_market.dm" #include "modular_nova\modules\verbs\code\looc.dm" #include "modular_nova\modules\verbs\code\say.dm" #include "modular_nova\modules\verbs\code\subtle.dm" diff --git a/tgui/packages/tgui/interfaces/ExaminePanel.jsx b/tgui/packages/tgui/interfaces/ExaminePanel.jsx index 7ed8129e4ba..b8807db8c24 100644 --- a/tgui/packages/tgui/interfaces/ExaminePanel.jsx +++ b/tgui/packages/tgui/interfaces/ExaminePanel.jsx @@ -43,6 +43,9 @@ export const ExaminePanel = (props) => { custom_species, custom_species_lore, headshot, + ideal_antag_optin_status, + current_antag_optin_status, + opt_in_colors = { optin, color }, } = data; return ( <Window title="Examine Panel" width={900} height={670} theme="admin"> @@ -105,6 +108,29 @@ export const ExaminePanel = (props) => { title="OOC Notes" preserveWhitespace > + {ideal_antag_optin_status && ( + <Stack.Item> + Current Antag Opt-In Status:{' '} + <span + style={{ + fontWeight: 'bold', + color: opt_in_colors[current_antag_optin_status], + }} + > + {current_antag_optin_status} + </span> + {'\n'} + Antag Opt-In Status {'(Preferences)'}:{' '} + <span + style={{ + color: opt_in_colors[ideal_antag_optin_status], + }} + > + {ideal_antag_optin_status} + </span> + {'\n\n'} + </Stack.Item> + )} {formatURLs(ooc_notes)} </Section> </Stack.Item> diff --git a/tgui/packages/tgui/interfaces/OpposingForcePanel.jsx b/tgui/packages/tgui/interfaces/OpposingForcePanel.jsx index 76d2f11b470..7f25e09847d 100644 --- a/tgui/packages/tgui/interfaces/OpposingForcePanel.jsx +++ b/tgui/packages/tgui/interfaces/OpposingForcePanel.jsx @@ -22,7 +22,7 @@ import { Window } from '../layouts'; export const OpposingForcePanel = (props) => { const [tab, setTab] = useState(1); const { act, data } = useBackend(); - const { admin_mode, creator_ckey, owner_antag } = data; + const { admin_mode, creator_ckey, owner_antag, opt_in_enabled } = data; return ( <Window title={'Opposing Force: ' + creator_ckey} @@ -74,6 +74,15 @@ export const OpposingForcePanel = (props) => { > Admin Chat </Tabs.Tab> + {!!opt_in_enabled && ( + <Tabs.Tab + width="100%" + selected={tab === 4} + onClick={() => setTab(4)} + > + Target List + </Tabs.Tab> + )} </> )} </Tabs> @@ -89,6 +98,7 @@ export const OpposingForcePanel = (props) => { {tab === 1 && <OpposingForceTab />} {tab === 2 && <EquipmentTab />} {tab === 3 && <AdminChatTab />} + {tab === 4 && <TargetTab />} </> )} </Window.Content> @@ -910,3 +920,39 @@ export const AdminTab = (props) => { </Stack> ); }; + +export const TargetTab = (props) => { + const { act, data } = useBackend(); + const { current_crew = [], opt_in_colors = { optin, color } } = data; + return ( + <Stack vertical fill> + <Stack.Item grow={10}> + <Section title="Currently active crew"> + {current_crew.map((crew) => ( + <Stack vertical={false} key={crew.name} pb="10px"> + <Stack.Item> + <span style={{ textDecoration: 'underline' }}>{crew.name}</span> + {': '} + {crew.rank}, Current Opt-In status:{' '} + <span + style={{ + fontWeight: 'bold', + color: opt_in_colors[crew.opt_in_status], + }} + > + {crew.opt_in_status} + </span> + , Ideal Opt-in status:{' '} + <span + style={{ color: opt_in_colors[crew.ideal_opt_in_status] }} + > + {crew.ideal_opt_in_status} + </span> + </Stack.Item> + </Stack> + ))} + </Section> + </Stack.Item> + </Stack> + ); +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/antag_optin.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/antag_optin.tsx new file mode 100644 index 00000000000..8e3032932a2 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/antag_optin.tsx @@ -0,0 +1,13 @@ +// THIS IS A NOVA SECTOR UI FILE +import { FeatureChoiced, FeatureDropdownInput } from '../../base'; + +export const antag_opt_in_status_pref: FeatureChoiced = { + name: 'Be Antagonist Target', + description: + 'This is for objective targetting and OOC consent.\ + By extension, picking "Round Remove" will allow you to be round removed in applicable situations, even by non-antagonists. \ + Enabling any non-ghost antags \ + (revenant, abductor contractor, etc.) will force your opt-in to be, \ + at minimum, "Temporarily Inconvenience".', + component: FeatureDropdownInput, +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/underworld_connections.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/underworld_connections.tsx new file mode 100644 index 00000000000..ce2d7763ffe --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/underworld_connections.tsx @@ -0,0 +1,22 @@ +// THIS IS A NOVA SECTOR UI FILE +import { + Feature, + FeatureChoiced, + FeatureDropdownInput, + FeatureShortTextInput, +} from '../../base'; + +export const underworld_uplink_skin: FeatureChoiced = { + name: 'Uplink Skin', + component: FeatureDropdownInput, +}; + +export const underworld_uplink_name: Feature<string> = { + name: 'Uplink Name', + component: FeatureShortTextInput, +}; + +export const underworld_uplink_desc: Feature<string> = { + name: 'Uplink Description', + component: FeatureShortTextInput, +};