Skip to content

Commit

Permalink
Merge pull request #4738 from MistakeNot4892/rework/unarmed
Browse files Browse the repository at this point in the history
Moving unarmed attacks onto limbs.
  • Loading branch information
out-of-phaze authored Jan 23, 2025
2 parents e22125b + 4261bc5 commit a8c82f3
Show file tree
Hide file tree
Showing 41 changed files with 215 additions and 199 deletions.
2 changes: 1 addition & 1 deletion code/game/machinery/camera/camera.dm
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
/obj/machinery/camera/physical_attack_hand(mob/living/human/user)
if(!istype(user))
return TRUE
if(user.species.can_shred(user))
if(user.can_shred())
user.do_attack_animation(src)
visible_message(SPAN_WARNING("\The [user] slashes at [src]!"))
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
Expand Down
12 changes: 5 additions & 7 deletions code/game/machinery/doors/windowdoor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,11 @@
return

/obj/machinery/door/window/physical_attack_hand(mob/user)
if(ishuman(user))
var/mob/living/human/H = user
if(H.species.can_shred(H))
playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("<span class='danger'>\The [user] smashes against \the [src].</span>", 1)
take_damage(25)
return TRUE
if(user.can_shred())
playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message(SPAN_DANGER("\The [user] smashes against \the [src]."))
take_damage(25)
return TRUE
return ..()

/obj/machinery/door/window/emag_act(var/remaining_charges, var/mob/user)
Expand Down
10 changes: 3 additions & 7 deletions code/game/objects/items/weapons/weaponry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,9 @@
/obj/effect/energy_net/attack_hand(var/mob/user)
if(!user.check_intent(I_FLAG_HARM))
return ..()
var/decl/species/my_species = user.get_species()
if(my_species)
if(my_species.can_shred(user))
playsound(src.loc, 'sound/weapons/slash.ogg', 80, 1)
current_health -= rand(10, 20)
else
current_health -= rand(1,3)
if(user.can_shred())
playsound(src.loc, 'sound/weapons/slash.ogg', 80, 1)
current_health -= rand(10, 20)
else
current_health -= rand(5,8)
to_chat(user, SPAN_DANGER("You claw at the energy net."))
Expand Down
3 changes: 1 addition & 2 deletions code/game/objects/structures/defensive_barrier.dm
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@
if(!user.check_dexterity(DEXTERITY_HOLD_ITEM, TRUE))
return ..()

var/decl/species/species = user.get_species()
if(ishuman(user) && species?.can_shred(user) && user.check_intent(I_FLAG_HARM))
if(user.can_shred() && user.check_intent(I_FLAG_HARM))
take_damage(20)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return TRUE
Expand Down
10 changes: 4 additions & 6 deletions code/game/objects/structures/grille.dm
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,10 @@

var/damage_dealt = 1
var/attack_message = "kicks"
if(ishuman(user))
var/mob/living/human/H = user
if(H.species.can_shred(H))
attack_message = "mangles"
damage_dealt = 5
attack_generic(user,damage_dealt,attack_message)
if(user.can_shred())
attack_message = "mangles"
damage_dealt = 5
attack_generic(user, damage_dealt, attack_message)
return TRUE

/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
Expand Down
22 changes: 12 additions & 10 deletions code/game/objects/structures/window.dm
Original file line number Diff line number Diff line change
Expand Up @@ -147,21 +147,23 @@
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if (user.check_intent(I_FLAG_HARM))

if (ishuman(user))
var/mob/living/human/H = user
if(H.species.can_shred(H))
return attack_generic(H,25)
if(user.can_shred())
return attack_generic(user, 25)

playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
user.do_attack_animation(src)
user.visible_message(SPAN_DANGER("\The [user] bangs against \the [src]!"),
SPAN_DANGER("You bang against \the [src]!"),
"You hear a banging sound.")
user.visible_message(
SPAN_DANGER("\The [user] bangs against \the [src]!"),
SPAN_DANGER("You bang against \the [src]!"),
"You hear a banging sound."
)
else
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
user.visible_message("[user.name] knocks on \the [src].",
"You knock on \the [src].",
"You hear a knocking sound.")
user.visible_message(
SPAN_NOTICE("\The [user] knocks on \the [src]."),
SPAN_NOTICE("You knock on \the [src]."),
"You hear a knocking sound."
)
return TRUE

