Skip to content

Commit

Permalink
Changes to disarm / CQC code (#3970)
Browse files Browse the repository at this point in the history
# About the pull request

It was broken so disarm chance changing for CQC didn't work.
Makes how long disarms stun you for a difference between CQC skills.
Plus general code changes.

# Explain why it's good for the game

bug bad lol

# Changelog

:cl:
add: How long disarm stuns for depends on the difference in CQC skill
between the participants
fix: CQC properly affects disarm chance again
/:cl:
  • Loading branch information
BeagleGaming1 committed Jul 24, 2023
1 parent 8a1c6cc commit 4a6938e
Showing 1 changed file with 65 additions and 69 deletions.
134 changes: 65 additions & 69 deletions code/modules/mob/living/carbon/human/human_attackhand.dm
Original file line number Diff line number Diff line change
@@ -1,189 +1,185 @@
/mob/living/carbon/human/var/cpr_cooldown
/mob/living/carbon/human/var/cpr_attempt_timer
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M)
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/attacking_mob)
if(..())
return TRUE

if((M != src) && check_shields(0, M.name))
visible_message(SPAN_DANGER("<B>[M] attempted to touch [src]!</B>"), null, null, 5)
if((attacking_mob != src) && check_shields(0, attacking_mob.name))
visible_message(SPAN_DANGER("<B>[attacking_mob] attempted to touch [src]!</B>"), null, null, 5)
return 0

switch(M.a_intent)
switch(attacking_mob.a_intent)
if(INTENT_HELP)

