diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index e8904f0bb1f..2e5d9beadaf 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -84,6 +84,8 @@ #define BODYTYPE_ALIEN (1<<3) ///The limb is from a golem #define BODYTYPE_GOLEM (1<<4) +//The limb is a peg limb +#define BODYTYPE_PEG (1<<5) // 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. @@ -95,7 +97,7 @@ ///The limb is snouted. #define BODYSHAPE_SNOUTED (1<<3) -#define BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE (BODYTYPE_ROBOTIC | BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_GOLEM) +#define BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE (BODYTYPE_ROBOTIC | BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_GOLEM | BODYTYPE_PEG) #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. @@ -135,6 +137,8 @@ #define BODYPART_ID_LARVA "larva" #define BODYPART_ID_PSYKER "psyker" #define BODYPART_ID_MEAT "meat" +#define BODYPART_ID_PEG "peg" + //See: datum/species/var/digitigrade_customization ///The species does not have digitigrade legs in generation. diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm index 42e00045761..feddc24c6f8 100644 --- a/code/__DEFINES/surgery.dm +++ b/code/__DEFINES/surgery.dm @@ -33,6 +33,8 @@ #define IS_ORGANIC_LIMB(limb) (limb.bodytype & BODYTYPE_ORGANIC) /// Helper to figure out if a limb is robotic #define IS_ROBOTIC_LIMB(limb) (limb.bodytype & BODYTYPE_ROBOTIC) +/// Helper to figure out if a limb is a peg limb +#define IS_PEG_LIMB(limb) (limb.bodytype & BODYTYPE_PEG) // Flags for the bodypart_flags var on /obj/item/bodypart /// Bodypart cannot be dismembered or amputated diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 17d9008a543..2d420339e18 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1153,5 +1153,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// This item cannot be selected for or used by a theft objective (Spies, Traitors, etc.) #define TRAIT_ITEM_OBJECTIVE_BLOCKED "item_objective_blocked" +/// This trait lets you attach limbs to any player without surgery. +#define TRAIT_EASY_ATTACH "easy_attach" // END TRAIT DEFINES diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 67f33d0460e..ead7b324cea 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -390,6 +390,7 @@ DEFINE_BITFIELD(bodytype, list( "BODYTYPE_LARVA_PLACEHOLDER" = BODYTYPE_LARVA_PLACEHOLDER, "BODYTYPE_ALIEN" = BODYTYPE_ALIEN, "BODYTYPE_GOLEM" = BODYTYPE_GOLEM, + "BODYTYPE_PEG" = BODYTYPE_PEG, )) DEFINE_BITFIELD(acceptable_bodytype, list( @@ -398,6 +399,7 @@ DEFINE_BITFIELD(acceptable_bodytype, list( "BODYTYPE_LARVA_PLACEHOLDER" = BODYTYPE_LARVA_PLACEHOLDER, "BODYTYPE_ALIEN" = BODYTYPE_ALIEN, "BODYTYPE_GOLEM" = BODYTYPE_GOLEM, + "BODYTYPE_PEG" = BODYTYPE_PEG, )) DEFINE_BITFIELD(bodyshape, list( diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 1fe465da39f..ba065653fe6 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -548,6 +548,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( /obj/item/bodypart = list( "TRAIT_PARALYSIS" = TRAIT_PARALYSIS, ), + /obj/item/bodypart = list( + "TRAIT_EASY_ATTACH" = TRAIT_EASY_ATTACH, + ), /obj/item/card/id = list( "TRAIT_JOB_FIRST_ID_CARD" = TRAIT_JOB_FIRST_ID_CARD, "TRAIT_MAGNETIC_ID_CARD" = TRAIT_MAGNETIC_ID_CARD, diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 7b6d4b62073..662f94c61d5 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -347,6 +347,12 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new /datum/stack_recipe("pew (left)", /obj/structure/chair/pew/left, 3, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), new /datum/stack_recipe("pew (right)", /obj/structure/chair/pew/right, 3, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE) )), + new/datum/stack_recipe_list("peg limbs", list( + new /datum/stack_recipe("peg arm (left)", /obj/item/bodypart/arm/left/ghetto, 2, crafting_flags = NONE, category = CAT_MISC), + new /datum/stack_recipe("peg arm (right)", /obj/item/bodypart/arm/right/ghetto, 2, crafting_flags = NONE, category = CAT_MISC), + new /datum/stack_recipe("peg leg (left)", /obj/item/bodypart/leg/left/ghetto, 2, crafting_flags = NONE, category = CAT_MISC), + new /datum/stack_recipe("peg leg (right)", /obj/item/bodypart/leg/right/ghetto, 2, crafting_flags = NONE, category = CAT_MISC) + )), null, \ )) @@ -377,6 +383,21 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ /obj/item/stack/sheet/mineral/wood/fifty amount = 50 +/obj/item/stack/sheet/mineral/wood/interact_with_atom(mob/living/carbon/human/target, mob/user) + if(!istype(target)) + return NONE + + var/obj/item/bodypart/affecting = target.get_bodypart(check_zone(user.zone_selected)) + if(affecting && IS_PEG_LIMB(affecting)) + if(user == target) + user.visible_message(span_notice("[user] starts to fix their [affecting.name]."), span_notice("You start fixing [target == user ? "your" : "[target]'s"] [affecting.name].")) + if(!do_after(user, 5 SECONDS, target)) + return ITEM_INTERACT_FAILURE + if(target.item_heal(user, brute_heal = 15, burn_heal = 15, heal_message_brute = "splintering", heal_message_burn = "charring", required_bodytype = BODYTYPE_PEG)) + use(1) + return ITEM_INTERACT_SUCCESS + else + return NONE /* * Bamboo */ diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 0e9b9743a45..b2b0109c04c 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -160,7 +160,7 @@ if(!use_tool(attacked_humanoid, user, use_delay, volume=50, amount=1)) return ITEM_INTERACT_BLOCKING - item_heal_robotic(attacked_humanoid, user, 15, 0) + attacked_humanoid.item_heal(user, brute_heal = 15, burn_heal = 0, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC) return ITEM_INTERACT_SUCCESS /obj/item/weldingtool/afterattack(atom/target, mob/user, click_parameters) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index da2c057d740..e588485aedc 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -360,3 +360,30 @@ var/damage = ((min_damage / 4) + (max_damage / 4)) / 2 // We expect you to have 4 functional limbs- if you have fewer you're probably not going to be so good at lifting return ceil(damage * (ceil(athletics_level / 2)) * fitness_modifier * maxHealth) + +/mob/living/carbon/human/proc/item_heal(mob/user, brute_heal, burn_heal, heal_message_brute, heal_message_burn, required_bodytype) + var/obj/item/bodypart/affecting = src.get_bodypart(check_zone(user.zone_selected)) + if (!affecting || !(affecting.bodytype == required_bodytype)) + to_chat(user, span_warning("[affecting] is already in good condition!")) + return FALSE + + var/brute_damaged = affecting.brute_dam > 0 + var/burn_damaged = affecting.burn_dam > 0 + + var/nothing_to_heal = ((brute_heal <= 0 || !brute_damaged) && (burn_heal <= 0 || !burn_damaged)) + if (nothing_to_heal) + to_chat(user, span_notice("[affecting] is already in good condition!")) + return FALSE + + src.update_damage_overlays() + var/message + if ((brute_damaged && brute_heal > 0) && (burn_damaged && burn_heal > 0)) + message = "[heal_message_brute] and [heal_message_burn] on" + else if (brute_damaged && brute_heal > 0) + message = "[heal_message_brute] on" + else + message = "[heal_message_burn] on" + affecting.heal_damage(brute_heal, burn_heal, required_bodytype) + user.visible_message(span_notice("[user] fixes some of the [message] [src]'s [affecting.name]."), \ + span_notice("You fix some of the [message] [src == user ? "your" : "[src]'s"] [affecting.name].")) + return TRUE diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 9092efac428..a6a1c58c7ed 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -331,19 +331,6 @@ toast.name = header toast.target_ref = WEAKREF(source) -/// Heals a robotic limb on a mob -/proc/item_heal_robotic(mob/living/carbon/human/human, mob/user, brute_heal, burn_heal) - var/obj/item/bodypart/affecting = human.get_bodypart(check_zone(user.zone_selected)) - if(!affecting || IS_ORGANIC_LIMB(affecting)) - to_chat(user, span_warning("[affecting] is already in good condition!")) - return FALSE - var/brute_damage = brute_heal > burn_heal //changes repair text based on how much brute/burn was supplied - if((brute_heal > 0 && affecting.brute_dam > 0) || (burn_heal > 0 && affecting.burn_dam > 0)) - if(affecting.heal_damage(brute_heal, burn_heal, required_bodytype = BODYTYPE_ROBOTIC)) - human.update_damage_overlays() - user.visible_message(span_notice("[user] fixes some of the [brute_damage ? "dents on" : "burnt wires in"] [human]'s [affecting.name]."), \ - span_notice("You fix some of the [brute_damage ? "dents on" : "burnt wires in"] [human == user ? "your" : "[human]'s"] [affecting.name].")) - return TRUE //successful heal ///Is the passed in mob a ghost with admin powers, doesn't check for AI interact like isAdminGhost() used to diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index e55442f31fd..a8e20cde8c7 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -575,7 +575,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri user.visible_message(span_notice("[user] starts to fix some of the wires in [H]'s [affecting.name]."), span_notice("You start fixing some of the wires in [H == user ? "your" : "[H]'s"] [affecting.name].")) if(!do_after(user, 5 SECONDS, H)) return - if(item_heal_robotic(H, user, 0, 15)) + if(H.item_heal(user, 0, 15, "dents", "burnt wires", BODYTYPE_ROBOTIC)) use(1) return else diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 318926465ae..c03a930395a 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -362,7 +362,7 @@ if(ishuman(victim)) var/mob/living/carbon/human/human_victim = victim - if(HAS_TRAIT(victim, TRAIT_LIMBATTACHMENT)) + if(HAS_TRAIT(victim, TRAIT_LIMBATTACHMENT) || HAS_TRAIT(src, TRAIT_EASY_ATTACH)) if(!human_victim.get_bodypart(body_zone)) user.temporarilyRemoveItemFromInventory(src, TRUE) if(!try_attach_limb(victim)) diff --git a/code/modules/surgery/bodyparts/ghetto_parts.dm b/code/modules/surgery/bodyparts/ghetto_parts.dm new file mode 100644 index 00000000000..36c0310dead --- /dev/null +++ b/code/modules/surgery/bodyparts/ghetto_parts.dm @@ -0,0 +1,79 @@ +/obj/item/bodypart/arm/left/ghetto + name = "left peg arm" + desc = "A roughly hewn wooden peg replaces where a forearm should be. It's simple and sturdy, clearly made in a hurry with whatever materials were at hand. Despite its crude appearance, it gets the job done." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_l_arm" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + attack_verb_simple = list("bashed", "slashed") + unarmed_damage_low = 3 + unarmed_damage_high = 9 + unarmed_effectiveness = 5 + brute_modifier = 1.2 + burn_modifier = 1.5 + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/arm/left/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) + +/obj/item/bodypart/arm/right/ghetto + name = "right peg arm" + desc = "A roughly hewn wooden peg replaces where a forearm should be. It's simple and sturdy, clearly made in a hurry with whatever materials were at hand. Despite its crude appearance, it gets the job done." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_r_arm" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + attack_verb_simple = list("bashed", "slashed") + unarmed_damage_low = 3 + unarmed_damage_high = 9 + unarmed_effectiveness = 5 + brute_modifier = 1.2 + burn_modifier = 1.5 + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/arm/right/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) + +/obj/item/bodypart/leg/left/ghetto + name = "left peg leg" + desc = "Fashioned from what looks suspiciously like a table leg, this peg leg brings a whole new meaning to 'dining on the go.' It's a bit wobbly and creaks ominously with every step, but at least you can claim to have the most well-balanced diet on the seven seas." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_l_leg" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + unarmed_damage_low = 2 + unarmed_damage_high = 5 + unarmed_effectiveness = 10 + brute_modifier = 1.2 + burn_modifier = 1.5 + +/obj/item/bodypart/leg/left/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) + +/obj/item/bodypart/leg/right/ghetto + name = "right peg leg" + desc = "Fashioned from what looks suspiciously like a table leg, this peg leg brings a whole new meaning to 'dining on the go.' It's a bit wobbly and creaks ominously with every step, but at least you can claim to have the most well-balanced diet on the seven seas." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_r_leg" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + unarmed_damage_low = 2 + unarmed_damage_high = 5 + unarmed_effectiveness = 10 + brute_modifier = 1.2 + burn_modifier = 1.5 + +/obj/item/bodypart/leg/right/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) diff --git a/icons/mob/human/bodyparts.dmi b/icons/mob/human/bodyparts.dmi index d6e4472973a..78be880423c 100644 Binary files a/icons/mob/human/bodyparts.dmi and b/icons/mob/human/bodyparts.dmi differ diff --git a/icons/mob/human/species/ghetto.dmi b/icons/mob/human/species/ghetto.dmi new file mode 100644 index 00000000000..e11701428eb Binary files /dev/null and b/icons/mob/human/species/ghetto.dmi differ diff --git a/tgstation.dme b/tgstation.dme index dd55b451101..b6ddcc5e209 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5879,6 +5879,7 @@ #include "code\modules\surgery\advanced\bioware\vein_threading.dm" #include "code\modules\surgery\bodyparts\_bodyparts.dm" #include "code\modules\surgery\bodyparts\dismemberment.dm" +#include "code\modules\surgery\bodyparts\ghetto_parts.dm" #include "code\modules\surgery\bodyparts\head.dm" #include "code\modules\surgery\bodyparts\head_hair_and_lips.dm" #include "code\modules\surgery\bodyparts\helpers.dm"