mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
[MIRROR] Moree unarmed fixes (#10234)
Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
812150cd72
commit
debcb137ea
@@ -174,8 +174,6 @@
|
|||||||
///from base of atom/attack_hand(): (mob/user)
|
///from base of atom/attack_hand(): (mob/user)
|
||||||
#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand"
|
#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand"
|
||||||
///from base of atom/attack_paw(): (mob/user)
|
///from base of atom/attack_paw(): (mob/user)
|
||||||
#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw"
|
|
||||||
#define COMPONENT_NO_ATTACK_HAND (1<<0) //works on all 3.
|
|
||||||
//This signal return value bitflags can be found in __DEFINES/misc.dm
|
//This signal return value bitflags can be found in __DEFINES/misc.dm
|
||||||
|
|
||||||
///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
|
///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ var/const/tk_maxrange = 15
|
|||||||
*/
|
*/
|
||||||
/atom/proc/attack_tk(mob/user)
|
/atom/proc/attack_tk(mob/user)
|
||||||
if(user.stat) return
|
if(user.stat) return
|
||||||
user.UnarmedAttack(src,0) // attack_hand, attack_paw, etc
|
user.UnarmedAttack(src,0)
|
||||||
return
|
return
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ THAT STUPID GAME KIT
|
|||||||
src.board_stat = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
|
src.board_stat = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
|
||||||
src.selected = "CR"
|
src.selected = "CR"
|
||||||
|
|
||||||
/obj/item/game_kit/attack_paw(mob/user as mob)
|
|
||||||
return src.attack_hand(user)
|
|
||||||
|
|
||||||
/obj/item/game_kit/MouseDrop(mob/user as mob)
|
/obj/item/game_kit/MouseDrop(mob/user as mob)
|
||||||
if (user == usr && !user.restrained() && !user.stat && (user.contents.Find(src) || in_range(src, user)))
|
if (user == usr && !user.restrained() && !user.stat && (user.contents.Find(src) || in_range(src, user)))
|
||||||
if (user.hand)
|
if (user.hand)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
var/datum/unarmed_attack/default_attack
|
var/datum/unarmed_attack/default_attack
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone)
|
/mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone)
|
||||||
// VOREStation Edit - Begin
|
|
||||||
if(nif && nif.flag_check(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT)){return unarmed_hardclaws}
|
if(nif && nif.flag_check(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT)){return unarmed_hardclaws}
|
||||||
if(src.default_attack && src.default_attack.is_usable(src, target, hit_zone))
|
if(src.default_attack && src.default_attack.is_usable(src, target, hit_zone))
|
||||||
if(pulling_punches)
|
if(pulling_punches)
|
||||||
@@ -10,7 +9,6 @@
|
|||||||
if(soft_type)
|
if(soft_type)
|
||||||
return soft_type
|
return soft_type
|
||||||
return src.default_attack
|
return src.default_attack
|
||||||
// VOREStation Edit - End
|
|
||||||
if(src.gloves)
|
if(src.gloves)
|
||||||
var/obj/item/clothing/gloves/G = src.gloves
|
var/obj/item/clothing/gloves/G = src.gloves
|
||||||
if(istype(G) && G.special_attack && G.special_attack.is_usable(src, target, hit_zone))
|
if(istype(G) && G.special_attack && G.special_attack.is_usable(src, target, hit_zone))
|
||||||
@@ -37,15 +35,15 @@
|
|||||||
/mob/living/carbon/human/attack_hand(mob/living/M as mob)
|
/mob/living/carbon/human/attack_hand(mob/living/M as mob)
|
||||||
var/datum/gender/TT = gender_datums[M.get_visible_gender()]
|
var/datum/gender/TT = gender_datums[M.get_visible_gender()]
|
||||||
var/mob/living/carbon/human/H = M
|
var/mob/living/carbon/human/H = M
|
||||||
|
var/has_hands = TRUE
|
||||||
if(istype(H))
|
if(istype(H))
|
||||||
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
|
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
|
||||||
if(H.hand)
|
if(H.hand)
|
||||||
temp = H.organs_by_name["l_hand"]
|
temp = H.organs_by_name["l_hand"]
|
||||||
if(!temp || !temp.is_usable())
|
if(!temp || !temp.is_usable())
|
||||||
to_chat(H, span_warning("You can't use your hand."))
|
//to_chat(H, span_warning("You can't use your hand."))
|
||||||
return
|
has_hands = FALSE
|
||||||
|
for(var/thing in GetViruses()) //This is intentionally not having a has_hands check. If you are clicking on someone next to them, you're close enough to sneeze/cough on them!
|
||||||
for(var/thing in GetViruses())
|
|
||||||
var/datum/disease/D = thing
|
var/datum/disease/D = thing
|
||||||
if(D.IsSpreadByTouch())
|
if(D.IsSpreadByTouch())
|
||||||
H.ContractDisease(D)
|
H.ContractDisease(D)
|
||||||
@@ -62,7 +60,7 @@
|
|||||||
..()
|
..()
|
||||||
|
|
||||||
// Should this all be in Touch()?
|
// Should this all be in Touch()?
|
||||||
if(istype(H))
|
if(istype(H) && has_hands)
|
||||||
if(H.get_accuracy_penalty() && H != src) //Should only trigger if they're not aiming well
|
if(H.get_accuracy_penalty() && H != src) //Should only trigger if they're not aiming well
|
||||||
var/hit_zone = get_zone_with_miss_chance(H.zone_sel.selecting, src, H.get_accuracy_penalty())
|
var/hit_zone = get_zone_with_miss_chance(H.zone_sel.selecting, src, H.get_accuracy_penalty())
|
||||||
if(!hit_zone)
|
if(!hit_zone)
|
||||||
@@ -75,284 +73,314 @@
|
|||||||
H.do_attack_animation(src)
|
H.do_attack_animation(src)
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
if(istype(M,/mob/living/carbon))
|
if(istype(M,/mob/living/carbon) && has_hands)
|
||||||
for(var/datum/disease/D in M.GetViruses())
|
for(var/datum/disease/D in M.GetViruses())
|
||||||
if(D.spread_flags & CONTACT_HANDS)
|
if(D.spread_flags & CONTACT_HANDS)
|
||||||
ContractDisease(D)
|
ContractDisease(D)
|
||||||
|
|
||||||
switch(M.a_intent)
|
switch(M.a_intent) //VARS: H = The one doing the attack. || M = The mob we are targeting || TT = gender of what we are targeting.
|
||||||
if(I_HELP)
|
if(I_HELP)
|
||||||
|
attack_hand_help_intent(H, M, TT, has_hands)
|
||||||
// VOREStation Edit - Begin
|
|
||||||
if (istype(H) && attempt_to_scoop(H))
|
|
||||||
return 0;
|
|
||||||
// VOREStation Edit - End
|
|
||||||
if(istype(H) && health < CONFIG_GET(number/health_threshold_crit))
|
|
||||||
if(!H.check_has_mouth())
|
|
||||||
to_chat(H, span_danger("You don't have a mouth, you cannot perform CPR!"))
|
|
||||||
return
|
|
||||||
if(!check_has_mouth())
|
|
||||||
to_chat(H, span_danger("They don't have a mouth, you cannot perform CPR!"))
|
|
||||||
return
|
|
||||||
if((H.head && (H.head.body_parts_covered & FACE)) || (H.wear_mask && (H.wear_mask.body_parts_covered & FACE)))
|
|
||||||
to_chat(H, span_notice("Remove your mask!"))
|
|
||||||
return 0
|
|
||||||
if((head && (head.body_parts_covered & FACE)) || (wear_mask && (wear_mask.body_parts_covered & FACE)))
|
|
||||||
to_chat(H, span_notice("Remove [src]'s mask!"))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if (!cpr_time)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
cpr_time = 0
|
|
||||||
spawn(30)
|
|
||||||
cpr_time = 1
|
|
||||||
|
|
||||||
H.visible_message(span_danger("\The [H] is trying to perform CPR on \the [src]!"))
|
|
||||||
|
|
||||||
if(!do_after(H, 30))
|
|
||||||
return
|
|
||||||
|
|
||||||
H.visible_message(span_danger("\The [H] performs CPR on \the [src]!"))
|
|
||||||
to_chat(H, span_warning("Repeat at least every 7 seconds."))
|
|
||||||
|
|
||||||
if(istype(H) && health > CONFIG_GET(number/health_threshold_dead))
|
|
||||||
adjustOxyLoss(-(min(getOxyLoss(), 5)))
|
|
||||||
updatehealth()
|
|
||||||
to_chat(src, span_notice("You feel a breath of fresh air enter your lungs. It feels good."))
|
|
||||||
|
|
||||||
else if(!(M == src && apply_pressure(M, M.zone_sel.selecting)))
|
|
||||||
help_shake_act(M)
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
if(I_GRAB)
|
if(I_GRAB)
|
||||||
if(M == src || anchored)
|
attack_hand_grab_intent(H, M, TT, has_hands)
|
||||||
return 0
|
|
||||||
for(var/obj/item/grab/G in src.grabbed_by)
|
|
||||||
if(G.assailant == M)
|
|
||||||
to_chat(M, span_notice("You already grabbed [src]."))
|
|
||||||
return
|
|
||||||
if(w_uniform)
|
|
||||||
w_uniform.add_fingerprint(M)
|
|
||||||
|
|
||||||
var/obj/item/grab/G = new /obj/item/grab(M, src)
|
|
||||||
if(buckled)
|
|
||||||
to_chat(M, span_notice("You cannot grab [src], [TT.he] is buckled in!"))
|
|
||||||
return
|
|
||||||
if(!G) //the grab will delete itself in New if affecting is anchored
|
|
||||||
return
|
|
||||||
M.put_in_active_hand(G)
|
|
||||||
G.synch()
|
|
||||||
LAssailant = M
|
|
||||||
|
|
||||||
H.do_attack_animation(src)
|
|
||||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
|
||||||
//VORESTATION EDIT
|
|
||||||
visible_message(span_warning("[M] has grabbed [src] [(M.zone_sel.selecting == BP_L_HAND || M.zone_sel.selecting == BP_R_HAND)? "by [(gender==FEMALE)? "her" : ((gender==MALE)? "his": "their")] hands": "passively"]!"))
|
|
||||||
//VORESTATION END END
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
if(I_HURT)
|
if(I_HURT)
|
||||||
|
attack_hand_harm_intent(H, M, TT, has_hands)
|
||||||
if(M.zone_sel.selecting == "mouth" && wear_mask && istype(wear_mask, /obj/item/grenade))
|
|
||||||
var/obj/item/grenade/G = wear_mask
|
|
||||||
if(!G.active)
|
|
||||||
visible_message(span_danger("\The [M] pulls the pin from \the [src]'s [G.name]!"))
|
|
||||||
G.activate(M)
|
|
||||||
update_inv_wear_mask()
|
|
||||||
else
|
|
||||||
to_chat(M, span_warning("\The [G] is already primed! Run!"))
|
|
||||||
return
|
|
||||||
|
|
||||||
if(!istype(H))
|
|
||||||
attack_generic(H,rand(1,3),"punched")
|
|
||||||
return
|
|
||||||
|
|
||||||
var/rand_damage = rand(1, 5)
|
|
||||||
var/block = 0
|
|
||||||
var/accurate = 0
|
|
||||||
var/hit_zone = H.zone_sel.selecting
|
|
||||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
|
||||||
|
|
||||||
if(!affecting || affecting.is_stump())
|
|
||||||
to_chat(M, span_danger("They are missing that limb!"))
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
switch(src.a_intent)
|
|
||||||
if(I_HELP)
|
|
||||||
// We didn't see this coming, so we get the full blow
|
|
||||||
rand_damage = 5
|
|
||||||
accurate = 1
|
|
||||||
if(I_HURT, I_GRAB)
|
|
||||||
// We're in a fighting stance, there's a chance we block
|
|
||||||
if(src.canmove && src!=H && prob(20))
|
|
||||||
block = 1
|
|
||||||
|
|
||||||
if (M.grabbed_by.len)
|
|
||||||
// Someone got a good grip on them, they won't be able to do much damage
|
|
||||||
rand_damage = max(1, rand_damage - 2)
|
|
||||||
|
|
||||||
if(src.grabbed_by.len || src.buckled || !src.canmove || src==H)
|
|
||||||
accurate = 1 // certain circumstances make it impossible for us to evade punches
|
|
||||||
rand_damage = 5
|
|
||||||
|
|
||||||
// Process evasion and blocking
|
|
||||||
var/miss_type = 0
|
|
||||||
var/attack_message
|
|
||||||
if(!accurate)
|
|
||||||
/* ~Hubblenaut
|
|
||||||
This place is kind of convoluted and will need some explaining.
|
|
||||||
ran_zone() will pick out of 11 zones, thus the chance for hitting
|
|
||||||
our target where we want to hit them is circa 9.1%.
|
|
||||||
|
|
||||||
Now since we want to statistically hit our target organ a bit more
|
|
||||||
often than other organs, we add a base chance of 20% for hitting it.
|
|
||||||
|
|
||||||
This leaves us with the following chances:
|
|
||||||
|
|
||||||
If aiming for chest:
|
|
||||||
27.3% chance you hit your target organ
|
|
||||||
70.5% chance you hit a random other organ
|
|
||||||
2.2% chance you miss
|
|
||||||
|
|
||||||
If aiming for something else:
|
|
||||||
23.2% chance you hit your target organ
|
|
||||||
56.8% chance you hit a random other organ
|
|
||||||
15.0% chance you miss
|
|
||||||
|
|
||||||
Note: We don't use get_zone_with_miss_chance() here since the chances
|
|
||||||
were made for projectiles.
|
|
||||||
TODO: proc for melee combat miss chances depending on organ?
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!hit_zone)
|
|
||||||
attack_message = "[H] attempted to strike [src], but missed!"
|
|
||||||
miss_type = 1
|
|
||||||
|
|
||||||
if(prob(80))
|
|
||||||
hit_zone = ran_zone(hit_zone, 70) //70% chance to hit what you're aiming at seems fair?
|
|
||||||
if(prob(15) && hit_zone != BP_TORSO) // Missed!
|
|
||||||
if(!src.lying)
|
|
||||||
attack_message = "[H] attempted to strike [src], but missed!"
|
|
||||||
else
|
|
||||||
attack_message = "[H] attempted to strike [src], but [TT.he] rolled out of the way!"
|
|
||||||
src.set_dir(pick(cardinal))
|
|
||||||
miss_type = 1
|
|
||||||
|
|
||||||
if(!miss_type && block)
|
|
||||||
attack_message = "[H] went for [src]'s [affecting.name] but was blocked!"
|
|
||||||
miss_type = 2
|
|
||||||
|
|
||||||
// See what attack they use
|
|
||||||
var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, hit_zone)
|
|
||||||
if(!attack)
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
if(attack.unarmed_override(H, src, hit_zone))
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
H.do_attack_animation(src)
|
|
||||||
if(!attack_message)
|
|
||||||
attack.show_attack(H, src, hit_zone, rand_damage)
|
|
||||||
else
|
|
||||||
H.visible_message(span_danger("[attack_message]"))
|
|
||||||
|
|
||||||
playsound(src, ((miss_type) ? (miss_type == 1 ? attack.miss_sound : 'sound/weapons/thudswoosh.ogg') : attack.attack_sound), 25, 1, -1)
|
|
||||||
|
|
||||||
add_attack_logs(H,src,"Melee attacked with fists (miss/block)")
|
|
||||||
|
|
||||||
if(miss_type)
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
var/real_damage = rand_damage
|
|
||||||
var/hit_dam_type = attack.damage_type
|
|
||||||
real_damage += attack.get_unarmed_damage(H)
|
|
||||||
if(H.gloves && attack.is_punch)
|
|
||||||
if(istype(H.gloves, /obj/item/clothing/gloves))
|
|
||||||
var/obj/item/clothing/gloves/G = H.gloves
|
|
||||||
real_damage += G.punch_force
|
|
||||||
hit_dam_type = G.punch_damtype
|
|
||||||
else if(istype(H.gloves, /obj/item/clothing/accessory))
|
|
||||||
var/obj/item/clothing/accessory/G = H.gloves
|
|
||||||
real_damage += G.punch_force
|
|
||||||
hit_dam_type = G.punch_damtype
|
|
||||||
if(H.pulling_punches && !attack.sharp && !attack.edge) //SO IT IS DECREED: PULLING PUNCHES WILL PREVENT THE ACTUAL DAMAGE FROM RINGS AND KNUCKLES, BUT NOT THE ADDED PAIN, BUT YOU CAN'T "PULL" A KNIFE
|
|
||||||
hit_dam_type = HALLOSS
|
|
||||||
real_damage *= damage_multiplier
|
|
||||||
rand_damage *= damage_multiplier
|
|
||||||
if(HULK in H.mutations)
|
|
||||||
real_damage *= 2 // Hulks do twice the damage
|
|
||||||
rand_damage *= 2
|
|
||||||
real_damage = max(1, real_damage)
|
|
||||||
|
|
||||||
var/armour = run_armor_check(hit_zone, "melee")
|
|
||||||
var/soaked = get_armor_soak(hit_zone, "melee")
|
|
||||||
// Apply additional unarmed effects.
|
|
||||||
attack.apply_effects(H, src, armour, rand_damage, hit_zone)
|
|
||||||
|
|
||||||
// Finally, apply damage to target
|
|
||||||
apply_damage(real_damage, hit_dam_type, hit_zone, armour, soaked, sharp=attack.sharp, edge=attack.edge)
|
|
||||||
|
|
||||||
if(I_DISARM)
|
if(I_DISARM)
|
||||||
add_attack_logs(H,src,"Disarmed")
|
attack_hand_disarm_intent(H, M, TT, has_hands)
|
||||||
|
|
||||||
M.do_attack_animation(src)
|
|
||||||
|
|
||||||
if(w_uniform)
|
|
||||||
w_uniform.add_fingerprint(M)
|
|
||||||
var/obj/item/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting))
|
|
||||||
|
|
||||||
var/list/holding = list(get_active_hand() = 40, get_inactive_hand = 20)
|
|
||||||
|
|
||||||
//See if they have any guns that might go off
|
|
||||||
for(var/obj/item/gun/W in holding)
|
|
||||||
if(W && prob(holding[W]))
|
|
||||||
var/list/turfs = list()
|
|
||||||
for(var/turf/T in view())
|
|
||||||
turfs += T
|
|
||||||
if(turfs.len)
|
|
||||||
var/turf/target = pick(turfs)
|
|
||||||
visible_message(span_danger("[src]'s [W] goes off during the struggle!"))
|
|
||||||
return W.afterattack(target,src)
|
|
||||||
|
|
||||||
if(last_push_time + 30 > world.time)
|
|
||||||
visible_message(span_warning("[M] has weakly pushed [src]!"))
|
|
||||||
return
|
|
||||||
|
|
||||||
var/randn = rand(1, 100)
|
|
||||||
last_push_time = world.time
|
|
||||||
// We ARE wearing shoes OR
|
|
||||||
// We as a species CAN be slipped when barefoot
|
|
||||||
// And also 1 in 4 because rngesus
|
|
||||||
if((shoes || !(species.flags & NO_SLIP)) && randn <= 25)
|
|
||||||
var/armor_check = run_armor_check(affecting, "melee")
|
|
||||||
apply_effect(3, WEAKEN, armor_check)
|
|
||||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
|
||||||
if(armor_check < 60)
|
|
||||||
drop_both_hands() // CHOMPEdit - We've been pushed! Drop our stuff as well
|
|
||||||
visible_message(span_danger("[M] has pushed [src]!"))
|
|
||||||
else
|
|
||||||
visible_message(span_warning("[M] attempted to push [src]!"))
|
|
||||||
return
|
|
||||||
|
|
||||||
if(randn <= 60)
|
|
||||||
//See about breaking grips or pulls
|
|
||||||
if(break_all_grabs(M))
|
|
||||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
|
||||||
return
|
|
||||||
|
|
||||||
//Actually disarm them
|
|
||||||
for(var/obj/item/I in holding)
|
|
||||||
if(I)
|
|
||||||
drop_from_inventory(I)
|
|
||||||
visible_message(span_danger("[M] has disarmed [src]!"))
|
|
||||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
|
||||||
return
|
|
||||||
|
|
||||||
playsound(src, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
|
||||||
visible_message(span_filter_combat("[span_red(span_bold("[M] attempted to disarm [src]!"))]"))
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
/// THE VARIOUS INTENTS.
|
||||||
|
/// Theses used to be included in the above proc into a MEGA PROC that was over 300 lines long.
|
||||||
|
/// This condenses them and makes it less of a cluster.
|
||||||
|
|
||||||
|
///Help Intent
|
||||||
|
/mob/living/carbon/human/proc/attack_hand_help_intent(var/mob/living/carbon/human/H, var/mob/living/M as mob, var/datum/gender/TT, var/has_hands)
|
||||||
|
PRIVATE_PROC(TRUE)
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
if(!has_hands) //This is here so if you WANT to do special code for 'if we don't have hands, do stuff' it can be done here!
|
||||||
|
return FALSE
|
||||||
|
if (istype(H) && attempt_to_scoop(H))
|
||||||
|
return FALSE;
|
||||||
|
if(istype(H) && health < CONFIG_GET(number/health_threshold_crit))
|
||||||
|
if(!H.check_has_mouth())
|
||||||
|
to_chat(H, span_danger("You don't have a mouth, you cannot perform CPR!"))
|
||||||
|
return FALSE
|
||||||
|
if(!check_has_mouth())
|
||||||
|
to_chat(H, span_danger("They don't have a mouth, you cannot perform CPR!"))
|
||||||
|
return FALSE
|
||||||
|
if((H.head && (H.head.body_parts_covered & FACE)) || (H.wear_mask && (H.wear_mask.body_parts_covered & FACE)))
|
||||||
|
to_chat(H, span_notice("Remove your mask!"))
|
||||||
|
return FALSE
|
||||||
|
if((head && (head.body_parts_covered & FACE)) || (wear_mask && (wear_mask.body_parts_covered & FACE)))
|
||||||
|
to_chat(H, span_notice("Remove [src]'s mask!"))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if (!cpr_time)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
cpr_time = 0
|
||||||
|
addtimer(VARSET_CALLBACK(src, cpr_time , 1), 3 SECONDS, TIMER_DELETE_ME)
|
||||||
|
|
||||||
|
H.visible_message(span_danger("\The [H] is trying to perform CPR on \the [src]!"))
|
||||||
|
|
||||||
|
if(!do_after(H, 30))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
H.visible_message(span_danger("\The [H] performs CPR on \the [src]!"))
|
||||||
|
to_chat(H, span_warning("Repeat at least every 7 seconds."))
|
||||||
|
|
||||||
|
if(istype(H) && health > CONFIG_GET(number/health_threshold_dead))
|
||||||
|
adjustOxyLoss(-(min(getOxyLoss(), 5)))
|
||||||
|
updatehealth()
|
||||||
|
to_chat(src, span_notice("You feel a breath of fresh air enter your lungs. It feels good."))
|
||||||
|
|
||||||
|
else if(!(M == src && apply_pressure(M, M.zone_sel.selecting)))
|
||||||
|
help_shake_act(M)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
//Disarm Intent
|
||||||
|
/mob/living/carbon/human/proc/attack_hand_disarm_intent(var/mob/living/carbon/human/H, var/mob/living/M as mob, var/datum/gender/TT, var/has_hands)
|
||||||
|
PRIVATE_PROC(TRUE)
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
if(!has_hands) //This is here so if you WANT to do special code for 'if we don't have hands, do stuff' it can be done here!
|
||||||
|
return
|
||||||
|
|
||||||
|
add_attack_logs(H,src,"Disarmed")
|
||||||
|
|
||||||
|
M.do_attack_animation(src)
|
||||||
|
|
||||||
|
if(w_uniform)
|
||||||
|
w_uniform.add_fingerprint(M)
|
||||||
|
var/obj/item/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting))
|
||||||
|
|
||||||
|
var/list/holding = list(get_active_hand() = 40, get_inactive_hand = 20)
|
||||||
|
|
||||||
|
//See if they have any guns that might go off
|
||||||
|
for(var/obj/item/gun/W in holding)
|
||||||
|
if(W && prob(holding[W]))
|
||||||
|
var/list/turfs = list()
|
||||||
|
for(var/turf/T in view())
|
||||||
|
turfs += T
|
||||||
|
if(turfs.len)
|
||||||
|
var/turf/target = pick(turfs)
|
||||||
|
visible_message(span_danger("[src]'s [W] goes off during the struggle!"))
|
||||||
|
return W.afterattack(target,src)
|
||||||
|
|
||||||
|
if(last_push_time + 30 > world.time)
|
||||||
|
visible_message(span_warning("[M] has weakly pushed [src]!"))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/randn = rand(1, 100)
|
||||||
|
last_push_time = world.time
|
||||||
|
// We ARE wearing shoes OR
|
||||||
|
// We as a species CAN be slipped when barefoot
|
||||||
|
// And also 1 in 4 because rngesus
|
||||||
|
if((shoes || !(species.flags & NO_SLIP)) && randn <= 25)
|
||||||
|
var/armor_check = run_armor_check(affecting, "melee")
|
||||||
|
apply_effect(3, WEAKEN, armor_check)
|
||||||
|
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||||
|
if(armor_check < 60)
|
||||||
|
drop_both_hands() // CHOMPEdit - We've been pushed! Drop our stuff as well
|
||||||
|
visible_message(span_danger("[M] has pushed [src]!"))
|
||||||
|
else
|
||||||
|
visible_message(span_warning("[M] attempted to push [src]!"))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(randn <= 60)
|
||||||
|
//See about breaking grips or pulls
|
||||||
|
if(break_all_grabs(M))
|
||||||
|
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||||
|
return
|
||||||
|
|
||||||
|
//Actually disarm them
|
||||||
|
for(var/obj/item/I in holding)
|
||||||
|
if(I)
|
||||||
|
drop_from_inventory(I)
|
||||||
|
visible_message(span_danger("[M] has disarmed [src]!"))
|
||||||
|
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||||
|
return
|
||||||
|
|
||||||
|
playsound(src, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||||
|
visible_message(span_filter_combat("[span_red(span_bold("[M] attempted to disarm [src]!"))]"))
|
||||||
|
//Grab Intent
|
||||||
|
/mob/living/carbon/human/proc/attack_hand_grab_intent(var/mob/living/carbon/human/H, var/mob/living/M as mob, var/datum/gender/TT, var/has_hands)
|
||||||
|
PRIVATE_PROC(TRUE)
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
if(!has_hands) //This is here so if you WANT to do special code for 'if we don't have hands, do stuff' it can be done here!
|
||||||
|
return FALSE
|
||||||
|
if(M == src || anchored)
|
||||||
|
return FALSE
|
||||||
|
for(var/obj/item/grab/G in src.grabbed_by)
|
||||||
|
if(G.assailant == M)
|
||||||
|
to_chat(M, span_notice("You already grabbed [src]."))
|
||||||
|
return
|
||||||
|
if(w_uniform)
|
||||||
|
w_uniform.add_fingerprint(M)
|
||||||
|
|
||||||
|
if(buckled)
|
||||||
|
to_chat(M, span_notice("You cannot grab [src], [TT.he] is buckled in!"))
|
||||||
|
return
|
||||||
|
var/obj/item/grab/G = new /obj/item/grab(M, src) //If this is put before the buckled check, the user will be perma-slowed due to a grab existing in nullspace.
|
||||||
|
if(!G) //the grab will delete itself in New if affecting is anchored
|
||||||
|
return
|
||||||
|
M.put_in_active_hand(G)
|
||||||
|
G.synch()
|
||||||
|
LAssailant = M
|
||||||
|
|
||||||
|
H.do_attack_animation(src)
|
||||||
|
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||||
|
visible_message(span_warning("[M] has grabbed [src] [(M.zone_sel.selecting == BP_L_HAND || M.zone_sel.selecting == BP_R_HAND)? "by [(gender==FEMALE)? "her" : ((gender==MALE)? "his": "their")] hands": "passively"]!"))
|
||||||
|
//Harm Intent
|
||||||
|
/mob/living/carbon/human/proc/attack_hand_harm_intent(var/mob/living/carbon/human/H, var/mob/living/M as mob, var/datum/gender/TT, var/has_hands)
|
||||||
|
PRIVATE_PROC(TRUE)
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
//As a note: This intentionally doesn't immediately return if has_hands is false. This is because you can attack with kicks/bites!
|
||||||
|
if(has_hands && M.zone_sel.selecting == "mouth" && wear_mask && istype(wear_mask, /obj/item/grenade))
|
||||||
|
var/obj/item/grenade/G = wear_mask
|
||||||
|
if(!G.active)
|
||||||
|
visible_message(span_danger("\The [M] pulls the pin from \the [src]'s [G.name]!"))
|
||||||
|
G.activate(M)
|
||||||
|
update_inv_wear_mask()
|
||||||
|
else
|
||||||
|
to_chat(M, span_warning("\The [G] is already primed! Run!"))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(has_hands && !istype(H))
|
||||||
|
attack_generic(H,rand(1,3),"punched")
|
||||||
|
return
|
||||||
|
|
||||||
|
var/rand_damage = rand(1, 5)
|
||||||
|
var/block = 0
|
||||||
|
var/accurate = 0
|
||||||
|
var/hit_zone = H.zone_sel.selecting
|
||||||
|
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||||
|
|
||||||
|
if(!affecting || affecting.is_stump())
|
||||||
|
to_chat(M, span_danger("They are missing that limb!"))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
switch(a_intent)
|
||||||
|
if(I_HELP)
|
||||||
|
// We didn't see this coming, so we get the full blow
|
||||||
|
rand_damage = 5
|
||||||
|
accurate = 1
|
||||||
|
if(I_HURT, I_GRAB)
|
||||||
|
// We're in a fighting stance, there's a chance we block
|
||||||
|
if(canmove && src!=H && prob(20))
|
||||||
|
block = 1
|
||||||
|
|
||||||
|
if (M.grabbed_by.len)
|
||||||
|
// Someone got a good grip on them, they won't be able to do much damage
|
||||||
|
rand_damage = max(1, rand_damage - 2)
|
||||||
|
|
||||||
|
if(src.grabbed_by.len || src.buckled || !src.canmove || src==H)
|
||||||
|
accurate = 1 // certain circumstances make it impossible for us to evade punches
|
||||||
|
rand_damage = 5
|
||||||
|
|
||||||
|
// Process evasion and blocking
|
||||||
|
var/miss_type = 0
|
||||||
|
var/attack_message
|
||||||
|
if(!accurate)
|
||||||
|
/* ~Hubblenaut
|
||||||
|
This place is kind of convoluted and will need some explaining.
|
||||||
|
ran_zone() will pick out of 11 zones, thus the chance for hitting
|
||||||
|
our target where we want to hit them is circa 9.1%.
|
||||||
|
|
||||||
|
Now since we want to statistically hit our target organ a bit more
|
||||||
|
often than other organs, we add a base chance of 20% for hitting it.
|
||||||
|
|
||||||
|
This leaves us with the following chances:
|
||||||
|
|
||||||
|
If aiming for chest:
|
||||||
|
27.3% chance you hit your target organ
|
||||||
|
70.5% chance you hit a random other organ
|
||||||
|
2.2% chance you miss
|
||||||
|
|
||||||
|
If aiming for something else:
|
||||||
|
23.2% chance you hit your target organ
|
||||||
|
56.8% chance you hit a random other organ
|
||||||
|
15.0% chance you miss
|
||||||
|
|
||||||
|
Note: We don't use get_zone_with_miss_chance() here since the chances
|
||||||
|
were made for projectiles.
|
||||||
|
TODO: proc for melee combat miss chances depending on organ?
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!hit_zone)
|
||||||
|
attack_message = "[H] attempted to strike [src], but missed!"
|
||||||
|
miss_type = 1
|
||||||
|
|
||||||
|
if(prob(80))
|
||||||
|
hit_zone = ran_zone(hit_zone, 70) //70% chance to hit what you're aiming at seems fair?
|
||||||
|
if(prob(15) && hit_zone != BP_TORSO) // Missed!
|
||||||
|
if(!src.lying)
|
||||||
|
attack_message = "[H] attempted to strike [src], but missed!"
|
||||||
|
else
|
||||||
|
attack_message = "[H] attempted to strike [src], but [TT.he] rolled out of the way!"
|
||||||
|
src.set_dir(pick(cardinal))
|
||||||
|
miss_type = 1
|
||||||
|
|
||||||
|
if(!miss_type && block)
|
||||||
|
attack_message = "[H] went for [src]'s [affecting.name] but was blocked!"
|
||||||
|
miss_type = 2
|
||||||
|
|
||||||
|
// See what attack they use
|
||||||
|
var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, hit_zone)
|
||||||
|
if(!attack)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(attack.unarmed_override(H, src, hit_zone))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
H.do_attack_animation(src)
|
||||||
|
if(!attack_message)
|
||||||
|
attack.show_attack(H, src, hit_zone, rand_damage)
|
||||||
|
else
|
||||||
|
H.visible_message(span_danger("[attack_message]"))
|
||||||
|
|
||||||
|
playsound(src, ((miss_type) ? (miss_type == 1 ? attack.miss_sound : 'sound/weapons/thudswoosh.ogg') : attack.attack_sound), 25, 1, -1)
|
||||||
|
|
||||||
|
add_attack_logs(H,src,"Melee attacked with fists (miss/block)")
|
||||||
|
|
||||||
|
if(miss_type)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
var/real_damage = rand_damage
|
||||||
|
var/hit_dam_type = attack.damage_type
|
||||||
|
real_damage += attack.get_unarmed_damage(H)
|
||||||
|
if(H.gloves && attack.is_punch)
|
||||||
|
if(istype(H.gloves, /obj/item/clothing/gloves))
|
||||||
|
var/obj/item/clothing/gloves/G = H.gloves
|
||||||
|
real_damage += G.punch_force
|
||||||
|
hit_dam_type = G.punch_damtype
|
||||||
|
else if(istype(H.gloves, /obj/item/clothing/accessory))
|
||||||
|
var/obj/item/clothing/accessory/G = H.gloves
|
||||||
|
real_damage += G.punch_force
|
||||||
|
hit_dam_type = G.punch_damtype
|
||||||
|
if(H.pulling_punches && !attack.sharp && !attack.edge) //SO IT IS DECREED: PULLING PUNCHES WILL PREVENT THE ACTUAL DAMAGE FROM RINGS AND KNUCKLES, BUT NOT THE ADDED PAIN, BUT YOU CAN'T "PULL" A KNIFE
|
||||||
|
hit_dam_type = HALLOSS
|
||||||
|
real_damage *= damage_multiplier
|
||||||
|
rand_damage *= damage_multiplier
|
||||||
|
if(HULK in H.mutations)
|
||||||
|
real_damage *= 2 // Hulks do twice the damage
|
||||||
|
rand_damage *= 2
|
||||||
|
real_damage = max(1, real_damage)
|
||||||
|
|
||||||
|
var/armour = run_armor_check(hit_zone, "melee")
|
||||||
|
var/soaked = get_armor_soak(hit_zone, "melee")
|
||||||
|
// Apply additional unarmed effects.
|
||||||
|
attack.apply_effects(H, src, armour, rand_damage, hit_zone)
|
||||||
|
|
||||||
|
// Finally, apply damage to target
|
||||||
|
apply_damage(real_damage, hit_dam_type, hit_zone, armour, soaked, sharp=attack.sharp, edge=attack.edge)
|
||||||
|
|
||||||
|
/// INTENTS END
|
||||||
|
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params)
|
/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
//Moving around with fractured ribs won't do you any good
|
//Moving around with fractured ribs won't do you any good
|
||||||
if (prob(10) && !stat && can_feel_pain() && chem_effects[CE_PAINKILLER] < 50 && E.is_broken() && E.internal_organs.len)
|
if (prob(10) && !stat && can_feel_pain() && chem_effects[CE_PAINKILLER] < 50 && E.is_broken() && E.internal_organs.len)
|
||||||
custom_pain("Pain jolts through your broken [E.encased ? E.encased : E.name], staggering you!", 50)
|
custom_pain("Pain jolts through your broken [E.encased ? E.encased : E.name], staggering you!", 50)
|
||||||
emote("pain")
|
emote("scream")
|
||||||
drop_item(loc)
|
drop_item(loc)
|
||||||
Stun(2)
|
Stun(2)
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,6 @@
|
|||||||
/obj/machinery/computer/am_engine/attack_ai(var/mob/user as mob)
|
/obj/machinery/computer/am_engine/attack_ai(var/mob/user as mob)
|
||||||
return src.attack_hand(user)
|
return src.attack_hand(user)
|
||||||
|
|
||||||
/obj/machinery/computer/am_engine/attack_paw(var/mob/user as mob)
|
|
||||||
return src.attack_hand(user)
|
|
||||||
|
|
||||||
/obj/machinery/computer/am_engine/attack_hand(var/mob/user as mob)
|
/obj/machinery/computer/am_engine/attack_hand(var/mob/user as mob)
|
||||||
if(..())
|
if(..())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -104,9 +104,6 @@
|
|||||||
attack_ai(mob/user as mob)
|
attack_ai(mob/user as mob)
|
||||||
interact(user)
|
interact(user)
|
||||||
|
|
||||||
attack_paw(mob/user as mob)
|
|
||||||
interact(user)
|
|
||||||
|
|
||||||
proc
|
proc
|
||||||
interact(mob/user)
|
interact(mob/user)
|
||||||
if (get_dist(src, user) > 1 )
|
if (get_dist(src, user) > 1 )
|
||||||
|
|||||||
Reference in New Issue
Block a user