if(on_fire && M != src)
if(on_fire && attacking_mob != src)
adjust_fire_stacks(-10, min_stacks = 0)
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 25, 1, 7)
M.visible_message(SPAN_DANGER("[M] tries to put out the fire on [src]!"), \
attacking_mob.visible_message(SPAN_DANGER("[attacking_mob] tries to put out the fire on [src]!"), \
SPAN_WARNING("You try to put out the fire on [src]!"), null, 5)
if(fire_stacks <= 0)
M.visible_message(SPAN_DANGER("[M] has successfully extinguished the fire on [src]!"), \
attacking_mob.visible_message(SPAN_DANGER("[attacking_mob] has successfully extinguished the fire on [src]!"), \
SPAN_NOTICE("You extinguished the fire on [src]."), null, 5)
return 1

// If unconcious with oxygen damage, do CPR. If dead, we do CPR
if(!(stat == UNCONSCIOUS && getOxyLoss() > 0) && !(stat == DEAD))
help_shake_act(M)
help_shake_act(attacking_mob)
return 1

if(M.head && (M.head.flags_inventory & COVERMOUTH) || M.wear_mask && (M.wear_mask.flags_inventory & COVERMOUTH) && !(M.wear_mask.flags_inventory & ALLOWCPR))
to_chat(M, SPAN_NOTICE("<B>Remove your mask!</B>"))
if(attacking_mob.head && (attacking_mob.head.flags_inventory & COVERMOUTH) || attacking_mob.wear_mask && (attacking_mob.wear_mask.flags_inventory & COVERMOUTH) && !(attacking_mob.wear_mask.flags_inventory & ALLOWCPR))
to_chat(attacking_mob, SPAN_NOTICE("<B>Remove your mask!</B>"))
return 0
if(head && (head.flags_inventory & COVERMOUTH) || wear_mask && (wear_mask.flags_inventory & COVERMOUTH) && !(wear_mask.flags_inventory & ALLOWCPR))
to_chat(M, SPAN_NOTICE("<B>Remove [src.gender==MALE?"his":"her"] mask!</B>"))
to_chat(attacking_mob, SPAN_NOTICE("<B>Remove [src.gender==MALE?"his":"her"] mask!</B>"))
return 0
if(cpr_attempt_timer >= world.time)
to_chat(M, SPAN_NOTICE("<B>CPR is already being performed on [src]!</B>"))
to_chat(attacking_mob, SPAN_NOTICE("<B>CPR is already being performed on [src]!</B>"))
return 0

//CPR
if(M.action_busy)
if(attacking_mob.action_busy)
return 1

M.visible_message(SPAN_NOTICE("<b>[M]</b> starts performing <b>CPR</b> on <b>[src]</b>."),
attacking_mob.visible_message(SPAN_NOTICE("<b>[attacking_mob]</b> starts performing <b>CPR</b> on <b>[src]</b>."),
SPAN_HELPFUL("You start <b>performing CPR</b> on <b>[src]</b>."))

cpr_attempt_timer = world.time + HUMAN_STRIP_DELAY * M.get_skill_duration_multiplier(SKILL_MEDICAL)
if(do_after(M, HUMAN_STRIP_DELAY * M.get_skill_duration_multiplier(SKILL_MEDICAL), INTERRUPT_ALL, BUSY_ICON_GENERIC, src, INTERRUPT_MOVED, BUSY_ICON_MEDICAL))
cpr_attempt_timer = world.time + HUMAN_STRIP_DELAY * attacking_mob.get_skill_duration_multiplier(SKILL_MEDICAL)
if(do_after(attacking_mob, HUMAN_STRIP_DELAY * attacking_mob.get_skill_duration_multiplier(SKILL_MEDICAL), INTERRUPT_ALL, BUSY_ICON_GENERIC, src, INTERRUPT_MOVED, BUSY_ICON_MEDICAL))
if(stat != DEAD)
var/suff = min(getOxyLoss(), 10) //Pre-merge level, less healing, more prevention of dieing.
apply_damage(-suff, OXY)
updatehealth()
src.affected_message(M,
src.affected_message(attacking_mob,
SPAN_HELPFUL("You feel a <b>breath of fresh air</b> enter your lungs. It feels good."),
SPAN_HELPFUL("You <b>perform CPR</b> on <b>[src]</b>. Repeat at least every <b>7 seconds</b>."),
SPAN_NOTICE("<b>[M]</b> performs <b>CPR</b> on <b>[src]</b>."))
SPAN_NOTICE("<b>[attacking_mob]</b> performs <b>CPR</b> on <b>[src]</b>."))
if(is_revivable() && stat == DEAD)
if(cpr_cooldown < world.time)
revive_grace_period += 7 SECONDS
M.visible_message(SPAN_NOTICE("<b>[M]</b> performs <b>CPR</b> on <b>[src]</b>."),
attacking_mob.visible_message(SPAN_NOTICE("<b>[attacking_mob]</b> performs <b>CPR</b> on <b>[src]</b>."),
SPAN_HELPFUL("You perform <b>CPR</b> on <b>[src]</b>."))
else
M.visible_message(SPAN_NOTICE("<b>[M]</b> fails to perform CPR on <b>[src]</b>."),
attacking_mob.visible_message(SPAN_NOTICE("<b>[attacking_mob]</b> fails to perform CPR on <b>[src]</b>."),
SPAN_HELPFUL("You <b>fail</b> to perform <b>CPR</b> on <b>[src]</b>. Incorrect rhythm. Do it <b>slower</b>."))
cpr_cooldown = world.time + 7 SECONDS
cpr_attempt_timer = 0
return 1

if(INTENT_GRAB)
if(M == src)
if(attacking_mob == src)
check_for_injuries()
return 1

if(anchored)
return 0

if(w_uniform)
w_uniform.add_fingerprint(M)

M.start_pulling(src)
w_uniform.add_fingerprint(attacking_mob)

attacking_mob.start_pulling(src)
return 1

if(INTENT_HARM)
// See if they can attack, and which attacks to use.
var/datum/unarmed_attack/attack = M.species.unarmed
if(!attack.is_usable(M)) attack = M.species.secondary_unarmed
if(!attack.is_usable(M)) return
var/datum/unarmed_attack/attack = attacking_mob.species.unarmed
if(!attack.is_usable(attacking_mob))
attack = attacking_mob.species.secondary_unarmed
return

last_damage_data = create_cause_data("fisticuffs", src)
M.attack_log += text("\[[time_stamp()]\] <font color='red'>[pick(attack.attack_verb)]ed [key_name(src)]</font>")
attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [pick(attack.attack_verb)]ed by [key_name(M)]</font>")
msg_admin_attack("[key_name(M)] [pick(attack.attack_verb)]ed [key_name(src)] in [get_area(src)] ([src.loc.x],[src.loc.y],[src.loc.z]).", src.loc.x, src.loc.y, src.loc.z)
attacking_mob.attack_log += text("\[[time_stamp()]\] <font color='red'>[pick(attack.attack_verb)]ed [key_name(src)]</font>")
attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [pick(attack.attack_verb)]ed by [key_name(attacking_mob)]</font>")
msg_admin_attack("[key_name(attacking_mob)] [pick(attack.attack_verb)]ed [key_name(src)] in [get_area(src)] ([src.loc.x],[src.loc.y],[src.loc.z]).", src.loc.x, src.loc.y, src.loc.z)

M.animation_attack_on(src)
M.flick_attack_overlay(src, "punch")
attacking_mob.animation_attack_on(src)
attacking_mob.flick_attack_overlay(src, "punch")

var/extra_cqc_dmg = 0 //soft maximum of 5, this damage is added onto the final value depending on how much cqc skill you have
if(M.skills)
extra_cqc_dmg = M.skills?.get_skill_level(SKILL_CQC)
if(attacking_mob.skills)
extra_cqc_dmg = attacking_mob.skills?.get_skill_level(SKILL_CQC)
var/raw_damage = 0 //final value, gets absorbed by the armor and then deals the leftover to the mob

var/obj/limb/affecting = get_limb(rand_zone(M.zone_selected, 70))
var/obj/limb/affecting = get_limb(rand_zone(attacking_mob.zone_selected, 70))
var/armor = getarmor(affecting, ARMOR_MELEE)

playsound(loc, attack.attack_sound, 25, 1)

visible_message(SPAN_DANGER("[M] [pick(attack.attack_verb)]ed [src]!"), null, null, 5)
visible_message(SPAN_DANGER("[attacking_mob] [pick(attack.attack_verb)]ed [src]!"), null, null, 5)

raw_damage = attack.damage + extra_cqc_dmg
var/final_damage = armor_damage_reduction(GLOB.marine_melee, raw_damage, armor, FALSE) // no penetration from punches
apply_damage(final_damage, BRUTE, affecting, sharp=attack.sharp, edge = attack.edge)

if(INTENT_DISARM)
if(M == src)
if(attacking_mob == src)
check_for_injuries()
return 1

M.attack_log += text("\[[time_stamp()]\] <font color='red'>Disarmed [key_name(src)]</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been disarmed by [key_name(M)]</font>")
attacking_mob.attack_log += text("\[[time_stamp()]\] <font color='red'>Disarmed [key_name(src)]</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been disarmed by [key_name(attacking_mob)]</font>")

M.animation_attack_on(src)
M.flick_attack_overlay(src, "disarm")
attacking_mob.animation_attack_on(src)
attacking_mob.flick_attack_overlay(src, "disarm")

msg_admin_attack("[key_name(M)] disarmed [key_name(src)] in [get_area(src)] ([src.loc.x],[src.loc.y],[src.loc.z]).", src.loc.x, src.loc.y, src.loc.z)
msg_admin_attack("[key_name(attacking_mob)] disarmed [key_name(src)] in [get_area(src)] ([src.loc.x],[src.loc.y],[src.loc.z]).", src.loc.x, src.loc.y, src.loc.z)

if(w_uniform)
w_uniform.add_fingerprint(M)
w_uniform.add_fingerprint(attacking_mob)

//Accidental gun discharge
if(!skillcheck(M, SKILL_CQC, SKILL_CQC_SKILLED))
if(!skillcheck(attacking_mob, SKILL_CQC, SKILL_CQC_SKILLED))
if (isgun(r_hand) || isgun(l_hand))
var/obj/item/weapon/gun/W = null
var/obj/item/weapon/gun/held_weapon = null
var/chance = 0

if (isgun(l_hand))
W = l_hand
held_weapon = l_hand
chance = hand ? 40 : 20

if (isgun(r_hand))
W = r_hand
held_weapon = r_hand
chance = !hand ? 40 : 20

if (prob(chance))
visible_message(SPAN_DANGER("[M] accidentally makes [src]'s [W.name] go off during the struggle!"), SPAN_DANGER("You accidentally make [src]'s [W.name] go off during the struggle!"), null, 5)
visible_message(SPAN_DANGER("[attacking_mob] accidentally makes [src]'s [held_weapon.name] go off during the struggle!"), SPAN_DANGER("You accidentally make [src]'s [held_weapon.name] go off during the struggle!"), null, 5)
var/list/turfs = list()
for(var/turf/T in view())
turfs += T
var/turf/target = pick(turfs)
count_niche_stat(STATISTICS_NICHE_DISCHARGE)

attack_log += "\[[time_stamp()]\] <b>[key_name(src)]</b> accidentally fired <b>[W.name]</b> in [get_area(src)] triggered by <b>[key_name(M)]</b>."
M.attack_log += "\[[time_stamp()]\] <b>[key_name(src)]</b> accidentally fired <b>[W.name]</b> in [get_area(src)] triggered by <b>[key_name(M)]</b>."
msg_admin_attack("[key_name(src)] accidentally fired <b>[W.name]</b> in [get_area(M)] ([M.loc.x],[M.loc.y],[M.loc.z]) triggered by <b>[key_name(M)]</b>.", M.loc.x, M.loc.y, M.loc.z)

return W.afterattack(target,src)
attack_log += "\[[time_stamp()]\] <b>[key_name(src)]</b> accidentally fired <b>[held_weapon.name]</b> in [get_area(src)] triggered by <b>[key_name(attacking_mob)]</b>."
attacking_mob.attack_log += "\[[time_stamp()]\] <b>[key_name(src)]</b> accidentally fired <b>[held_weapon.name]</b> in [get_area(src)] triggered by <b>[key_name(attacking_mob)]</b>."
msg_admin_attack("[key_name(src)] accidentally fired <b>[held_weapon.name]</b> in [get_area(attacking_mob)] ([attacking_mob.loc.x],[attacking_mob.loc.y],[attacking_mob.loc.z]) triggered by <b>[key_name(attacking_mob)]</b>.", attacking_mob.loc.x, attacking_mob.loc.y, attacking_mob.loc.z)

var/randn = rand(1, 100)
var/skill_level = M.skills.get_skill_level(SKILL_CQC)
if(M.skills)
randn -= 5 * skill_level //attacker's martial arts training
return held_weapon.afterattack(target,src)

if(skills)
randn += 5 * skill_level //defender's martial arts training
var/disarm_chance = rand(1, 100)
var/attacker_skill_level = attacking_mob.skills ? skills.get_skill_level(SKILL_CQC) : SKILL_CQC_MAX // No skills, so assume max
var/defender_skill_level = skills ? skills.get_skill_level(SKILL_CQC) : SKILL_CQC_MAX // No skills, so assume max
disarm_chance -= 5 * attacker_skill_level
disarm_chance += 5 * defender_skill_level

if (randn <= 25)
apply_effect(2 + skill_level, WEAKEN)
if(disarm_chance <= 25)
apply_effect(2 + max((attacker_skill_level - defender_skill_level), 0), WEAKEN)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 25, 1, 7)
var/shovetext = skill_level > 1 ? "tackled" : pick("pushed", "shoved")
visible_message(SPAN_DANGER("<B>[M] has [shovetext] [src]!</B>"), null, null, 5)
var/shove_text = attacker_skill_level > 1 ? "tackled" : pick("pushed", "shoved")
visible_message(SPAN_DANGER("<B>[attacking_mob] has [shove_text] [src]!</B>"), null, null, 5)
return

if(randn <= 60)
if(disarm_chance <= 60)
//BubbleWrap: Disarming breaks a pull
if(pulling)
visible_message(SPAN_DANGER("<b>[M] has broken [src]'s grip on [pulling]!</B>"), null, null, 5)
visible_message(SPAN_DANGER("<b>[attacking_mob] has broken [src]'s grip on [pulling]!</B>"), null, null, 5)
stop_pulling()
else
drop_held_item()
visible_message(SPAN_DANGER("<B>[M] has disarmed [src]!</B>"), null, null, 5)
visible_message(SPAN_DANGER("<B>[attacking_mob] has disarmed [src]!</B>"), null, null, 5)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 25, 1, 7)
return


playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, 7)
visible_message(SPAN_DANGER("<B>[M] attempted to disarm [src]!</B>"), null, null, 5)
return
visible_message(SPAN_DANGER("<B>[attacking_mob] attempted to disarm [src]!</B>"), null, null, 5)

/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params)
return
Expand Down

0 comments on commit 4a6938e

Please sign in to comment.