/obj/structure/window/do_simple_ranged_interaction(var/mob/user)
Expand Down
24 changes: 9 additions & 15 deletions code/modules/mob/living/human/human_attackhand.dm
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/mob/living/human/proc/get_unarmed_attack(var/mob/target, var/hit_zone = null)
if(!hit_zone)
hit_zone = get_target_zone()
var/list/available_attacks = get_natural_attacks()
var/list/available_attacks = get_mob_natural_attacks()
var/decl/natural_attack/use_attack = default_attack
if(!use_attack || !use_attack.is_usable(src, target, hit_zone) || !(use_attack.type in available_attacks))
use_attack = null
var/list/other_attacks = list()
for(var/u_attack_type in available_attacks)
var/decl/natural_attack/u_attack = GET_DECL(u_attack_type)
for(var/decl/natural_attack/u_attack as anything in available_attacks)
if(!u_attack.is_usable(src, target, hit_zone))
continue
if(u_attack.is_starting_default)
Expand All @@ -18,11 +17,8 @@
use_attack = pick(other_attacks)
. = use_attack?.resolve_to_soft_variant(src)

/mob/living/human/proc/get_natural_attacks()
. = list()
for(var/obj/item/organ/external/limb in get_external_organs())
if(length(limb.unarmed_attacks) && limb.is_usable())
. |= limb.unarmed_attacks
/obj/item/organ/external/proc/get_natural_attacks()
return null

/obj/item/organ/external/proc/get_injury_status(include_pain = TRUE, include_visible = TRUE)
. = list()
Expand Down Expand Up @@ -409,14 +405,12 @@
set src = usr

var/list/choices
for(var/thing in get_natural_attacks())
var/decl/natural_attack/u_attack = GET_DECL(thing)
if(istype(u_attack))
var/image/radial_button = new
radial_button.name = capitalize(u_attack.name)
LAZYSET(choices, u_attack, radial_button)
for(var/decl/natural_attack/u_attack as anything in get_mob_natural_attacks())
var/image/radial_button = new
radial_button.name = capitalize(u_attack.name)
LAZYSET(choices, u_attack, radial_button)
var/decl/natural_attack/new_attack = show_radial_menu(src, (attack_selector || src), choices, radius = 42, use_labels = RADIAL_LABELS_OFFSET)
if(QDELETED(src) || !istype(new_attack) || !(new_attack.type in get_natural_attacks()))
if(QDELETED(src) || !istype(new_attack) || !(new_attack in get_mob_natural_attacks()))
return
default_attack = new_attack
to_chat(src, SPAN_NOTICE("Your default unarmed attack is now <b>[default_attack?.name || "cleared"]</b>."))
Expand Down
2 changes: 0 additions & 2 deletions code/modules/mob/living/human/human_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
var/mob/remoteview_target = null
var/hand_blood_color
var/list/flavor_texts = list()
/// Are you trying not to hurt your opponent?
var/pulling_punches
/// We are a robutt.
var/full_prosthetic
/// Number of robot limbs.
Expand Down
6 changes: 0 additions & 6 deletions code/modules/mob/living/human/human_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,3 @@
"<span class='danger'>[self ? "You pop" : "[U] pops"] your [current_limb.joint] back in!</span>" \
)
current_limb.undislocate()

/mob/living/human/verb/pull_punches()
set name = "Switch Stance"
set desc = "Try not to hurt them."
set category = "IC"
species.toggle_stance(src)
8 changes: 8 additions & 0 deletions code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2024,3 +2024,11 @@ default behaviour is:
// or things should just update their worn slot when coating is added
update_equipment_overlay(slot_shoes_str)
return TRUE

/mob/living/verb/pull_punches()
set name = "Switch Stance"
set desc = "Try not to hurt them."
set category = "IC"
if(!incapacitated())
pulling_punches = !pulling_punches
to_chat(src, SPAN_NOTICE("You are now [pulling_punches ? "pulling your punches" : "not pulling your punches"]."))
3 changes: 1 addition & 2 deletions code/modules/mob/living/living_resist.dm
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@
return 1

