Skip to content

Commit

Permalink
[MIRROR] Malicious Intent - adds mauling people with entrenching tool…
Browse files Browse the repository at this point in the history
…s and machetes (#5276)

* Malicious Intent - adds mauling people with entrenching tools and machetes (#4701)

* Put the boots to him. Well-done.

* the war

* the rule of beasts

* bad at amputating

---------

Co-authored-by: Hatterhat <[email protected]>

* [MIRROR] Malicious Intent - adds mauling people with entrenching tools and machetes

---------

Co-authored-by: Hatterhat <[email protected]>
Co-authored-by: Hatterhat <[email protected]>
Co-authored-by: StealsThePRs <[email protected]>
  • Loading branch information
4 people authored Jan 8, 2025
1 parent 7a406b9 commit 49916cc
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 0 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/inventory.dm
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ GLOBAL_LIST_INIT(security_vest_allowed, list(
/obj/item/storage/belt/holster/energy,
/obj/item/gun/ballistic/shotgun/automatic/combat/compact,
/obj/item/pen/red/security,
/obj/item/storage/belt/machete, // NOVA EDIT ADDITION
))

GLOBAL_LIST_INIT(security_wintercoat_allowed, list(
Expand All @@ -268,6 +269,7 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, list(
/obj/item/storage/belt/holster/nukie,
/obj/item/storage/belt/holster/energy,
/obj/item/gun/ballistic/shotgun/automatic/combat/compact,
/obj/item/storage/belt/machete, // NOVA EDIT ADDITION
))

//Allowed list for all chaplain suits (except the honkmother robe)
Expand Down Expand Up @@ -304,6 +306,7 @@ GLOBAL_LIST_INIT(mining_suit_allowed, list(
/obj/item/spear,
/obj/item/forging/reagent_weapon, // NOVA EDIT ADDITION
/obj/item/gun/ballistic/bow, // NOVA EDIT ADDITION
/obj/item/storage/belt/machete, // NOVA EDIT ADDITION
))

/// String for items placed into the left pocket.
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/~nova_defines/colony_fabricator_misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ GLOBAL_LIST_INIT(colonist_suit_allowed, list(
/obj/item/storage/medkit,
/obj/item/fireaxe/metal_h2_axe,
/obj/item/forging/reagent_weapon,
/obj/item/storage/belt/machete,
))
12 changes: 12 additions & 0 deletions modular_nova/master_files/code/modules/surgery/amputation.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/datum/surgery_step/sever_limb/New()
implements += list(
/obj/item/machete = 75,
)
return ..()

// doesn't work on robo limbs
/datum/surgery_step/sever_limb/mechanic/New()
. = ..()
implements -= list(
/obj/item/machete,
)
Binary file added modular_nova/modules/mauling_melees/icons/back.dmi
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
95 changes: 95 additions & 0 deletions modular_nova/modules/mauling_melees/mauling_element.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* The mauling element, adapted nearly wholesale from kneecapping, replaces the item's secondary attack with an aimed attack at limbs under certain circumstances.
*
* Element is incompatible with non-items. Requires the parent item to have a force equal to or greater than WOUND_MINIMUM_DAMAGE.
* Also requires that the parent can actually get past pre_secondary_attack without the attack chain cancelling.
*
* As kneecapping, mauling attacks have a wounding bonus between severe and critical+10 wound thresholds. Without some serious wound protecting
* armour this all but guarantees a wound of some sort. The attack is directed specifically at a limb and the limb takes the damage.
*
* Requires the attacker to be aiming for a limb, which will be targeted specifically. They will than have a 3-second long
* do_after before executing the attack.
*
* Mauling, much like kneecapping, requires the target to either be on the floor, immobilised or buckled to something. And also to have an appropriate limb.
*
* Passing all the checks will cancel the entire attack chain.
*/
/datum/element/mauling

/datum/element/mauling/Attach(datum/target)
if(!isitem(target))
stack_trace("Mauling element added to non-item object: \[[target]\]")
return ELEMENT_INCOMPATIBLE

var/obj/item/target_item = target

if(target_item.force < WOUND_MINIMUM_DAMAGE)
stack_trace("Mauling element added to item with too little force to wound: \[[target]\]")
return ELEMENT_INCOMPATIBLE

. = ..()

if(. == ELEMENT_INCOMPATIBLE)
return

RegisterSignal(target, COMSIG_ITEM_ATTACK_SECONDARY , PROC_REF(try_maul_target))

/datum/element/mauling/Detach(datum/target)
UnregisterSignal(target, COMSIG_ITEM_ATTACK_SECONDARY)

return ..()

/**
* Signal handler for COMSIG_ITEM_ATTACK_SECONDARY. Does checks for pacifism, zones and target state before either returning nothing
* if the special attack could not be attempted, performing the ordinary attack procs instead - Or cancelling the attack chain if
* the attack can be started.
*/
/datum/element/mauling/proc/try_maul_target(obj/item/source, mob/living/carbon/target, mob/attacker, params)
SIGNAL_HANDLER

if(HAS_TRAIT(attacker, TRAIT_PACIFISM))
return

if(!iscarbon(target))
return

if(!target.buckled && !HAS_TRAIT(target, TRAIT_FLOORED) && !HAS_TRAIT(target, TRAIT_IMMOBILIZED))
return

var/obj/item/bodypart/limb_target = target.get_bodypart(attacker.zone_selected)

if(!limb_target)
return

. = COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN

INVOKE_ASYNC(src, PROC_REF(do_maul_target), source, limb_target, target, attacker)

/**
* After a short do_after, attacker applies damage to the given limb with a significant wounding bonus, applying the weapon's force as damage.
*/
/datum/element/mauling/proc/do_maul_target(obj/item/weapon, obj/item/bodypart/limb, mob/living/carbon/target, mob/attacker)
if(LAZYACCESS(attacker.do_afters, weapon))
return

attacker.visible_message(span_warning("[attacker] carefully aims [attacker.p_their()] [weapon] at [target]'s [limb.plaintext_zone]!"), span_danger("You carefully aim \the [weapon] for a swing at [target]'s [limb.plaintext_zone]!"))
log_combat(attacker, target, "started aiming a swing to maul", weapon)

if(do_after(attacker, 3 SECONDS, target, interaction_key = weapon))
attacker.visible_message(span_warning("[attacker] swings [attacker.p_their()] [weapon] at [target]'s [limb.plaintext_zone]!"), span_danger("You swing \the [weapon] at [target]'s [limb.plaintext_zone]!"))
var/wound_to_inflict = WOUND_BLUNT
if(weapon.sharpness & SHARP_EDGED)
wound_to_inflict = WOUND_SLASH
else if(weapon.sharpness & SHARP_POINTY)
wound_to_inflict = WOUND_PIERCE
var/min_wound = limb.get_wound_threshold_of_wound_type(wound_to_inflict, WOUND_SEVERITY_SEVERE, return_value_if_no_wound = 30, wound_source = weapon)
var/max_wound = limb.get_wound_threshold_of_wound_type(wound_to_inflict, WOUND_SEVERITY_CRITICAL, return_value_if_no_wound = 50, wound_source = weapon)

limb.receive_damage(brute = weapon.force, wound_bonus = rand(min_wound, max_wound + 10), sharpness = weapon.sharpness, damage_source = "mauling")
// make sure we're actually able to feel pain
if(!target.has_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy))
target.emote("scream")
log_combat(attacker, target, "mauled", weapon)
target.update_damage_overlays()
attacker.do_attack_animation(target, used_item = weapon)
playsound(source = get_turf(weapon), soundin = weapon.hitsound, vol = weapon.get_clamped_volume(), vary = TRUE)
138 changes: 138 additions & 0 deletions modular_nova/modules/mauling_melees/mauling_melees.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/obj/item/machete
name = "surplus machete"
icon = 'modular_nova/modules/mauling_melees/icons/objects.dmi'
icon_state = "machete"
lefthand_file = 'modular_nova/modules/mauling_melees/icons/lefthands.dmi'
righthand_file = 'modular_nova/modules/mauling_melees/icons/righthands.dmi'
inhand_icon_state = "machete"
desc = "An nondescript machete with a rubberized, non-conductive handle. Could be from some old military surplus, or from a recent stockpile, or anywhere in between. \
Good for hacking away at things, like plants, people, or plantpeople."
obj_flags = NONE
force = 20
w_class = WEIGHT_CLASS_BULKY
throwforce = 10
hitsound = 'sound/items/weapons/bladeslice.ogg'
throw_speed = 1
throw_range = 5
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6)
attack_verb_continuous = list("slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts")
attack_verb_simple = list("slash", "slice", "tear", "lacerate", "rip", "dice", "cut")
sharpness = SHARP_EDGED
armor_type = /datum/armor/item_knife
wound_bonus = 10
bare_wound_bonus = 20
tool_behaviour = TOOL_KNIFE
/*
20 force, 10 wb, 20 bwb = 30, 50 against bare skin
compare/contrast force/wound bonuses with the captain's sabre, i guess
which at time of writing is 20 force 5 wb 20 bwb = 25, 45 against bare skin, BUT has 75 AP/50 melee-only blockchance
the shamshir also has the same damage/wound stats but "only" 25 AP/20 blockchance
*/

/obj/item/machete/Initialize(mapload)
. = ..()
// not great for butchering. kind of unwieldy for doing so
AddComponent(/datum/component/butchering, \
speed = 6 SECONDS, \
effectiveness = 80, \
bonus_modifier = force - 10, \
)
// but it's good for murdering plantpeople
AddElement(/datum/element/bane, mob_biotypes = MOB_PLANT, damage_multiplier = 0.5, requires_combat_mode = FALSE)
// Kill.
AddElement(/datum/element/mauling)

/obj/item/machete/afterattack(atom/target, mob/user, click_parameters)
. = ..()
if(target.resistance_flags & INDESTRUCTIBLE)
return
if(istype(target, /obj/structure/flora))
var/obj/structure/flora/flora_target = target
if(!(flora_target.flora_flags & FLORA_HERBAL) && !(flora_target.flora_flags & FLORA_WOODEN))
return
target.take_damage(force) // simulate taking double damage

#define MACHETE_BACK 0
#define MACHETE_WAIST 1
#define MACHETE_LEG 2
/obj/item/storage/belt/machete
name = "surplus machete scabbard"
desc = "A large synthetic-leather scabbard used to carry some kind of machete. A compact set of buckles suggests the ability to be strapped to the back, waist, or some kinds of armor."
icon = 'modular_nova/modules/mauling_melees/icons/objects.dmi'
worn_icon = 'modular_nova/modules/mauling_melees/icons/back.dmi'
lefthand_file = 'modular_nova/modules/mauling_melees/icons/lefthands.dmi'
righthand_file = 'modular_nova/modules/mauling_melees/icons/righthands.dmi'
icon_state = "msheath"
inhand_icon_state = "msheath"
worn_icon_state = "msheath"
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK | ITEM_SLOT_SUITSTORE
/// Used for deciding the worn icon_state variant, using defines for MACHETE_BACK, MACHETE_WAIST, MACHETE_LEG.
var/worn_variant = MACHETE_BACK

/obj/item/storage/belt/machete/Initialize(mapload)
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
atom_storage.max_slots = 1
// not a rifle but this is the sound tgmc uses
atom_storage.rustle_sound = 'modular_nova/modules/mauling_melees/sounds/rifle_draw.ogg'
atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
atom_storage.set_holdable(/obj/item/machete)
atom_storage.click_alt_open = FALSE
RegisterSignal(atom_storage, COMSIG_STORAGE_REMOVED_ITEM, PROC_REF(on_item_removed))

/obj/item/storage/belt/machete/examine(mob/user)
. = ..()
if(length(contents))
. += span_notice("Alt-click it to quickly draw the blade.")

/obj/item/storage/belt/machete/click_alt(mob/user)
for(var/obj/item/machete/machete in contents)
user.visible_message(span_notice("[user] takes [machete] out of [src]."), span_notice("You take [machete] out of [src]."))
machete.remove_item_from_storage(user)
user.put_in_hands(machete)
update_appearance()
return CLICK_ACTION_SUCCESS
balloon_alert(user, "it's empty!")

/obj/item/storage/belt/machete/update_icon_state()
icon_state = initial(icon_state)
inhand_icon_state = initial(inhand_icon_state)
worn_icon_state = initial(worn_icon_state)
worn_icon_state += "[worn_variant]"
if(contents.len)
icon_state += "-full"
inhand_icon_state += "-full"
worn_icon_state += "-full"
return ..()

/obj/item/storage/belt/machete/full/PopulateContents()
new /obj/item/machete(src)
update_appearance()

/// triggers on item removal from the scabbard - plays a draw sound, which should be the rustle sound
/// had to snowflake it because remove rustle sounds are. never triggered in the code. funnily enough
/obj/item/storage/belt/machete/proc/on_item_removed()
SIGNAL_HANDLER
playsound(src, atom_storage.rustle_sound, 50, TRUE, -5)

/// alt rmb to change wear style
/obj/item/storage/belt/machete/click_alt_secondary(mob/user)
switch(worn_variant)
if (MACHETE_BACK)
worn_variant = MACHETE_WAIST
to_chat(user, "You adjust [src] to hang sideways behind your back.")
if (MACHETE_WAIST)
worn_variant = MACHETE_LEG
to_chat(user, "You adjust [src] to hang down your leg.")
if (MACHETE_LEG)
worn_variant = MACHETE_BACK
to_chat(user, "You adjust [src] to hang across your back.")
update_appearance()

#undef MACHETE_BACK
#undef MACHETE_WAIST
#undef MACHETE_LEG

/obj/item/trench_tool/Initialize(mapload)
. = ..()
AddElement(/datum/element/mauling)
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
/obj/item/storage/pouch/medical/firstaid/advanced = ITEM_WEIGHT_MISC_BUT_RARER,
// maybe not junk
/obj/item/knife/combat/throwing = ITEM_WEIGHT_MISC_BUT_RARER,
/obj/item/storage/belt/machete/full = ITEM_WEIGHT_MISC_BUT_RARER,
/obj/item/storage/medkit/expeditionary/surplus = ITEM_WEIGHT_MISC_BUT_RARER,
/obj/item/pointman_broken = ITEM_WEIGHT_GUN_RARE, // diy project for a shield that you can wield for 75 blockchance + beat people to death with
/obj/item/clothing/gloves/chief_engineer/expeditionary_corps = ITEM_WEIGHT_MISC_BUT_RARER, // congratulations you won (it's basically combat gloves but not quite)
Expand Down
3 changes: 3 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -7020,6 +7020,7 @@
#include "modular_nova\master_files\code\modules\research\techweb\all_nodes.dm"
#include "modular_nova\master_files\code\modules\shuttle\shuttle.dm"
#include "modular_nova\master_files\code\modules\shuttle\shuttle_events\meteors.dm"
#include "modular_nova\master_files\code\modules\surgery\amputation.dm"
#include "modular_nova\master_files\code\modules\surgery\surgery.dm"
#include "modular_nova\master_files\code\modules\surgery\bodyparts\_bodyparts.dm"
#include "modular_nova\master_files\code\modules\surgery\bodyparts\head.dm"
Expand Down Expand Up @@ -8024,6 +8025,8 @@
#include "modular_nova\modules\marines\code\mod.dm"
#include "modular_nova\modules\marines\code\modsuit_modules.dm"
#include "modular_nova\modules\marines\code\smartgun.dm"
#include "modular_nova\modules\mauling_melees\mauling_element.dm"
#include "modular_nova\modules\mauling_melees\mauling_melees.dm"
#include "modular_nova\modules\medical\code\anesthetic_machine.dm"
#include "modular_nova\modules\medical\code\carbon_examine.dm"
#include "modular_nova\modules\medical\code\carbon_update_icons.dm"
Expand Down

0 comments on commit 49916cc

Please sign in to comment.