diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm
index 2a705f5ad14..4b6072a52ab 100644
--- a/code/modules/mob/living/carbon/human/unarmed_attack.dm
+++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm
@@ -106,7 +106,11 @@ var/global/list/sparring_attack_cache = list()
if(!affecting)
return
- user.visible_message("[user] [pick(attack_verb)] [target] in the [affecting.name]!")
+ user.visible_message(SPAN_WARNING("[user] [pick(attack_verb)] [target] in the [affecting.name]!"))
+ playsound(user.loc, attack_sound, 25, 1, -1)
+
+/datum/unarmed_attack/proc/show_attack_simple(var/mob/living/carbon/human/user, var/mob/living/target, var/zone)
+ user.visible_message(SPAN_WARNING("[user] [pick(attack_verb)] [target] in the [zone]!"))
playsound(user.loc, attack_sound, 25, 1, -1)
/datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
diff --git a/code/modules/mob/living/simple_animal/friendly/carp.dm b/code/modules/mob/living/simple_animal/friendly/carp.dm
index 9cd55e4b302..8979020bc5f 100644
--- a/code/modules/mob/living/simple_animal/friendly/carp.dm
+++ b/code/modules/mob/living/simple_animal/friendly/carp.dm
@@ -57,7 +57,7 @@
blood_overlay_icon = 'icons/mob/npc/blood_overlay.dmi'
else
blood_overlay_icon = initial(blood_overlay_icon)
- handle_blood_overlay(TRUE)
+ handle_blood(TRUE)
/mob/living/simple_animal/carp/fall_impact()
src.visible_message(SPAN_NOTICE("\The [src] gently floats to a stop."))
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index eae113d0fe7..77ff8dcf479 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -53,7 +53,7 @@
blood_overlay_icon = 'icons/mob/npc/blood_overlay.dmi'
else
blood_overlay_icon = initial(blood_overlay_icon)
- handle_blood_overlay(TRUE)
+ handle_blood(TRUE)
/mob/living/simple_animal/hostile/carp/Allow_Spacemove(var/check_drift = 0)
return 1 //No drifting in space for space carp! //original comments do not steal
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index c4b3898a51c..de775d3603f 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -26,6 +26,7 @@
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "pokes"
+ blood_amount = 150
stop_automated_movement_when_pulled = 0
maxHealth = 200
health = 200
@@ -54,6 +55,7 @@
icon_state = "greimorian_worker"
icon_living = "greimorian_worker"
icon_dead = "greimorian_worker_dead"
+ blood_amount = 50
maxHealth = 40
health = 40
melee_damage_lower = 5
@@ -70,6 +72,7 @@
icon_state = "greimorian_hunter"
icon_living = "greimorian_hunter"
icon_dead = "greimorian_hunter_dead"
+ blood_amount = 90
maxHealth = 120
health = 120
melee_damage_lower = 10
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index 07d7bf9faea..c04511025b0 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -56,7 +56,7 @@
blood_overlay_icon = 'icons/mob/npc/blood_overlay.dmi'
else
blood_overlay_icon = initial(blood_overlay_icon)
- handle_blood_overlay(TRUE)
+ handle_blood(TRUE)
/mob/living/simple_animal/hostile/hivebot/get_blood_overlay_name()
if(stance == HOSTILE_STANCE_IDLE)
@@ -726,7 +726,7 @@
blood_overlay_icon = 'icons/mob/npc/blood_overlay.dmi'
else
blood_overlay_icon = initial(blood_overlay_icon)
- handle_blood_overlay(TRUE)
+ handle_blood(TRUE)
/mob/living/simple_animal/hostile/retaliate/hivebotharvester/proc/prospect()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index d7fb916edf8..85e081e1a75 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -26,6 +26,11 @@
var/blood_state = BLOOD_NONE
var/image/blood_overlay
+ var/bleeding = FALSE
+ var/blood_amount = 50 // set a limit to the amount of blood it can bleed, otherwise it will keep bleeding forever and crunk the server
+ var/previous_bleed_timer = 0 // they only bleed for as many seconds as force damage was applied to them
+ var/blood_timer_mod = 1 // tweak to change the amount of seconds a mob will bleed
+
var/list/speak = list()
var/speak_chance = 0
var/list/emote_hear = list() //Hearable emotes
@@ -201,7 +206,7 @@
if(health > maxHealth)
health = maxHealth
- handle_blood_overlay()
+ handle_blood()
handle_stunned()
handle_weakened()
handle_paralysed()
@@ -329,10 +334,13 @@
if(purge)
purge -= 1
-/mob/living/simple_animal/proc/handle_blood_overlay(var/force_reset = FALSE)
+/mob/living/simple_animal/proc/handle_blood(var/force_reset = FALSE)
if(!blood_overlay_icon)
return
+ if(blood_amount <= 0 && stat != DEAD)
+ death()
+
var/current_blood_state = blood_state
var/blood_mod = health / maxHealth
if(blood_mod > 0.9)
@@ -344,6 +352,18 @@
else
blood_state = BLOOD_HEAVY
+ if(bleeding)
+ switch(blood_state)
+ if(BLOOD_LIGHT)
+ blood_splatter(src, null, FALSE, sourceless_color = blood_color)
+ blood_amount--
+ if(BLOOD_MEDIUM)
+ blood_splatter(src, null, TRUE, sourceless_color = blood_color)
+ blood_amount -= 2
+ if(BLOOD_HEAVY)
+ blood_splatter(src, null, TRUE, sourceless_color = blood_color)
+ blood_amount -= 3
+
if(force_reset || current_blood_state != blood_state)
if(blood_overlay)
cut_overlay(blood_overlay)
@@ -429,15 +449,6 @@
var/can_ghosts_hear = client ? GHOSTS_ALL_HEAR : ONLY_GHOSTS_IN_VIEW
custom_emote(AUDIBLE_MESSAGE, act_desc, can_ghosts_hear)
-/*
-mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
- if(!Proj || Proj.nodamage)
- return
-
- adjustBruteLoss(Proj.damage)
- return 0
-*/
-
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M as mob)
..()
switch(M.a_intent)
@@ -480,9 +491,21 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
return
/mob/living/simple_animal/proc/unarmed_harm_attack(var/mob/living/carbon/human/user)
+ if(istype(user))
+ var/datum/unarmed_attack/attack = user.get_unarmed_attack(src)
+ if(!attack)
+ simple_harm_attack(user)
+ return
+ attack.show_attack_simple(user, src, pick(organ_names))
+ apply_damage(attack.get_unarmed_damage(user), attack.damage_type)
+ user.do_attack_animation(src, FIST_ATTACK_ANIMATION)
+ return
+ simple_harm_attack(user)
+
+/mob/living/simple_animal/proc/simple_harm_attack(var/mob/living/user)
apply_damage(harm_intent_damage, BRUTE, used_weapon = "Attack by [user.name]")
user.visible_message(SPAN_WARNING("\The [user] [response_harm] \the [src]!"), SPAN_WARNING("You [response_harm] \the [src]!"))
- user.do_attack_animation(src)
+ user.do_attack_animation(src, FIST_ATTACK_ANIMATION)
poke(TRUE)
/mob/living/simple_animal/attackby(obj/item/O, mob/user)
@@ -546,16 +569,32 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
poke()
visible_message(SPAN_DANGER("\The [src] has been attacked with \the [O] by \the [user]."))
- user.do_attack_animation(src)
+ if(O.hitsound)
+ playsound(loc, O.hitsound, O.get_clamped_volume(), 1, -1)
+ user.do_attack_animation(src, O)
return TRUE
/mob/living/simple_animal/apply_damage(damage, damagetype, def_zone, blocked, used_weapon, damage_flags, armor_pen, silent = FALSE)
. = ..()
- handle_blood_overlay()
+ handle_bleeding_timer(damage)
+ handle_blood()
+
+/mob/living/simple_animal/proc/handle_bleeding_timer(var/damage_inflicted)
+ if(!blood_overlay_icon) // no blood, don't bother
+ return
+ if(damage_inflicted <= 0) // just to be safe
+ return
+ if(!bleeding || previous_bleed_timer <= damage_inflicted)
+ bleeding = TRUE
+ previous_bleed_timer = damage_inflicted
+ addtimer(CALLBACK(src, .proc/stop_bleeding), (damage_inflicted SECONDS) * blood_timer_mod, TIMER_UNIQUE | TIMER_OVERRIDE)
+
+/mob/living/simple_animal/proc/stop_bleeding()
+ bleeding = FALSE
/mob/living/simple_animal/heal_organ_damage(var/brute, var/burn)
. = ..()
- handle_blood_overlay()
+ handle_blood()
/mob/living/simple_animal/movement_delay()
var/tally = 0 //Incase I need to add stuff other than "speed" later
diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm
index 85ac869ff16..7f9811a3910 100644
--- a/code/modules/organs/blood.dm
+++ b/code/modules/organs/blood.dm
@@ -217,7 +217,7 @@ proc/blood_incompatible(donor,receiver,donor_species,receiver_species)
data["dose_chem"] = chem_doses.Copy()
return data
-proc/blood_splatter(var/target, var/source, var/large, var/spray_dir)
+proc/blood_splatter(var/target, var/source, var/large, var/spray_dir, var/sourceless_color)
var/obj/effect/decal/cleanable/blood/splatter
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
@@ -255,6 +255,11 @@ proc/blood_splatter(var/target, var/source, var/large, var/spray_dir)
else if(isatom(source))
var/atom/donor = source
blood_data = REAGENT_DATA(donor.reagents, /decl/reagent/blood)
+ else if(!source)
+ if(sourceless_color)
+ splatter.basecolor = sourceless_color
+ splatter.update_icon()
+ return splatter
if(!islist(blood_data))
return splatter
diff --git a/html/changelogs/geeves-satisfying_combat.yml b/html/changelogs/geeves-satisfying_combat.yml
new file mode 100644
index 00000000000..9709d78e0da
--- /dev/null
+++ b/html/changelogs/geeves-satisfying_combat.yml
@@ -0,0 +1,8 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - rscadd: "Simple mobs now bleed. They also bleed out and die."
+ - rscadd: "Attacking a simple mob while unarmed will now use your default attack with a hitsound."
+ - rscadd: "Attacking a simple mob with an item will now properly show the attack animation and hitsound."