diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index b8030886c3d..29cee6aa74c 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -116,34 +116,124 @@
if(!attack.is_usable(M))
attack = M.species.secondary_unarmed
if(!attack.is_usable(M))
+ return 0 // COMMENT: This means that there's no way the secondary attack gets used, ever. Needs work ~Hubble
+
+ if(attack_move) return 0
+
+ var/damage = rand(1, 5)
+ var/block = 0
+ var/accurate = 0
+ var/target_zone = check_zone(M.zone_sel.selecting) // The zone that was targeted
+ var/hit_zone = target_zone // The zone that is actually hit
+ var/datum/organ/external/affecting = get_organ(hit_zone)
+
+ // Snowflakey magboot stomp
+ if(src.lying && M.canmove && !M.lying && M.shoes && istype(M.shoes, /obj/item/clothing/shoes/magboots))
+ var/obj/item/clothing/shoes/magboots/mboots = M.shoes
+ if(mboots.magpulse)
+ visible_message("\red [M] raises one of \his magboots over [src]'s [affecting.display_name]...")
+ attack_move = 1
+ spawn(20)
+ if(M.canmove && !M.lying && M.Adjacent(src) && src.lying)
+ visible_message("\red [M] stomps \his magboot down on [src]'s [affecting.display_name] with full force!")
+ apply_damage(rand(20,30), BRUTE, affecting, run_armor_check(affecting, "melee"))
+ playsound(loc, 'sound/weapons/genhit3.ogg', 25, 1, -1)
+ attack_move = 0
+
+ M.attack_log += text("\[[time_stamp()]\] Magboot-stomped [src.name] ([src.ckey])")
+ src.attack_log += text("\[[time_stamp()]\] Has been magboot-stomped by [M.name] ([M.ckey])")
+ msg_admin_attack("[key_name(M)] magboot-stomped [key_name(src)]")
+ return 0
+
+ switch(src.a_intent)
+ if("help")
+ // We didn't see this coming, so we get the full blow
+ damage = 5
+ accurate = 1
+ if("hurt", "grab")
+ // We're in a fighting stance, there's a chance we block
+ if(prob(20) && src.canmove && (!src==M))
+ block = 1
+
+ if (M.grabbed_by.len)
+ // Someone got a good grip on them, they won't be able to do much damage
+ damage = max(0, damage - 2)
+
+ if(src.grabbed_by.len || src.buckled || !src.canmove || src==M)
+ accurate = 1 // certain circumstances make it impossible for us to evade punches
+
+ // Process evasion and blocking
+ if(!accurate)
+ hit_zone = ran_zone(target_zone)
+ if(prob(15) && hit_zone != "chest") // Missed!
+ playsound(loc, attack.miss_sound, 25, 1, -1)
+ visible_message("\red [M] attempted to punch [src]!")
+ visible_message("\red [pick("The punch barely misses their [affecting.display_name]!", "[src] manages to dodge narrowly!")]")
+
+ M.attack_log += text("\[[time_stamp()]\] attempted to [pick(attack.attack_verb)] [src.name] ([src.ckey]) (dodged)")
+ src.attack_log += text("\[[time_stamp()]\] Dodged attack by [M.name] ([M.ckey])")
+ msg_admin_attack("[key_name(M)] attempted to [pick(attack.attack_verb)] [key_name(src)] (dodged)")
+ return 0
+ if(block)
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ visible_message("\red [M] went for [src]'s [affecting.display_name] but was blocked!")
+
+ M.attack_log += text("\[[time_stamp()]\] attempted to [pick(attack.attack_verb)] [src.name] ([src.ckey]) (blocked)")
+ src.attack_log += text("\[[time_stamp()]\] Blocked attack by [M.name] ([M.ckey])")
+ msg_admin_attack("[key_name(M)] attempted to [pick(attack.attack_verb)] [key_name(src)] (blocked)")
return 0
+ // Handle the attack logs
+ attack.combat_log(M, src, hit_zone, damage)
+
M.attack_log += text("\[[time_stamp()]\] [pick(attack.attack_verb)]ed [src.name] ([src.ckey])")
src.attack_log += text("\[[time_stamp()]\] Has been [pick(attack.attack_verb)]ed by [M.name] ([M.ckey])")
msg_admin_attack("[key_name(M)] [pick(attack.attack_verb)]ed [key_name(src)]")
- var/damage = rand(0, 5)//BS12 EDIT
- if(!damage)
- playsound(loc, attack.miss_sound, 25, 1, -1)
- visible_message("\red [M] tried to [pick(attack.attack_verb)] [src]!")
- return 0
+ // This here is where buffs go
+ if(M.mind && (M.mind.special_role == "Ninja" || M.mind.special_role == "Changeling"))
+ damage += 2 // We assume Ninjas and Changelings are slightly better in combat than the usual human
+ if(HULK in M.mutations)
+ damage *= 2 // Hulks do twice the damage
-
- var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting))
- var/armor_block = run_armor_check(affecting, "melee")
-
- if(HULK in M.mutations) damage += 5
-
-
- playsound(loc, attack.attack_sound, 25, 1, -1)
-
- visible_message("\red [M] [pick(attack.attack_verb)]ed [src]!")
- //Rearranged, so claws don't increase weaken chance.
- if(damage >= 5 && prob(50))
- visible_message("\red [M] has weakened [src]!")
+ var/armor_block = run_armor_check(affecting, "melee") // IMPORTANT: To run armor check after attack log as it produces a log itself
+ var/numb = rand(0, 100)
+ if(damage >= 5 && armor_block < 2 && !lying && numb <= damage*5)
+ switch(hit_zone) // strong punches can have effects depending on where they hit
+ if("head")
+ // Induce blurriness
+ visible_message("\red [src] stares blankly for a few moments.", "\red You see stars.")
+ apply_effect(damage*2, EYE_BLUR, armor_block)
+ if("l_arm", "l_hand")
+ if (l_hand)
+ // Disarm left hand
+ visible_message("\red [src] [pick("dropped", "let go off")] \the [l_hand][pick("", " with a scream")]!")
+ drop_l_hand()
+ if("r_arm", "r_hand")
+ if (r_hand)
+ // Disarm right hand
+ visible_message("\red [src] [pick("dropped", "let go off")] \the [r_hand][pick("", " with a scream")]!")
+ drop_r_hand()
+ if("chest")
+ visible_message("\red [pick("[src] was sent flying backward a few metres!", "[src] staggers back from the impact!")]")
+ step(src, get_dir(get_turf(M), get_turf(src)))
+ apply_effect(0.4*damage, WEAKEN, armor_block)
+ if("groin")
+ visible_message("\red [src] looks like \he is in pain!", (gender=="female")?"\red Oh god that hurt!":"\red Oh no, not your[pick("testicles", "crown jewels", "clockweights", "family jewels", "marbles", "bean bags", "teabags", "sweetmeats", "goolies")]!")
+ apply_effects(stutter=damage*2, agony=damage*3, blocked=armor_block)
+ if("l_leg", "l_foot", "r_leg", "r_foot")
+ visible_message("\red [src] gives way slightly.")
+ apply_effect(damage*3, AGONY, armor_block)
+ else if(damage >= 5 && numb >= damage*10) // Chance to get the usual throwdown as well
+ visible_message("\red [src] [pick("slumps", "falls", "drops")] down to the ground!")
apply_effect(3, WEAKEN, armor_block)
- damage += attack.damage
+ // Sum up species damage bonus at the very end so xenos don't get buffed stun chances
+ damage += attack.damage // 3 for human/skrell, 5 for tajaran/unathi
+
+ playsound(M.loc, attack.attack_sound, 25, 1, -1)
+
+ // Finally, apply damage to target
apply_damage(damage, BRUTE, affecting, armor_block, sharp=attack.sharp, edge=attack.edge)
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 6869d7efaff..80783cfee09 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -80,4 +80,6 @@
var/mob/remoteview_target = null
var/hand_blood_color
- var/list/flavor_texts = list()
\ No newline at end of file
+ var/list/flavor_texts = list()
+
+ var/attack_move = 0 //Used in combat to check if user is performing an attack over several ticks
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index a539f328207..b530a180998 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -491,6 +491,7 @@
//Species unarmed attacks
/datum/unarmed_attack
var/attack_verb = list("attack") // Empty hand hurt intent verb.
+ var/attack_noun = list("fist")
var/damage = 0 // Extra empty hand attack damage.
var/attack_sound = "punch"
var/miss_sound = 'sound/weapons/punchmiss.ogg'
@@ -513,6 +514,11 @@
return 0
+/datum/unarmed_attack/proc/combat_log(mob/living/carbon/human/M as mob, mob/living/carbon/human/T as mob, zone, damage)
+ var/datum/organ/external/affecting = T.get_organ(zone)
+ M.visible_message("[M] [pick(attack_verb)] [T] in the [affecting.display_name]!")
+ playsound(M.loc, attack_sound, 25, 1, -1)
+
/datum/unarmed_attack/bite
attack_verb = list("bite") // 'x has biteed y', needs work.
attack_sound = 'sound/weapons/bite.ogg'
@@ -528,20 +534,174 @@
/datum/unarmed_attack/punch
attack_verb = list("punch")
+ attack_noun = list("fist")
damage = 3
+/datum/unarmed_attack/punch/combat_log(mob/living/carbon/human/M as mob, mob/living/carbon/human/T as mob, zone, damage)
+ var/skill = M.skills["combat"]
+// if (M.mind && M.mind.special_role == "Ninja")
+// skill = 3
+ var/datum/organ/external/affecting = T.get_organ(zone)
+ var/organ = affecting.display_name
+
+ if(!skill) skill = 1
+ damage = Clamp(damage, 1, 5)
+
+ if(T == M)
+ M.visible_message("\red [M] [pick(attack_verb)]ed \himself in the [organ]!")
+ return 0
+ if(!M.lying)
+ switch(skill)
+ if(0)
+ switch(zone)
+ if("head", "chest", "l_arm", "r_arm", "l_hand", "r_hand")
+ M.visible_message("\red [M] [pick("flailed", "thrashed")] at [T]'s [organ]!")
+ if("groin", "l_leg", "r_leg", "l_foot", "r_foot")
+ M.visible_message("\red [M] [pick("kicked", "thrashed")] at [T]'s [organ]!")
+ if(1 to 2) // Amateur, Trained
+ switch(zone)
+ if("head")
+ // ----- HEAD ----- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] slapped [T] across \his cheek!")
+ if(3 to 4) M.visible_message("\red [M] struck [T] in the head[pick("", " with a closed fist")]!")
+ if(5) M.visible_message("\red [M] gave [T] a resounding slap to the face!")
+ if("chest", "l_arm", "r_arm", "l_hand", "r_hand")
+ // -- UPPER BODY -- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] slapped [T]'s [organ]!")
+ if(3 to 4) M.visible_message("\red [M] [findtext(zone, "hand")?"[pick(attack_verb)]ed":pick("[pick(attack_verb)]ed", "shoulders")] [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] rammed \his [pick(attack_noun)] into [T]'s [organ]!")
+ if("groin", "l_leg", "r_leg")
+ // -- LOWER BODY -- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] gave [T] a light kick to the [organ]!")
+ if(3 to 4) M.visible_message("\red [M] [pick("kicked", "kneed")] [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] landed a strong kick against [T]'s [organ]!")
+ if("l_foot", "r_foot")
+ // ----- FEET ----- //
+ switch(damage)
+ if(1 to 4) M.visible_message("\red [M] kicked [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] stomped down hard on [T]'s [organ]!")
+ if(3) // Professional
+ switch(zone)
+ if("head")
+ // ----- HEAD ----- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] threw a [pick("jab", "cross", "hook")] punch against [T]'s head!")
+ if(3 to 4) M.visible_message("\red [M] threw an uppercut on [T]!")
+ if(5 to 6) M.visible_message("\red [M] grabbed [T]'s head and gave \him a strong headbutt!")
+ if("chest", "l_arm", "r_arm", "l_hand", "r_hand")
+ // -- UPPER BODY -- //
+ switch(damage)
+ if(1 to 4) M.visible_message("\red [M] [findtext(zone, "hand")?"[pick(attack_verb)]ed":pick("[pick(attack_verb)]ed", "shoulders")] [T] in \his [organ]!")
+ if(5 to 6) M.visible_message("\red [M] rammed \his [pick(attack_noun)] into [T]'s [organ]!")
+ if("groin", "l_leg", "r_leg")
+ // -- LOWER BODY -- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] threw a light [pick("front", "side")] kick against [T]'s [organ]!")
+ if(3 to 4) M.visible_message("\red [M] gave [T] a [pick("knee strike", "kick")] in \his [organ]!")
+ if(5 to 6) M.visible_message("\red [M] threw a strong [pick("front", "side", "roundhouse")] kick against [T]'s [organ]!")
+ if("l_foot", "r_foot")
+ // ----- FEET ----- //
+ switch(damage)
+ if(1 to 4) M.visible_message("\red [M] kicked [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] stomped down hard on [T]'s [organ]!")
+ else if (M.loc != M.loc)
+ M.visible_message("\red [M] [pick("stomped down hard on", "kicked against", "gave a strong kick against", "rams their foot into")] [T]'s [organ]!")
+ else
+ M.visible_message("\red [M] [pick("punches", "throws a punch", "strikes", "slaps", "rams their [pick(attack_noun)] into")] [T]'s [organ]!")
+
+
/datum/unarmed_attack/diona
attack_verb = list("lash", "bludgeon")
+ attack_noun = list("tendril")
damage = 5
/datum/unarmed_attack/claws
- attack_verb = list("scratch", "claw")
+ attack_verb = list("scratch", "claw", "gouge", "tear", "rip")
+ attack_noun = list("claws")
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
damage = 5
sharp = 1
edge = 1
+/datum/unarmed_attack/claws/combat_log(mob/living/carbon/human/M as mob, mob/living/carbon/human/T as mob, zone, damage)
+ var/skill = M.skills["combat"]
+// if (M.mind && M.mind.special_role == "Ninja")
+// skill = 3
+ var/datum/organ/external/affecting = T.get_organ(zone)
+ var/organ = affecting.display_name
+
+ if(!skill) skill = 1
+ damage = Clamp(damage, 1, 5)
+
+ if(T == M)
+ M.visible_message("\red [M] [pick(attack_verb)]ed \himself in the [organ]!")
+ return 0
+ if(!M.lying)
+ switch(skill)
+ if(0)
+ switch(zone)
+ if("head", "chest", "l_arm", "r_arm", "l_hand", "r_hand")
+ M.visible_message("\red [M] [pick("flailed", "thrashed")] at [T]'s [organ]!")
+ if("groin", "l_leg", "r_leg", "l_foot", "r_foot")
+ M.visible_message("\red [M] [pick("kicked", "thrashed")] at [T]'s [organ]!")
+ if(1 to 2) // Amateur, Trained
+ switch(zone)
+ if("head")
+ // ----- HEAD ----- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] slapped [T] across \his cheek!")
+ if(3 to 4) M.visible_message("\red [M] struck [T] in the head[pick("", " with a closed fist")]!")
+ if(5) M.visible_message("\red [M] gave [T] a resounding slap to the face!")
+ if("chest", "l_arm", "r_arm", "l_hand", "r_hand")
+ // -- UPPER BODY -- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] slapped [T]'s [organ]!")
+ if(3 to 4) M.visible_message("\red [M] [findtext(zone, "hand")?"[pick(attack_verb)]ed":pick("[pick(attack_verb)]ed", "shoulders")] [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] rammed \his [pick(attack_noun)] into [T]'s [organ]!")
+ if("groin", "l_leg", "r_leg")
+ // -- LOWER BODY -- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] gave [T] a light kick to the [organ]!")
+ if(3 to 4) M.visible_message("\red [M] [pick("kicked", "kneed")] [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] landed a strong kick against [T]'s [organ]!")
+ if("l_foot", "r_foot")
+ // ----- FEET ----- //
+ switch(damage)
+ if(1 to 4) M.visible_message("\red [M] kicked [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] stomped down hard on [T]'s [organ]!")
+ if(3) // Professional
+ switch(zone)
+ if("head")
+ // ----- HEAD ----- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] threw a [pick("jab", "cross", "hook")] punch against [T]'s head!")
+ if(3 to 4) M.visible_message("\red [M] threw an uppercut on [T]!")
+ if(5 to 6) M.visible_message("\red [M] grabbed [T]'s head and gave \him a strong headbutt!")
+ if("chest", "l_arm", "r_arm", "l_hand", "r_hand")
+ // -- UPPER BODY -- //
+ switch(damage)
+ if(1 to 4) M.visible_message("\red [M] [findtext(zone, "hand")?"[pick(attack_verb)]ed":pick("[pick(attack_verb)]ed", "shoulders")] [T] in \his [organ]!")
+ if(5 to 6) M.visible_message("\red [M] rammed \his [pick(attack_noun)] into [T]'s [organ]!")
+ if("groin", "l_leg", "r_leg")
+ // -- LOWER BODY -- //
+ switch(damage)
+ if(1 to 2) M.visible_message("\red [M] threw a light [pick("front", "side")] kick against [T]'s [organ]!")
+ if(3 to 4) M.visible_message("\red [M] gave [T] a [pick("knee strike", "kick")] in \his [organ]!")
+ if(5 to 6) M.visible_message("\red [M] threw a strong [pick("front", "side", "roundhouse")] kick against [T]'s [organ]!")
+ if("l_foot", "r_foot")
+ // ----- FEET ----- //
+ switch(damage)
+ if(1 to 4) M.visible_message("\red [M] kicked [T] in \his [organ]!")
+ if(5) M.visible_message("\red [M] stomped down hard on [T]'s [organ]!")
+ else if (M.loc != M.loc)
+ M.visible_message("\red [M] [pick("stomped down hard on", "kicked against", "gave a strong kick against", "rams their foot into")] [T]'s [organ]!")
+ else
+ M.visible_message("\red [M] [pick("punches", "throws a punch", "strikes", "slaps", "rams their [pick(attack_noun)] into")] [T]'s [organ]!")
+
/datum/unarmed_attack/claws/strong
attack_verb = list("slash")
damage = 10