/mob/living/proc/can_break_restraints()
var/decl/species/my_species = get_species()
return my_species?.can_shred(src, 1)
return can_shred(ignore_intent = TRUE)

/mob/living/proc/get_special_resist_time()
return 0
Expand Down
3 changes: 1 addition & 2 deletions code/modules/mob/living/silicon/robot/robot.dm
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,7 @@
return user?.attempt_hug(src)

/mob/living/silicon/robot/default_hurt_interaction(mob/user)
var/decl/species/user_species = user.get_species()
if(user_species?.can_shred(user))
if(user.can_shred())
attack_generic(user, rand(30,50), "slashed")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return TRUE
Expand Down
21 changes: 21 additions & 0 deletions code/modules/mob/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1392,3 +1392,24 @@
paw = GET_EXTERNAL_ORGAN(src, BP_R_HAND)
if(istype(paw) && paw.is_usable())
return paw

// Called when using the shredding behavior.
/mob/proc/can_shred(var/mob/living/human/H, var/ignore_intent, var/ignore_antag)
if((!ignore_intent && !check_intent(I_FLAG_HARM)) || pulling_punches)
return FALSE
if(!ignore_antag && mind && !player_is_antag(mind))
return FALSE
if(get_equipped_item(slot_handcuffed_str) || buckled)
return FALSE
for(var/decl/natural_attack/attack as anything in get_mob_natural_attacks())
if(attack.is_usable(src) && attack.shredding)
return TRUE
return FALSE

/mob/proc/get_mob_natural_attacks()
for(var/obj/item/organ/external/limb in get_external_organs())
if(!limb.is_usable())
continue
var/list/limb_unarmed_attacks = limb.get_natural_attacks()
if(istype(limb_unarmed_attacks, /decl/natural_attack) || (islist(limb_unarmed_attacks) && length(limb_unarmed_attacks)))
LAZYDISTINCTADD(., limb_unarmed_attacks)
3 changes: 3 additions & 0 deletions code/modules/mob/mob_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,6 @@
// Offset the overhead text if necessary.
var/offset_overhead_text_x = 0
var/offset_overhead_text_y = 0

/// Are you trying not to hurt your opponent?
var/pulling_punches
6 changes: 0 additions & 6 deletions code/modules/organs/external/_external.dm
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@
var/stage = 0
var/cavity = 0

var/list/unarmed_attacks

var/atom/movable/applied_pressure
var/atom/movable/splinted

Expand Down Expand Up @@ -141,10 +139,6 @@
_icon_cache_key = null
. = ..()
skin_blend = bodytype.limb_blend
for(var/attack_type in species.unarmed_attacks)
var/decl/natural_attack/attack = GET_DECL(attack_type)
if(istype(attack) && (organ_tag in attack.usable_with_limbs))
LAZYADD(unarmed_attacks, attack_type)
update_icon()

/obj/item/organ/external/set_bodytype(decl/bodytype/new_bodytype, override_material = null, apply_to_internal_organs = TRUE)
Expand Down
18 changes: 18 additions & 0 deletions code/modules/organs/external/head.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@
var/forehead_graffiti
var/graffiti_style

/obj/item/organ/external/head/get_natural_attacks()
if(!can_intake_reagents)
return null
var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite)
return unarmed_attack

/obj/item/organ/external/head/sharp_bite/get_natural_attacks()
if(!can_intake_reagents)
return null
var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite/sharp)
return unarmed_attack

/obj/item/organ/external/head/strong_bite/get_natural_attacks()
if(!can_intake_reagents)
return null
var/static/unarmed_attack = GET_DECL(/decl/natural_attack/bite/strong)
return unarmed_attack

/obj/item/organ/external/head/proc/get_organ_eyes_overlay()
if(!glowing_eyes && !owner?.has_chemical_effect(CE_GLOWINGEYES, 1))
return
Expand Down
19 changes: 19 additions & 0 deletions code/modules/organs/external/standard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@
limb_flags = ORGAN_FLAG_CAN_AMPUTATE | ORGAN_FLAG_CAN_STAND | ORGAN_FLAG_HAS_TENDON | ORGAN_FLAG_CAN_BREAK | ORGAN_FLAG_CAN_DISLOCATE
organ_category = ORGAN_CATEGORY_STANCE

/obj/item/organ/external/foot/get_natural_attacks()
var/static/list/unarmed_attacks = list(
GET_DECL(/decl/natural_attack/stomp),
GET_DECL(/decl/natural_attack/kick)
)
return unarmed_attacks

/obj/item/organ/external/foot/right
organ_tag = BP_R_FOOT
name = "right foot"
Expand All @@ -139,6 +146,10 @@
is_washable = TRUE
var/gripper_type = /datum/inventory_slot/gripper/left_hand

/obj/item/organ/external/hand/get_natural_attacks()
var/static/unarmed_attack = GET_DECL(/decl/natural_attack/punch)
return unarmed_attack

/obj/item/organ/external/hand/do_install(mob/living/human/target, affected, in_place, update_icon, detached)
. = ..()
if(. && owner && gripper_type)
Expand All @@ -158,3 +169,11 @@
joint = "right wrist"
amputation_point = "right wrist"
gripper_type = /datum/inventory_slot/gripper/right_hand

/obj/item/organ/external/hand/clawed/get_natural_attacks()
var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws)
return unarmed_attack

/obj/item/organ/external/hand/right/clawed/get_natural_attacks()
var/static/unarmed_attack = GET_DECL(/decl/natural_attack/claws)
return unarmed_attack
4 changes: 2 additions & 2 deletions code/modules/paperwork/papershredder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
/obj/machinery/papershredder/proc/is_bin_empty()
return !(length(shredder_bin) > 0 && cached_total_matter)

/obj/machinery/papershredder/proc/can_shred(var/obj/item/I, var/mob/user = null)
/obj/machinery/papershredder/proc/can_shred_document(var/obj/item/I, var/mob/user = null)
if(!istype(I))
if(user)
to_chat(user, SPAN_WARNING("\The [I] cannot be shredded by \the [src]!"))
Expand Down Expand Up @@ -120,7 +120,7 @@
empty_bin(user, used_item)
return TRUE

else if(!trying_to_smack && can_shred(used_item))
else if(!trying_to_smack && can_shred_document(used_item))
shred(used_item, user)
return TRUE
return ..()
Expand Down
29 changes: 14 additions & 15 deletions code/modules/power/apc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -491,21 +491,20 @@ var/global/list/all_apcs = list()

/obj/machinery/power/apc/physical_attack_hand(mob/user)
//Human mob special interaction goes here.
if(ishuman(user))
var/mob/living/human/H = user

if(H.species.can_shred(H))
user.visible_message("<span class='warning'>\The [user] slashes at \the [src]!</span>", "<span class='notice'>You slash at \the [src]!</span>")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)

var/allcut = wires.IsAllCut()
if(beenhit >= pick(3, 4) && allcut == 0)
wires.CutAll()
src.update_icon()
src.visible_message("<span class='warning'>\The [src]'s wires are shredded!</span>")
else
beenhit += 1
return TRUE
if(user.can_shred())
user.visible_message(
SPAN_DANGER("\The [user] slashes at \the [src]!"),
SPAN_DANGER("You slash at \the [src]!")
)
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
var/allcut = wires.IsAllCut()
if(beenhit >= pick(3, 4) && allcut == 0)
wires.CutAll()
update_icon()
visible_message(SPAN_DANGER("\The [src]'s wires are shredded!"))
else
beenhit += 1
return TRUE
return FALSE

/obj/machinery/power/apc/interface_interact(mob/user)
Expand Down
13 changes: 7 additions & 6 deletions code/modules/power/lighting.dm
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,13 @@
to_chat(user, "There is no [get_fitting_name()] in this light.")
return TRUE

if(ishuman(user))
var/mob/living/human/H = user
if(H.species.can_shred(H))
visible_message("<span class='warning'>[user.name] smashed the light!</span>", 3, "You hear a tinkle of breaking glass.")
broken()
return TRUE
if(user.can_shred())
visible_message(
SPAN_DANGER("\The [user] smashes the light!"),
blind_message = "You hear a tinkle of breaking glass."
)
broken()
return TRUE

// make it burn hands if not wearing fire-insulated gloves
if(on)
Expand Down
Loading

0 comments on commit a8c82f3

Please sign in to comment.