diff --git a/beestation.dme b/beestation.dme
index fef444dac67fa..2b1dc71f5d9c9 100644
--- a/beestation.dme
+++ b/beestation.dme
@@ -389,7 +389,6 @@
#include "code\_onclick\hud\alien_larva.dm"
#include "code\_onclick\hud\blob_overmind.dm"
#include "code\_onclick\hud\blobbernauthud.dm"
-#include "code\_onclick\hud\constructs.dm"
#include "code\_onclick\hud\credits.dm"
#include "code\_onclick\hud\drones.dm"
#include "code\_onclick\hud\fullscreen.dm"
@@ -398,7 +397,7 @@
#include "code\_onclick\hud\holoparasite.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
-#include "code\_onclick\hud\lavaland_elite.dm"
+#include "code\_onclick\hud\living.dm"
#include "code\_onclick\hud\map_popups.dm"
#include "code\_onclick\hud\minebot.dm"
#include "code\_onclick\hud\monkey.dm"
@@ -412,7 +411,6 @@
#include "code\_onclick\hud\revenanthud.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
-#include "code\_onclick\hud\slime.dm"
#include "code\_onclick\hud\swarmer.dm"
#include "code\_onclick\hud\rendering\plane_master.dm"
#include "code\_onclick\hud\rendering\plane_master_controller.dm"
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 44f9bfb1e656f..520f5eb5df0f3 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -295,6 +295,15 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define NICE_SHOT_RICOCHET_BONUS 10 //if the shooter has the NICE_SHOT trait and they fire a ricocheting projectile, add this to the ricochet chance and auto aim angle
+/// Martial arts attack requested but is not available, allow a check for a regular attack.
+#define MARTIAL_ATTACK_INVALID -1
+
+/// Martial arts attack happened but failed, do not allow a check for a regular attack.
+#define MARTIAL_ATTACK_FAIL FALSE
+
+/// Martial arts attack happened and succeeded, do not allow a check for a regular attack.
+#define MARTIAL_ATTACK_SUCCESS TRUE
+
// Flags for energy shields
/// Energy shields will block projectiles
#define ENERGY_SHIELD_BLOCK_PROJECTILES (1 << 0)
diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index 813fedfa18630..05781a250ae1c 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -44,6 +44,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_HUSK "husk"
#define TRAIT_BADDNA "baddna"
#define TRAIT_CLUMSY "clumsy"
+//means that you can't use weapons with normal trigger guards.
+#define TRAIT_CHUNKYFINGERS "chunkyfingers"
#define TRAIT_DUMB "dumb"
#define TRAIT_DISCOORDINATED "discoordinated" //sets IsAdvancedToolUser to FALSE on humans and monkies
#define TRAIT_PACIFISM "pacifism"
@@ -68,6 +70,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_RESISTCOLD "resist_cold"
#define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure"
#define TRAIT_RESISTLOWPRESSURE "resist_low_pressure"
+#define TRAIT_BOMBIMMUNE "bomb_immunity"
#define TRAIT_RADIMMUNE "rad_immunity"
#define TRAIT_NORADDAMAGE "no_rad_damage"
#define TRAIT_VIRUSIMMUNE "virus_immunity"
@@ -172,6 +175,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_NO_BLOOD "no_blood" // Bleeding heals itself and bleeding is impossible
#define TRAIT_NO_BLEEDING "no_bleed" // The user can acquire the bleeding status effect, but will no lose blood
#define TRAIT_BLOOD_COOLANT "blood_coolant" // Replaces blood with coolant, meaning we overheat instead of losing air
+#define TRAIT_MARTIAL_ARTS_IMMUNE "martial_arts_immune" // nobody can use martial arts on this mob
// You can stare into the abyss, but it does not stare back.
// You're immune to the hallucination effect of the supermatter, either
diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm
index 9cd1e59e7144d..2564ac55af483 100644
--- a/code/__DEFINES/traits/sources.dm
+++ b/code/__DEFINES/traits/sources.dm
@@ -85,6 +85,7 @@
#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
#define HIVEMIND_TRAIT "hivemind-trait"
#define VR_ZONE_TRAIT "vr_zone_trait"
+#define SLEEPING_CARP_TRAIT "sleeping_carp"
#define GLUED_ITEM_TRAIT "glued-item"
#define LEGION_CORE_TRAIT "legion_core_trait"
#define MIRROR_TRAIT "mirror_trait"
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index d75e959633899..45e1334d4b09b 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -48,6 +48,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD,
"TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE,
"TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE,
+ "TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE,
"TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE,
"TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE,
"TRAIT_PIERCEIMMUNE" = TRAIT_PIERCEIMMUNE,
@@ -184,7 +185,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_IGNORING_GRAVITY" = TRAIT_IGNORING_GRAVITY,
"TRAIT_FORCED_GRAVITY" = TRAIT_FORCED_GRAVITY,
"TRAIT_MOVE_UPSIDE_DOWN" = TRAIT_MOVE_UPSIDE_DOWN,
- "TRAIT_NEGATES_GRAVITY" = TRAIT_NEGATES_GRAVITY
+ "TRAIT_NEGATES_GRAVITY" = TRAIT_NEGATES_GRAVITY,
+ "TRAIT_MARTIAL_ARTS_IMMUNE" = TRAIT_MARTIAL_ARTS_IMMUNE,
+ "TRAIT_CHUNKYFINGERS" = TRAIT_CHUNKYFINGERS,
),
/obj/item/integrated_circuit = list(
"TRAIT_COMPONENT_MMI" = TRAIT_COMPONENT_MMI,
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 027d1f498fc82..7ebe16a641a05 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -337,15 +337,34 @@
if(istype(ML))
ML.pulled(src)
+/mob/living/CtrlClick(mob/user)
+ if(!isliving(user) || !Adjacent(user) || user.incapacitated())
+ return ..()
+
+ if(world.time < user.next_move)
+ return FALSE
+
+ var/mob/living/user_living = user
+ if(user_living.apply_martial_art(src, null) == MARTIAL_ATTACK_SUCCESS)
+ user_living.changeNext_move(CLICK_CD_MELEE)
+ return TRUE
+
+ return ..()
+
/mob/living/carbon/human/CtrlClick(mob/user)
- if(ishuman(user) && Adjacent(user) && !user.incapacitated())
- if(world.time < user.next_move)
- return FALSE
- var/mob/living/carbon/human/H = user
- H.dna.species.grab(H, src, H.mind.martial_art)
- H.changeNext_move(CLICK_CD_MELEE)
- else
- ..()
+
+ if(!ishuman(user) ||!Adjacent(user) || user.incapacitated())
+ return ..()
+
+ if(world.time < user.next_move)
+ return FALSE
+
+ var/mob/living/carbon/human/human_user = user
+ if(human_user.dna.species.grab(human_user, src, human_user.mind.martial_art))
+ human_user.changeNext_move(CLICK_CD_MELEE)
+ return TRUE
+
+ return ..()
/mob/proc/CtrlMiddleClickOn(atom/A)
// specifically made for admin feature.
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index d2f077fc6aa6d..a08c17b36cb17 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -17,21 +17,6 @@
Therefore, the top right corner (except during admin shenanigans) is at "17,15"
*/
-//Lower left, persistent menu
-#define ui_inventory "WEST:6,SOUTH:5"
-
-//Middle left indicators
-#define ui_lingchemdisplay "WEST,CENTER-1:15"
-#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
-
-#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
-
-//Lower center, persistent menu
-#define ui_sstore1 "CENTER-5:10,SOUTH:5"
-#define ui_id "CENTER-4:12,SOUTH:5"
-#define ui_belt "CENTER-3:14,SOUTH:5"
-#define ui_back "CENTER-2:14,SOUTH:5"
-
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
var/x_off = -(!(i % 2))
var/y_off = round((i-1) / 2)
@@ -46,8 +31,22 @@
var/y_off = round((M.held_items.len-1) / 2)
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
+//Lower left, persistent menu
+#define ui_inventory "WEST:6,SOUTH:5"
+
+//Middle left indicators
+#define ui_lingchemdisplay "WEST,CENTER-1:15"
+#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
+#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
+
+//Lower center, persistent menu
+#define ui_sstore1 "CENTER-5:10,SOUTH:5"
+#define ui_id "CENTER-4:12,SOUTH:5"
+#define ui_belt "CENTER-3:14,SOUTH:5"
+#define ui_back "CENTER-2:14,SOUTH:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
+#define ui_combo "CENTER+4:24,SOUTH+1:7" //combo meter for martial arts
#define ui_borg_lamp "CENTER-3:16, SOUTH:5" //borgs
#define ui_borg_tablet "CENTER-4:16, SOUTH:5" //borgs
@@ -61,6 +60,10 @@
#define ui_borg_crew_manifest "CENTER+5:21,SOUTH:5" //borgs
#define ui_borg_language_menu "CENTER+4:21,SOUTH+1:5" //borgs
+//Generic living
+#define ui_living_pull "EAST-1:28,CENTER-3:15"
+#define ui_living_healthdoll "EAST-1:28,CENTER-1:15"
+
#define ui_monkey_body "CENTER-6:12,SOUTH:5" //monkey
#define ui_monkey_head "CENTER-5:14,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-4:15,SOUTH:5" //monkey
@@ -117,12 +120,9 @@
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
#define ui_alien_queen_finder "EAST,CENTER-3:15"
-//constructs
+//Constructs
#define ui_construct_pull "EAST,CENTER-2:15"
-#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
-
-//slimes
-#define ui_slime_health "EAST,CENTER:15" //same as borgs, constructs and humans
+#define ui_construct_health "EAST,CENTER:15"
// AI
diff --git a/code/_onclick/hud/constructs.dm b/code/_onclick/hud/constructs.dm
deleted file mode 100644
index bee898ea489c8..0000000000000
--- a/code/_onclick/hud/constructs.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-/datum/hud/constructs
- ui_style = 'icons/hud/screen_construct.dmi'
-
-/datum/hud/constructs/New(mob/owner)
- ..()
- pull_icon = new /atom/movable/screen/pull()
- pull_icon.icon = ui_style
- pull_icon.update_icon()
- pull_icon.screen_loc = ui_construct_pull
- pull_icon.hud = src
- static_inventory += pull_icon
-
- healths = new /atom/movable/screen/healths/construct()
- healths.hud = src
- infodisplay += healths
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 6d94886e3f886..e817dfd21e940 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
var/atom/movable/screen/alien_plasma_display
var/atom/movable/screen/alien_queen_finder
- var/atom/movable/screen/devil/soul_counter/devilsouldisplay
+ var/atom/movable/screen/combo/combo_display
var/atom/movable/screen/action_intent
var/atom/movable/screen/zone_select
@@ -117,11 +117,11 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
stamina = null
healthdoll = null
lingchemdisplay = null
- devilsouldisplay = null
lingstingdisplay = null
blobpwrdisplay = null
alien_plasma_display = null
alien_queen_finder = null
+ combo_display = null
QDEL_LIST_ASSOC_VAL(plane_masters)
QDEL_LIST_ASSOC_VAL(plane_master_controllers)
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 3a4c8dfda6cb5..13ea00ba8cc29 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -336,16 +336,15 @@
lingstingdisplay.hud = src
infodisplay += lingstingdisplay
- devilsouldisplay = new /atom/movable/screen/devil/soul_counter
- devilsouldisplay.hud = src
- infodisplay += devilsouldisplay
-
zone_select = new /atom/movable/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon()
zone_select.hud = src
static_inventory += zone_select
+ combo_display = new /atom/movable/screen/combo()
+ infodisplay += combo_display
+
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
diff --git a/code/_onclick/hud/lavaland_elite.dm b/code/_onclick/hud/lavaland_elite.dm
deleted file mode 100644
index 526e48ba87ba0..0000000000000
--- a/code/_onclick/hud/lavaland_elite.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/datum/hud/lavaland_elite
- ui_style = 'icons/hud/screen_slime.dmi'
-
-/datum/hud/lavaland_elite/New(mob/living/simple_animal/hostile/asteroid/elite)
- ..()
- healths = new /atom/movable/screen/healths/lavaland_elite()
- infodisplay += healths
diff --git a/code/_onclick/hud/living.dm b/code/_onclick/hud/living.dm
new file mode 100644
index 0000000000000..366079f233d10
--- /dev/null
+++ b/code/_onclick/hud/living.dm
@@ -0,0 +1,20 @@
+/datum/hud/living
+ ui_style = 'icons/hud/screen_gen.dmi'
+
+/datum/hud/living/New(mob/living/owner)
+ ..()
+
+ pull_icon = new /atom/movable/screen/pull()
+ pull_icon.icon = ui_style
+ pull_icon.update_appearance()
+ pull_icon.screen_loc = ui_living_pull
+ pull_icon.hud = src
+ static_inventory += pull_icon
+
+ combo_display = new /atom/movable/screen/combo()
+ infodisplay += combo_display
+
+ //mob health doll! assumes whatever sprite the mob is
+ healthdoll = new /atom/movable/screen/healthdoll/living()
+ healthdoll.hud = src
+ infodisplay += healthdoll
diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm
index 542b496d3459a..f44dd3c5ddf4e 100644
--- a/code/_onclick/hud/monkey.dm
+++ b/code/_onclick/hud/monkey.dm
@@ -124,6 +124,9 @@
zone_select.hud = src
static_inventory += zone_select
+ combo_display = new /atom/movable/screen/combo()
+ infodisplay += combo_display
+
mymob.client.screen = list()
using = new /atom/movable/screen/resist()
diff --git a/code/_onclick/hud/revenanthud.dm b/code/_onclick/hud/revenanthud.dm
index 708b1d49154d7..0e7b795965539 100644
--- a/code/_onclick/hud/revenanthud.dm
+++ b/code/_onclick/hud/revenanthud.dm
@@ -1,7 +1,16 @@
+/datum/hud/revenant
+ ui_style = 'icons/hud/screen_gen.dmi'
/datum/hud/revenant/New(mob/owner)
..()
+ pull_icon = new /atom/movable/screen/pull()
+ pull_icon.icon = ui_style
+ pull_icon.update_icon()
+ pull_icon.screen_loc = ui_living_pull
+ pull_icon.hud = src
+ static_inventory += pull_icon
+
healths = new /atom/movable/screen/healths/revenant()
healths.hud = src
infodisplay += healths
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index effec7721c770..29bc98cf12070 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -566,7 +566,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/atom/movable/screen/storage)
/atom/movable/screen/healths/minebot
icon = 'icons/hud/screen_cyborg.dmi'
- screen_loc = ui_health
+ screen_loc = ui_borg_health
/atom/movable/screen/healths/blob
name = "blob health"
@@ -581,8 +581,8 @@ CREATION_TEST_IGNORE_SUBTYPES(/atom/movable/screen/storage)
/atom/movable/screen/healths/blob/naut/core
name = "overmind health"
- screen_loc = ui_health
icon_state = "corehealth"
+ screen_loc = ui_health
/atom/movable/screen/healths/clock
icon = 'icons/hud/actions/action_generic.dmi'
@@ -599,25 +599,6 @@ CREATION_TEST_IGNORE_SUBTYPES(/atom/movable/screen/storage)
name = "essence"
icon = 'icons/hud/actions/action_generic.dmi'
icon_state = "bg_revenant"
- screen_loc = ui_health
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/atom/movable/screen/healths/construct
- icon = 'icons/hud/screen_construct.dmi'
- icon_state = "artificer_health0"
- screen_loc = ui_construct_health
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/atom/movable/screen/healths/slime
- icon = 'icons/hud/screen_slime.dmi'
- icon_state = "slime_health0"
- screen_loc = ui_slime_health
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/atom/movable/screen/healths/lavaland_elite
- icon = 'icons/hud/screen_elite.dmi'
- icon_state = "elite_health0"
- screen_loc = ui_health
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/atom/movable/screen/healthdoll
@@ -629,6 +610,11 @@ CREATION_TEST_IGNORE_SUBTYPES(/atom/movable/screen/storage)
var/mob/living/carbon/C = usr
C.check_self_for_injuries()
+/atom/movable/screen/healthdoll/living
+ icon_state = "fullhealth0"
+ screen_loc = ui_living_healthdoll
+ var/filtered = FALSE //so we don't repeatedly create the mask of the mob every update
+
/atom/movable/screen/mood
name = "mood"
icon_state = "mood5"
@@ -701,6 +687,37 @@ CREATION_TEST_IGNORE_SUBTYPES(/atom/movable/screen/component_button)
if(parent)
parent.component_click(src, params)
+/atom/movable/screen/combo
+ icon_state = ""
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ screen_loc = ui_combo
+ plane = ABOVE_HUD_PLANE
+ var/timerid
+
+/atom/movable/screen/combo/proc/clear_streak()
+ animate(src, alpha = 0, 2 SECONDS, SINE_EASING)
+ timerid = addtimer(CALLBACK(src, PROC_REF(reset_icons)), 2 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
+
+/atom/movable/screen/combo/proc/reset_icons()
+ cut_overlays()
+ icon_state = ""
+
+/atom/movable/screen/combo/update_icon_state(streak = "", time = 2 SECONDS)
+ reset_icons()
+ if(timerid)
+ deltimer(timerid)
+ alpha = 255
+ if(!streak)
+ return ..()
+ timerid = addtimer(CALLBACK(src, PROC_REF(clear_streak)), time, TIMER_UNIQUE | TIMER_STOPPABLE)
+ icon_state = "combo"
+ for (var/i = 1; i <= length(streak); ++i)
+ var/intent_text = copytext(streak, i, i + 1)
+ var/image/intent_icon = image(icon,src,"combo_[intent_text]")
+ intent_icon.pixel_x = 16 * (i - 1) - 8 * length(streak)
+ add_overlay(intent_icon)
+ return ..()
+
/atom/movable/screen/stamina
name = "stamina"
icon_state = "stamina0"
diff --git a/code/_onclick/hud/slime.dm b/code/_onclick/hud/slime.dm
deleted file mode 100644
index 35845b64a24ec..0000000000000
--- a/code/_onclick/hud/slime.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-/datum/hud/slime
- ui_style = 'icons/hud/screen_slime.dmi'
-
-/datum/hud/slime/New(mob/living/simple_animal/slime/owner)
- ..()
- healths = new /atom/movable/screen/healths/slime()
- healths.hud = src
- infodisplay += healths
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 2aff31691887e..4aea3d0590d89 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -111,7 +111,7 @@
if(item_flags & NOBLUDGEON)
nonharmfulhit = TRUE
- if(force && HAS_TRAIT(user, TRAIT_PACIFISM) && !nonharmfulhit)
+ if(damtype != STAMINA && force && HAS_TRAIT(user, TRAIT_PACIFISM) && !nonharmfulhit)
to_chat(user, span_warning("You don't want to harm other living beings!"))
nonharmfulhit = TRUE
diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm
index cf6db650d0d00..9038bd1e875c0 100644
--- a/code/datums/cinematic.dm
+++ b/code/datums/cinematic.dm
@@ -72,7 +72,7 @@
ooc_toggled = TRUE
toggle_ooc(FALSE)
- //Place /obj/screen/cinematic into everyone's screens, prevent them from moving
+ //Place /atom/movable/cinematic into everyone's screens, prevent them from moving
for(var/MM in watchers)
var/mob/M = MM
show_to(M, M.client)
diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm
index fd989179d9d9a..1c0ef2688ea09 100644
--- a/code/datums/martial/_martial.dm
+++ b/code/datums/martial/_martial.dm
@@ -5,114 +5,93 @@
var/max_streak_length = 6
var/current_target
var/datum/martial_art/base // The permanent style. This will be null unless the martial art is temporary
- var/deflection_chance = 0 //Chance to deflect projectiles
- var/reroute_deflection = FALSE //Delete the bullet, or actually deflect it in some direction?
var/block_chance = 0 //Chance to block melee attacks using items while on throw mode.
- var/restraining = 0 //used in cqc's disarm_act to check if the disarmed is being restrained and so whether they should be put in a chokehold or not
var/help_verb
- var/no_guns = FALSE
var/allow_temp_override = TRUE //if this martial art can be overridden by temporary martial arts
var/smashes_tables = FALSE //If the martial art smashes tables when performing table slams and head smashes
+ var/datum/weakref/holder //owner of the martial art
+ var/display_combos = FALSE //shows combo meter if true
+ var/combo_timer = 6 SECONDS // period of time after which the combo streak is reset.
+ var/timerid
+ /// If set to true this style allows you to punch people despite being a pacifist (for instance Boxing, which does no damage)
+ var/pacifist_style = FALSE
-/datum/martial_art/proc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
- return 0
+/datum/martial_art/proc/help_act(mob/living/A, mob/living/D)
+ return MARTIAL_ATTACK_INVALID
-/datum/martial_art/proc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
- return 0
+/datum/martial_art/proc/disarm_act(mob/living/A, mob/living/D)
+ return MARTIAL_ATTACK_INVALID
-/datum/martial_art/proc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
- return 0
+/datum/martial_art/proc/harm_act(mob/living/A, mob/living/D)
+ return MARTIAL_ATTACK_INVALID
-/datum/martial_art/proc/can_use(mob/living/carbon/human/H)
+/datum/martial_art/proc/grab_act(mob/living/A, mob/living/D)
+ return MARTIAL_ATTACK_INVALID
+
+/datum/martial_art/proc/can_use(mob/living/L)
return TRUE
-/datum/martial_art/proc/add_to_streak(element,mob/living/carbon/human/D)
+/datum/martial_art/proc/add_to_streak(element, mob/living/D)
if(D != current_target)
- current_target = D
- streak = ""
- restraining = 0
+ reset_streak(D)
streak = streak+element
if(length(streak) > max_streak_length)
streak = copytext(streak, 1 + length(streak[1]))
- return
-
-/datum/martial_art/proc/basic_hit(mob/living/carbon/human/A,mob/living/carbon/human/D)
-
- var/damage = A.dna.species.punchdamage
-
- var/atk_verb = A.dna.species.attack_verb
- if(D.body_position == LYING_DOWN)
- atk_verb = "kick"
-
- switch(atk_verb)
- if("kick")
- A.do_attack_animation(D, ATTACK_EFFECT_KICK)
- if("slash")
- A.do_attack_animation(D, ATTACK_EFFECT_CLAW)
- if("smash")
- A.do_attack_animation(D, ATTACK_EFFECT_SMASH)
- else
- A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
-
- if(!damage)
- playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
- D.visible_message(span_warning("[A]'s [atk_verb] misses [D]!"), \
- span_danger("You avoid [A]'s [atk_verb]!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, A)
- to_chat(A, span_warning("Your [atk_verb] misses [D]!"))
- log_combat(A, D, "attempted to [atk_verb]", important = FALSE)
- return 0
-
- var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D)))
- var/armor_block = D.run_armor_check(affecting, MELEE)
-
- playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
- D.visible_message(span_danger("[A] [atk_verb]ed [D]!"), \
- span_userdanger("You're [atk_verb]ed by [A]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, A)
- to_chat(A, span_danger("You [atk_verb]ed [D]!"))
-
- D.apply_damage(damage, A.dna.species.attack_type, affecting, armor_block)
-
- log_combat(A, D, "punched", name)
-
- if(D.body_position == LYING_DOWN)
- D.force_say(A)
- return 1
-
-/datum/martial_art/proc/teach(mob/living/carbon/human/H,make_temporary=0)
- if(!istype(H) || !H.mind)
+ if (display_combos)
+ var/mob/living/holder_living = holder.resolve()
+ timerid = addtimer(CALLBACK(src, PROC_REF(reset_streak), null, FALSE), combo_timer, TIMER_UNIQUE | TIMER_STOPPABLE)
+ holder_living?.hud_used?.combo_display.update_icon_state(streak, combo_timer - 2 SECONDS)
+
+/datum/martial_art/proc/reset_streak(mob/living/new_target, update_icon = TRUE)
+ if(timerid)
+ deltimer(timerid)
+ current_target = new_target
+ streak = ""
+ if(update_icon)
+ var/mob/living/holder_living = holder?.resolve()
+ holder_living?.hud_used?.combo_display.update_icon_state(streak)
+
+/datum/martial_art/proc/teach(mob/living/holder_living, make_temporary=FALSE)
+ if(!istype(holder_living) || !holder_living.mind)
return FALSE
- if(H.mind.martial_art)
+ if(holder_living.mind.martial_art)
if(make_temporary)
- if(!H.mind.martial_art.allow_temp_override)
+ if(!holder_living.mind.martial_art.allow_temp_override)
return FALSE
- store(H.mind.martial_art,H)
+ store(holder_living.mind.martial_art, holder_living)
else
- H.mind.martial_art.on_remove(H)
+ holder_living.mind.martial_art.on_remove(holder_living)
else if(make_temporary)
- base = H.mind.default_martial_art
+ base = holder_living.mind.default_martial_art
if(help_verb)
- H.add_verb(help_verb)
- H.mind.martial_art = src
+ holder_living.add_verb(help_verb)
+ holder_living.mind.martial_art = src
+ holder = WEAKREF(holder_living)
return TRUE
-/datum/martial_art/proc/store(datum/martial_art/M,mob/living/carbon/human/H)
- M.on_remove(H)
- if(M.base) //Checks if M is temporary, if so it will not be stored.
- base = M.base
- else //Otherwise, M is stored.
- base = M
+/datum/martial_art/proc/store(datum/martial_art/old, mob/living/holder_living)
+ old.on_remove(holder_living)
+ if (old.base) //Checks if old is temporary, if so it will not be stored.
+ base = old.base
+ else //Otherwise, old is stored.
+ base = old
-/datum/martial_art/proc/remove(mob/living/carbon/human/H)
- if(!istype(H) || !H.mind || H.mind.martial_art != src)
+/datum/martial_art/proc/remove(mob/living/holder_living)
+ if(!istype(holder_living) || !holder_living.mind || holder_living.mind.martial_art != src)
return
- on_remove(H)
+ on_remove(holder_living)
if(base)
- base.teach(H)
+ base.teach(holder_living)
else
- var/datum/martial_art/X = H.mind.default_martial_art
- X.teach(H)
+ var/datum/martial_art/default = holder_living.mind.default_martial_art
+ default.teach(holder_living)
+ holder = null
-/datum/martial_art/proc/on_remove(mob/living/carbon/human/H)
+/datum/martial_art/proc/on_remove(mob/living/holder_living)
if(help_verb)
- H.remove_verb(help_verb)
+ holder_living.remove_verb(help_verb)
return
+
+///Gets called when a projectile hits the owner. Returning anything other than BULLET_ACT_HIT will stop the projectile from hitting the mob.
+/datum/martial_art/proc/on_projectile_hit(mob/living/A, obj/projectile/P, def_zone)
+ return BULLET_ACT_HIT
diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm
index efa07687749ba..ccedec1bc37fd 100644
--- a/code/datums/martial/boxing.dm
+++ b/code/datums/martial/boxing.dm
@@ -1,24 +1,28 @@
/datum/martial_art/boxing
name = "Boxing"
id = MARTIALART_BOXING
+ pacifist_style = TRUE
-/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/boxing/disarm_act(mob/living/A, mob/living/D)
to_chat(A, span_warning("Can't disarm while boxing!"))
- return 1
+ return TRUE
-/datum/martial_art/boxing/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/boxing/grab_act(mob/living/A, mob/living/D)
to_chat(A, span_warning("Can't grab while boxing!"))
- return 1
+ return TRUE
-/datum/martial_art/boxing/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/boxing/harm_act(mob/living/A, mob/living/D)
+
+ var/mob/living/carbon/human/attacker_human = A
+ var/datum/species/species = attacker_human.dna.species
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
var/atk_verb = pick("left hook","right hook","straight punch")
- var/damage = 6 + A.dna.species.punchdamage
+ var/damage = 6 +species.punchdamage
if(!damage)
- playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
+ playsound(D.loc, species.miss_sound, 25, TRUE, -1)
D.visible_message(span_warning("[A]'s [atk_verb] misses [D]!"), \
span_userdanger("[A]'s [atk_verb] misses you!"), null, COMBAT_MESSAGE_RANGE)
log_combat(A, D, "attempted to hit", atk_verb, important = FALSE)
@@ -28,7 +32,7 @@
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D)))
var/armor_block = D.run_armor_check(affecting, MELEE)
- playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
+ playsound(D.loc, species.attack_sound, 25, TRUE, -1)
D.visible_message(span_danger("[A] [atk_verb]ed [D]!"), \
span_userdanger("[A] [atk_verb]ed you!"), null, COMBAT_MESSAGE_RANGE)
@@ -43,29 +47,31 @@
to_chat(A, span_danger("You knock [D] out with a haymaker!"))
D.apply_effect(200,EFFECT_KNOCKDOWN,armor_block)
D.SetSleeping(100)
- D.force_say(A)
log_combat(A, D, "knocked out (boxing) ", name)
- else if(D.body_position == LYING_DOWN)
- D.force_say(A)
return TRUE
+/datum/martial_art/boxing/can_use(mob/living/owner)
+ if (!ishuman(owner))
+ return FALSE
+ return ..()
+
/obj/item/clothing/gloves/boxing
var/datum/martial_art/boxing/style = new
/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
..()
+ // boxing requires human
if(!ishuman(user))
return
if(slot == ITEM_SLOT_GLOVES)
- var/mob/living/carbon/human/H = user
- style.teach(H,1)
+ var/mob/living/student = user
+ style.teach(student, 1)
return
/obj/item/clothing/gloves/boxing/dropped(mob/user)
..()
if(!ishuman(user))
return
- var/mob/living/carbon/human/H = user
- if(H.get_item_by_slot(ITEM_SLOT_GLOVES) == src)
- style.remove(H)
+ var/mob/living/owner = user
+ style.remove(owner)
return
diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm
index bc776b57aef2e..2bfbbff2352b9 100644
--- a/code/datums/martial/cqc.dm
+++ b/code/datums/martial/cqc.dm
@@ -7,49 +7,39 @@
/datum/martial_art/cqc
name = "CQC"
id = MARTIALART_CQC
- help_verb = /mob/living/carbon/human/proc/CQC_help
+ help_verb = /mob/living/proc/CQC_help
block_chance = 75
- var/just_a_cook = FALSE
smashes_tables = TRUE
+ display_combos = TRUE
+ var/old_grab_state = null
+ var/mob/restraining_mob
-/datum/martial_art/cqc/under_siege
- name = "Close Quarters Cooking"
- just_a_cook = TRUE
-
-/datum/martial_art/cqc/proc/drop_restraining()
- restraining = FALSE
-
-/datum/martial_art/cqc/can_use(mob/living/carbon/human/H)
- var/area/A = get_area(H)
- if(just_a_cook && !(istype(A, /area/crew_quarters/kitchen)))
- return FALSE
+/datum/martial_art/cqc/reset_streak(mob/living/new_target)
+ if(new_target && new_target != restraining_mob)
+ restraining_mob = null
return ..()
-/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/proc/check_streak(mob/living/A, mob/living/D)
if(!can_use(A))
return FALSE
if(findtext(streak,SLAM_COMBO))
- streak = ""
- Slam(A,D)
- return TRUE
+ reset_streak()
+ return Slam(A,D)
if(findtext(streak,KICK_COMBO))
- streak = ""
- Kick(A,D)
- return TRUE
+ reset_streak()
+ return Kick(A,D)
if(findtext(streak,RESTRAIN_COMBO))
- streak = ""
- Restrain(A,D)
- return TRUE
+ reset_streak()
+ return Restrain(A,D)
if(findtext(streak,PRESSURE_COMBO))
- streak = ""
- Pressure(A,D)
- return TRUE
+ reset_streak()
+ return Pressure(A,D)
if(findtext(streak,CONSECUTIVE_COMBO))
- streak = ""
- Consecutive(A,D)
+ reset_streak()
+ return Consecutive(A,D)
return FALSE
-/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/proc/Slam(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
if(!can_use(A))
return FALSE
@@ -59,11 +49,11 @@
to_chat(A, span_danger("You slam [D] into the ground!"))
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE, blocked = def_check)
- D.Paralyze(120)
+ D.Paralyze(12 SECONDS)
log_combat(A, D, "slammed (CQC)", name)
- return TRUE
+ return TRUE
-/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/proc/Kick(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
if(!can_use(A))
return FALSE
@@ -74,8 +64,9 @@
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, A.dir)
D.throw_at(throw_target, 1, 14, A)
- D.apply_damage(10, A.dna.species.attack_type, blocked = def_check)
+ D.apply_damage(10, A.get_attack_type(), blocked = def_check)
log_combat(A, D, "kicked (CQC)", name)
+ . = TRUE
if(D.IsParalyzed() && !D.stat)
log_combat(A, D, "knocked out (Head kick)(CQC)", name)
D.visible_message(span_danger("[A] kicks [D]'s head, knocking [D.p_them()] out!"), \
@@ -84,9 +75,9 @@
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
D.SetSleeping(10 SECONDS)
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150)
- return TRUE
+ . = TRUE
-/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/proc/Pressure(mob/living/A, mob/living/D)
if(!can_use(A))
return FALSE
log_combat(A, D, "pressured (CQC)", name)
@@ -97,8 +88,8 @@
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
return TRUE
-/datum/martial_art/cqc/proc/Restrain(mob/living/carbon/human/A, mob/living/carbon/human/D)
- if(restraining)
+/datum/martial_art/cqc/proc/Restrain(mob/living/A, mob/living/D)
+ if(restraining_mob)
return
if(!can_use(A))
return FALSE
@@ -108,12 +99,12 @@
span_userdanger("You're locked into a restraining position by [A]!"), span_hear("You hear shuffling and a muffled groan!"), null, A)
to_chat(A, span_danger("You lock [D] into a restraining position!"))
D.adjustStaminaLoss(20)
- D.Stun(100)
- restraining = TRUE
- addtimer(CALLBACK(src, PROC_REF(drop_restraining)), 50, TIMER_UNIQUE)
- return TRUE
+ D.Stun(10 SECONDS)
+ restraining_mob = D
+ addtimer(VARSET_CALLBACK(src, restraining_mob, null), 50, TIMER_UNIQUE)
+ return TRUE
-/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/proc/Consecutive(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
if(!can_use(A))
return FALSE
@@ -127,31 +118,28 @@
if(I && D.temporarilyRemoveItemFromInventory(I))
A.put_in_hands(I)
D.adjustStaminaLoss(50)
- D.apply_damage(25, A.dna.species.attack_type, blocked = def_check)
- return TRUE
+ D.apply_damage(25, A.get_attack_type(), blocked = def_check)
+ return TRUE
-/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
- if(!can_use(A))
- return FALSE
- if(A==D)
- return FALSE //prevents grabbing yourself
- if(A.a_intent == INTENT_GRAB)
+/datum/martial_art/cqc/grab_act(mob/living/A, mob/living/D)
+ if(A.a_intent == INTENT_GRAB && A!=D && can_use(A)) // A!=D prevents grabbing yourself
add_to_streak("G",D)
- if(check_streak(A,D)) //doing combos is prioritized over upgrading grabs
+ if(check_streak(A,D)) //if a combo is made no grab upgrade is done
return TRUE
+ old_grab_state = A.grab_state
D.grabbedby(A, 1)
- if(A.grab_state == GRAB_PASSIVE)
+ if(old_grab_state == GRAB_PASSIVE)
D.drop_all_held_items()
A.setGrabState(GRAB_AGGRESSIVE) //Instant aggressive grab if on grab intent
log_combat(A, D, "grabbed", name, addition="aggressively")
D.visible_message(span_warning("[A] violently grabs [D]!"), \
span_userdanger("You're grabbed violently by [A]!"), span_hear("You hear sounds of aggressive fondling!"), COMBAT_MESSAGE_RANGE, A)
to_chat(A, span_danger("You violently grab [D]!"))
+ return TRUE
else
- D.grabbedby(A, 1)
- return TRUE
+ return FALSE
-/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/harm_act(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
if(!can_use(A))
return FALSE
@@ -180,11 +168,11 @@
to_chat(A, span_danger("You leg sweep [D]!"))
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE, blocked = def_check)
- D.Paralyze(60)
+ D.Paralyze(6 SECONDS)
log_combat(A, D, "sweeped (CQC)", name)
return TRUE
-/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/cqc/disarm_act(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
if(!can_use(A))
return FALSE
@@ -192,8 +180,19 @@
var/obj/item/I = null
if(check_streak(A,D))
return TRUE
+ log_combat(A, D, "disarmed (CQC)", "[I ? " grabbing \the [I]" : ""]")
+ if(restraining_mob && A.pulling == restraining_mob)
+ log_combat(A, D, "knocked out (Chokehold)(CQC)", name)
+ D.visible_message("[A] puts [D] into a chokehold!", \
+ "You're put into a chokehold by [A]!", "You hear shuffling and a muffled groan!", null, A)
+ to_chat(A, "You put [D] into a chokehold!")
+ D.SetSleeping(40 SECONDS)
+ restraining_mob = null
+ if(A.grab_state < GRAB_NECK && !HAS_TRAIT(A, TRAIT_PACIFISM))
+ A.setGrabState(GRAB_NECK)
+ return TRUE
if(prob(65))
- if(!D.stat || !D.IsParalyzed() || !restraining)
+ if(!D.stat || !D.IsParalyzed() || !restraining_mob)
I = D.get_active_held_item()
D.visible_message(span_danger("[A] strikes [D]'s jaw with their hand!"), \
span_userdanger("Your jaw is struck by [A], you feel disoriented!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, A)
@@ -202,28 +201,16 @@
if(I && D.temporarilyRemoveItemFromInventory(I))
A.put_in_hands(I)
D.Jitter(2)
- D.apply_damage(5, A.dna.species.attack_type, blocked = def_check)
+ D.apply_damage(5, A.get_attack_type(), blocked = def_check)
else
- D.visible_message(span_danger("[A] fails to disarm [D]!"), \
- span_userdanger("You're nearly disarmed by [A]!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, A)
- to_chat(A, span_warning("You fail to disarm [D]!"))
- playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
- log_combat(A, D, "disarmed (CQC)[I ? " grabbing \the [I]" : ""]", name)
- if(restraining && A.pulling == D)
- log_combat(A, D, "knocked out (Chokehold)(CQC)", name)
- D.visible_message(span_danger("[A] puts [D] into a chokehold!"), \
- span_userdanger("You're put into a chokehold by [A]!"), span_hear("You hear shuffling and a muffled groan!"), null, A)
- to_chat(A, span_danger("You put [D] into a chokehold!"))
- D.SetSleeping(15 SECONDS)
- restraining = FALSE
- if(A.grab_state < GRAB_NECK)
- A.setGrabState(GRAB_NECK)
- else
- restraining = FALSE
- return FALSE
- return TRUE
+ D.visible_message("[A] fails to disarm [D]!", \
+ "You're nearly disarmed by [A]!", "You hear a swoosh!", COMBAT_MESSAGE_RANGE, A)
+ to_chat(A, "You fail to disarm [D]!")
+ playsound(D, 'sound/weapons/punchmiss.ogg', 25, TRUE, -1)
+ return FALSE
+
-/mob/living/carbon/human/proc/CQC_help()
+/mob/living/proc/CQC_help()
set name = "Remember The Basics"
set desc = "You try to remember some of the basics of CQC."
set category = "CQC"
@@ -237,6 +224,17 @@
to_chat(usr, "In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.")
+///Subtype of CQC. Only used for the chef.
+/datum/martial_art/cqc/under_siege
+ name = "Close Quarters Cooking"
+ var/list/valid_areas = list(/area/crew_quarters/kitchen)
+
+///Prevents use if the cook is not in the kitchen.
+/datum/martial_art/cqc/under_siege/can_use(mob/living/owner) //this is used to make chef CQC only work in kitchen
+ if(!is_type_in_list(get_area(owner), valid_areas))
+ return FALSE
+ return ..()
+
#undef SLAM_COMBO
#undef KICK_COMBO
#undef RESTRAIN_COMBO
diff --git a/code/datums/martial/karate.dm b/code/datums/martial/karate.dm
index 0094483b8549e..0339a7a782c75 100644
--- a/code/datums/martial/karate.dm
+++ b/code/datums/martial/karate.dm
@@ -11,19 +11,19 @@
/datum/martial_art/karate/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,JUMPING_KNEE_COMBO))
- streak = ""
+ reset_streak()
jumpingKnee(A,D)
return 1
if(findtext(streak,KARATE_CHOP_COMBO))
- streak = ""
+ reset_streak()
karateChop(A,D)
return 1
if(findtext(streak,FLOOR_KICK_COMBO))
- streak = ""
+ reset_streak()
floorKick(A,D)
return 1
if(findtext(streak,CALF_KICK_COMBO))
- streak = ""
+ reset_streak()
calfKick(A,D)
return 1
return 0
@@ -42,7 +42,7 @@
D.apply_damage(20, A.dna.species.attack_type, BODY_ZONE_HEAD, def_check)
D.apply_damage(10, STAMINA, BODY_ZONE_HEAD, def_check)
return 1
- return basic_hit(A,D)
+ return FALSE
//Calf Kick - paralyse one leg with stamina damage
/datum/martial_art/karate/proc/calfKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -57,7 +57,7 @@
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
D.apply_damage(50, STAMINA, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG), def_check)
return 1
- return basic_hit(A,D)
+ return FALSE
//Jumping Knee - brief knockdown and decent stamina damage
/datum/martial_art/karate/proc/jumpingKnee(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -74,7 +74,7 @@
D.apply_damage(30, STAMINA, BODY_ZONE_CHEST, def_check)
D.Knockdown(10)
return 1
- return basic_hit(A,D)
+ return FALSE
// Karate Chop - short confusion and blurred eyes
/datum/martial_art/karate/proc/karateChop(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -90,7 +90,7 @@
D.confused += 2
D.Jitter(20)
return 1
- return basic_hit(A,D)
+ return FALSE
/datum/martial_art/karate/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm
index d262d438776bd..c75c2345d0f46 100644
--- a/code/datums/martial/krav_maga.dm
+++ b/code/datums/martial/krav_maga.dm
@@ -14,13 +14,12 @@
if(owner.incapacitated())
to_chat(owner, span_warning("You can't use [name] while you're incapacitated."))
return
- var/mob/living/carbon/human/H = owner
- if (H.mind.martial_art.streak == "neck_chop")
+ if (owner.mind.martial_art.streak == "neck_chop")
owner.visible_message(span_danger("[owner] assumes a neutral stance."), "Your next attack is cleared.")
- H.mind.martial_art.streak = ""
+ owner.mind.martial_art.streak = ""
else
owner.visible_message(span_danger("[owner] assumes the Neck Chop stance!"), "Your next attack will be a Neck Chop.")
- H.mind.martial_art.streak = "neck_chop"
+ owner.mind.martial_art.streak = "neck_chop"
/datum/action/leg_sweep
name = "Leg Sweep - Trips the victim, knocking them down for a brief moment."
@@ -31,13 +30,12 @@
if(owner.incapacitated())
to_chat(owner, span_warning("You can't use [name] while you're incapacitated."))
return
- var/mob/living/carbon/human/H = owner
- if (H.mind.martial_art.streak == "leg_sweep")
+ if (owner.mind.martial_art.streak == "leg_sweep")
owner.visible_message(span_danger("[owner] assumes a neutral stance."), "Your next attack is cleared.")
- H.mind.martial_art.streak = ""
+ owner.mind.martial_art.streak = ""
else
owner.visible_message(span_danger("[owner] assumes the Leg Sweep stance!"), "Your next attack will be a Leg Sweep.")
- H.mind.martial_art.streak = "leg_sweep"
+ owner.mind.martial_art.streak = "leg_sweep"
/datum/action/lung_punch//referred to internally as 'quick choke'
name = "Lung Punch - Delivers a strong punch just above the victim's abdomen, constraining the lungs. The victim will be unable to breathe for a short time."
@@ -48,29 +46,28 @@
if(owner.incapacitated())
to_chat(owner, span_warning("You can't use [name] while you're incapacitated."))
return
- var/mob/living/carbon/human/H = owner
- if (H.mind.martial_art.streak == "quick_choke")
+ if (owner.mind.martial_art.streak == "quick_choke")
owner.visible_message(span_danger("[owner] assumes a neutral stance."), "Your next attack is cleared.")
- H.mind.martial_art.streak = ""
+ owner.mind.martial_art.streak = ""
else
owner.visible_message(span_danger("[owner] assumes the Lung Punch stance!"), "Your next attack will be a Lung Punch.")
- H.mind.martial_art.streak = "quick_choke"//internal name for lung punch
+ owner.mind.martial_art.streak = "quick_choke"//internal name for lung punch
-/datum/martial_art/krav_maga/teach(mob/living/carbon/human/H,make_temporary=0)
+/datum/martial_art/krav_maga/teach(mob/living/owner, make_temporary=FALSE)
if(..())
- to_chat(H, span_userdanger("You know the arts of [name]!"))
- to_chat(H, span_danger("Place your cursor over a move at the top of the screen to see what it does."))
- neckchop.Grant(H)
- legsweep.Grant(H)
- lungpunch.Grant(H)
-
-/datum/martial_art/krav_maga/on_remove(mob/living/carbon/human/H)
- to_chat(H, span_userdanger("You suddenly forget the arts of [name]..."))
- neckchop.Remove(H)
- legsweep.Remove(H)
- lungpunch.Remove(H)
-
-/datum/martial_art/krav_maga/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+ to_chat(owner, span_userdanger("You know the arts of [name]!"))
+ to_chat(owner, span_danger("Place your cursor over a move at the top of the screen to see what it does."))
+ neckchop.Grant(owner)
+ legsweep.Grant(owner)
+ lungpunch.Grant(owner)
+
+/datum/martial_art/krav_maga/on_remove(mob/living/owner)
+ to_chat(owner, span_userdanger("You suddenly forget the arts of [name]..."))
+ neckchop.Remove(owner)
+ legsweep.Remove(owner)
+ lungpunch.Remove(owner)
+
+/datum/martial_art/krav_maga/proc/check_streak(mob/living/A, mob/living/D)
switch(streak)
if("neck_chop")
streak = ""
@@ -86,7 +83,7 @@
return 1
return 0
-/datum/martial_art/krav_maga/proc/leg_sweep(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+/datum/martial_art/krav_maga/proc/leg_sweep(mob/living/A, mob/living/D)
if(D.stat || D.IsParalyzed())
return 0
var/obj/item/bodypart/affecting = D.get_bodypart(BODY_ZONE_CHEST)
@@ -98,9 +95,9 @@
D.apply_damage(rand(20,30), STAMINA, affecting, armor_block)
D.Knockdown(60)
log_combat(A, D, "leg sweeped", name)
- return 1
+ return TRUE
-/datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch
+/datum/martial_art/krav_maga/proc/quick_choke(mob/living/A, mob/living/D)//is actually lung punch
D.visible_message(span_warning("[A] pounds [D] on the chest!"), \
span_userdanger("Your chest is slammed by [A]! You can't breathe!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, A)
to_chat(A, span_danger("You pound [D] on the chest!"))
@@ -109,28 +106,30 @@
D.losebreath = clamp(D.losebreath + 5, 0, 10)
D.adjustOxyLoss(10)
log_combat(A, D, "quickchoked", name)
- return 1
+ return TRUE
-/datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+/datum/martial_art/krav_maga/proc/neck_chop(mob/living/A, mob/living/D)
D.visible_message(span_warning("[A] karate chops [D]'s neck!"), \
span_userdanger("Your neck is karate chopped by [A], rendering you unable to speak!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, A)
to_chat(A, span_danger("You karate chop [D]'s neck, rendering [D.p_them()] unable to speak!"))
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
- D.apply_damage(5, A.dna.species.attack_type)
- if(D.silent <= 10)
- D.silent = clamp(D.silent + 10, 0, 10)
+ D.apply_damage(5, A.get_attack_type())
+ if (iscarbon(D))
+ var/mob/living/carbon/carbon_defender = D
+ if(carbon_defender.silent <= 10)
+ carbon_defender.silent = clamp(carbon_defender.silent + 10, 0, 10)
log_combat(A, D, "neck chopped", name)
- return 1
+ return TRUE
-/datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+/datum/martial_art/krav_maga/grab_act(mob/living/A, mob/living/D)
if(check_streak(A,D))
- return 1
+ return TRUE
log_combat(A, D, "grabbed (Krav Maga)", name)
..()
-/datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+/datum/martial_art/krav_maga/harm_act(mob/living/A, mob/living/D)
if(check_streak(A,D))
- return 1
+ return TRUE
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D)))
var/armor_block = D.run_armor_check(affecting, MELEE)
var/picked_hit_type = pick("punch", "kick")
@@ -138,7 +137,7 @@
if(D.body_position == LYING_DOWN)
bonus_damage += 5
picked_hit_type = "stomp"
- D.apply_damage(rand(5,10) + bonus_damage, A.dna.species.attack_type, affecting, armor_block)
+ D.apply_damage(rand(5,10) + bonus_damage, A.get_attack_type(), affecting, armor_block)
if(picked_hit_type == "kick" || picked_hit_type == "stomp")
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
playsound(get_turf(D), 'sound/effects/hit_kick.ogg', 50, 1, -1)
@@ -151,7 +150,7 @@
log_combat(A, D, "[picked_hit_type] with [name]", name)
return 1
-/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+/datum/martial_art/krav_maga/disarm_act(mob/living/A, mob/living/D)
if(check_streak(A,D))
return 1
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D)))
@@ -194,19 +193,13 @@
/obj/item/clothing/gloves/krav_maga/equipped(mob/user, slot)
. = ..()
- if(!ishuman(user))
- return
if(slot == ITEM_SLOT_GLOVES)
- var/mob/living/carbon/human/H = user
- style.teach(H,1)
+ style.teach(user, TRUE)
/obj/item/clothing/gloves/krav_maga/dropped(mob/user)
. = ..()
- if(!ishuman(user))
- return
- var/mob/living/carbon/human/H = user
- if(H.get_item_by_slot(ITEM_SLOT_GLOVES) == src)
- style.remove(H)
+ if(user.get_item_by_slot(ITEM_SLOT_GLOVES) == src)
+ style.remove(user)
/obj/item/clothing/gloves/krav_maga/combatglovesplus
name = "combat gloves plus"
diff --git a/code/datums/martial/mushpunch.dm b/code/datums/martial/mushpunch.dm
index 1f9f0d32d5b72..3cda46667dc15 100644
--- a/code/datums/martial/mushpunch.dm
+++ b/code/datums/martial/mushpunch.dm
@@ -2,7 +2,7 @@
name = "Mushroom Punch"
id = MARTIALART_MUSHPUNCH
-/datum/martial_art/mushpunch/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/mushpunch/harm_act(mob/living/A, mob/living/D)
var/atk_verb
to_chat(A, span_spider("You begin to wind up an attack..."))
if(!do_after(A, 25, target = D))
@@ -13,7 +13,7 @@
D.visible_message(span_danger("[A] [atk_verb]ed [D] with such inhuman strength that it sends [D.p_them()] flying backwards!"), \
span_userdanger("You're [atk_verb]ed by [A] with such inhuman strength that it sends you flying backwards!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
to_chat(A, span_danger("You [atk_verb] [D] with such inhuman strength that it sends [D.p_them()] flying backwards!"))
- D.apply_damage(rand(15,30), A.dna.species.attack_type)
+ D.apply_damage(rand(15,30), A.get_attack_type())
playsound(D, 'sound/effects/meteorimpact.ogg', 25, 1, -1)
var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
@@ -28,7 +28,7 @@
icon = 'icons/obj/hydroponics/seeds.dmi'
icon_state = "mycelium-angel"
-/obj/item/mushpunch/attack_self(mob/living/carbon/human/user)
+/obj/item/mushpunch/attack_self(mob/living/user)
if(!istype(user) || !user)
return
var/message = span_spider("You devour [src], and a confluence of skill and power from the mushroom enhances your punches! You do need a short moment to charge these powerful punches.")
diff --git a/code/datums/martial/plasma_fist.dm b/code/datums/martial/plasma_fist.dm
index aeabb10ae5777..f5f7a8f190de3 100644
--- a/code/datums/martial/plasma_fist.dm
+++ b/code/datums/martial/plasma_fist.dm
@@ -5,23 +5,34 @@
/datum/martial_art/plasma_fist
name = "Plasma Fist"
id = MARTIALART_PLASMAFIST
- help_verb = /mob/living/carbon/human/proc/plasma_fist_help
+ help_verb = /mob/living/proc/plasma_fist_help
+ var/nobomb = FALSE
+ var/plasma_power = 1 //starts at a 1, 2, 4 explosion.
+ var/plasma_increment = 1 //how much explosion power gets added per kill (1 = 1, 2, 4. 2 = 2, 4, 8 and so on)
+ var/plasma_cap = 12 //max size explosion level
+ display_combos = TRUE
-
-/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/plasma_fist/proc/check_streak(mob/living/A, mob/living/D)
if(findtext(streak,TORNADO_COMBO))
- streak = ""
+ if(A == D)//helps using apotheosis
+ return FALSE
+ reset_streak()
Tornado(A,D)
- return 1
+ return TRUE
if(findtext(streak,THROWBACK_COMBO))
- streak = ""
+ if(A == D)//helps using apotheosis
+ return FALSE
+ reset_streak()
Throwback(A,D)
- return 1
+ return TRUE
if(findtext(streak,PLASMA_COMBO))
- streak = ""
- Plasma(A,D)
- return 1
- return 0
+ reset_streak()
+ if(A == D && !nobomb)
+ Apotheosis(A,D)
+ else
+ Plasma(A,D)
+ return TRUE
+ return FALSE
/datum/martial_art/plasma_fist/proc/TornadoAnimate(mob/living/carbon/human/A)
set waitfor = FALSE
@@ -32,7 +43,7 @@
playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1)
sleep(1)
-/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/plasma_fist/proc/Tornado(mob/living/A, mob/living/D)
A.say("TORNADO SWEEP!", forced="plasma fist")
TornadoAnimate(A)
var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null)
@@ -40,7 +51,7 @@
log_combat(A, D, "tornado sweeped(Plasma Fist)", name)
return
-/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/plasma_fist/proc/Throwback(mob/living/A, mob/living/D)
D.visible_message(span_danger("[A] hits [D] with Plasma Punch!"), \
span_userdanger("You're hit with a Plasma Punch by [A]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
to_chat(A, span_danger("You hit [D] with Plasma Punch!"))
@@ -51,47 +62,135 @@
log_combat(A, D, "threw back (Plasma Fist)", name)
return
-/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/plasma_fist/proc/Plasma(mob/living/A, mob/living/D)
+ var/hasclient = D.client ? TRUE : FALSE
+
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
A.say("PLASMA FIST!", forced="plasma fist")
D.visible_message(span_danger("[A] hits [D] with THE PLASMA FIST TECHNIQUE!"), \
span_userdanger("You're suddenly hit with THE PLASMA FIST TECHNIQUE by [A]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
to_chat(A, span_danger("You hit [D] with THE PLASMA FIST TECHNIQUE!"))
- D.gib()
log_combat(A, D, "gibbed (Plasma Fist)", name)
- return
+ var/turf/Dturf = get_turf(D)
+ D.gib()
+ if(nobomb)
+ return
+ if(!hasclient)
+ to_chat(A, "Taking this plasma energy for your Apotheosis would bring dishonor to the clan!")
+ new /obj/effect/temp_visual/plasma_soul(Dturf)//doesn't beam to you, so it just hangs around and poofs.
+ return
+ else if(plasma_power >= plasma_cap)
+ to_chat(A, "You cannot power up your Apotheosis any more!")
+ new /obj/effect/temp_visual/plasma_soul(Dturf)//doesn't beam to you, so it just hangs around and poofs.
+ else
+ plasma_power += plasma_increment
+ to_chat(A, "Power increasing! Your Apotheosis is now at power level [plasma_power]!")
+ new /obj/effect/temp_visual/plasma_soul(Dturf, A)
+ var/oldcolor = A.color
+ A.color = "#9C00FF"
+ flash_color(A, flash_color = "#9C00FF", flash_time = 3 SECONDS)
+ animate(A, color = oldcolor, time = 3 SECONDS)
+
+
+/datum/martial_art/plasma_fist/proc/Apotheosis(mob/living/A, mob/living/D)
+ A.say("APOTHEOSIS!!", forced="plasma fist")
+ if (ishuman(A))
+ var/mob/living/carbon/human/human_attacker = A
+ human_attacker.set_species(/datum/species/plasmaman)
+ human_attacker.dna.species.species_traits += TRAIT_BOMBIMMUNE
+ human_attacker.unequip_everything()
+ human_attacker.underwear = "Nude"
+ human_attacker.undershirt = "Nude"
+ human_attacker.socks = "Nude"
+ human_attacker.update_body()
+ var/turf/boomspot = get_turf(A)
+
+ //before ghosting to prevent issues
+ log_combat(A, A, "triggered final plasma explosion with size [plasma_power], [plasma_power*2], [plasma_power*4] (Plasma Fist)")
+ message_admins("[key_name_admin(A)] triggered final plasma explosion with size [plasma_power], [plasma_power*2], [plasma_power*4].")
+
+ to_chat(A, "The explosion knocks your soul out of your body!")
+ A.ghostize(FALSE) //prevents... horrible memes just believe me
-/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+ A.apply_damage(rand(50,70), BRUTE)
+
+ addtimer(CALLBACK(src, PROC_REF(Apotheosis_end), A), 6 SECONDS)
+ playsound(boomspot, 'sound/weapons/punch1.ogg', 50, TRUE, -1)
+ explosion(boomspot,plasma_power,plasma_power*2,plasma_power*4,ignorecap = TRUE)
+ plasma_power = 1 //just in case there is any clever way to cause it to happen again
+
+/datum/martial_art/plasma_fist/proc/Apotheosis_end(mob/living/dying)
+ var/datum/dna/dna = dying.has_dna()
+ if (dna?.species)
+ dna.species.species_traits -= TRAIT_BOMBIMMUNE
+ if(dying.stat == DEAD)
+ return
+ dying.death()
+
+/datum/martial_art/plasma_fist/harm_act(mob/living/A, mob/living/D)
add_to_streak("H",D)
if(check_streak(A,D))
- return 1
- basic_hit(A,D)
- return 1
+ return TRUE
+ return FALSE
-/datum/martial_art/plasma_fist/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/plasma_fist/disarm_act(mob/living/A, mob/living/D)
add_to_streak("D",D)
if(check_streak(A,D))
- return 1
- basic_hit(A,D)
- return 1
+ return TRUE
+ if(A == D)//there is no disarming yourself, so we need to let plasma fist user know
+ to_chat(A, "You have added a disarm to your streak.")
+ return FALSE
-/datum/martial_art/plasma_fist/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/plasma_fist/grab_act(mob/living/A, mob/living/D)
add_to_streak("G",D)
if(check_streak(A,D))
- return 1
- basic_hit(A,D)
- return 1
+ return TRUE
+ return FALSE
-/mob/living/carbon/human/proc/plasma_fist_help()
+/mob/living/proc/plasma_fist_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Plasma Fist."
set category = "Plasma Fist"
+ var/datum/martial_art/plasma_fist/martial = usr.mind.martial_art
to_chat(usr, "You clench your fists and have a flashback of knowledge...")
to_chat(usr, "[span_notice("Tornado Sweep")]: Harm Harm Disarm. Repulses target and everyone back.")
to_chat(usr, "[span_notice("Throwback")]: Disarm Harm Disarm. Throws the target and an item at them.")
to_chat(usr, "[span_notice("The Plasma Fist")]: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.")
+ if(!martial.nobomb)
+ to_chat(usr, "Apotheosis: Use The Plasma Fist on yourself. Sends you away in a glorious explosion.")
+
+
+/obj/effect/temp_visual/plasma_soul
+ name = "plasma energy"
+ desc = "Leftover energy brought out from The Plasma Fist."
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "explosion"
+ duration = 3 SECONDS
+ var/atom/movable/beam_target
+
+/obj/effect/temp_visual/plasma_soul/Initialize(mapload, _beam_target)
+ . = ..()
+ beam_target = _beam_target
+ if(beam_target)
+ var/datum/beam/beam = Beam(beam_target, "plasmabeam", time= 3 SECONDS, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/plasma_fist)
+ animate(beam.visuals, alpha = 0, time = 3 SECONDS)
+ animate(src, alpha = 0, transform = matrix()*0.5, time = 3 SECONDS)
+
+/obj/effect/temp_visual/plasma_soul/Destroy()
+ if(!beam_target)
+ visible_message("[src] fades away...")
+ . = ..()
+
+/obj/effect/ebeam/plasma_fist
+ name = "plasma"
+ mouse_opacity = MOUSE_OPACITY_ICON
+ desc = "Flowing energy."
+
+/datum/martial_art/plasma_fist/nobomb
+ name = "Novice Plasma Fist"
+ nobomb = TRUE
#undef TORNADO_COMBO
#undef THROWBACK_COMBO
diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm
index ad0af9ccb9561..829917680e23e 100644
--- a/code/datums/martial/psychotic_brawl.dm
+++ b/code/datums/martial/psychotic_brawl.dm
@@ -2,24 +2,26 @@
name = "Psychotic Brawling"
id = MARTIALART_PSYCHOBRAWL
-/datum/martial_art/psychotic_brawling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/psychotic_brawling/disarm_act(mob/living/A, mob/living/D)
if(HAS_TRAIT(A, TRAIT_PACIFISM))
return FALSE
return psycho_attack(A,D)
-/datum/martial_art/psychotic_brawling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/psychotic_brawling/grab_act(mob/living/A, mob/living/D)
if(HAS_TRAIT(A, TRAIT_PACIFISM))
return FALSE
return psycho_attack(A,D)
-/datum/martial_art/psychotic_brawling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/psychotic_brawling/harm_act(mob/living/A, mob/living/D)
return psycho_attack(A,D)
-/datum/martial_art/psychotic_brawling/proc/psycho_attack(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/psychotic_brawling/proc/psycho_attack(mob/living/A, mob/living/D)
var/atk_verb
switch(rand(1,8))
if(1)
- D.help_shake_act(A)
+ if (iscarbon(D) && iscarbon(A))
+ var/mob/living/carbon/defender = D
+ defender.help_shake_act(A)
atk_verb = "helped"
if(2)
A.emote("cry")
@@ -49,10 +51,12 @@
span_userdanger("You're [atk_verb]ed by [A]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
to_chat(A, span_danger("You [atk_verb] [D]!"))
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 40, 1, -1)
- D.apply_damage(rand(5,10), A.dna.species.attack_type, BODY_ZONE_HEAD)
- A.apply_damage(rand(5,10), A.dna.species.attack_type, BODY_ZONE_HEAD)
- if(!istype(D.head,/obj/item/clothing/head/helmet/) && !istype(D.head,/obj/item/clothing/head/utility/hardhat))
- D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
+ D.apply_damage(rand(5,10), A.get_attack_type(), BODY_ZONE_HEAD)
+ A.apply_damage(rand(5,10), A.get_attack_type(), BODY_ZONE_HEAD)
+ if (iscarbon(D))
+ var/mob/living/carbon/defender = D
+ if(!istype(defender.head,/obj/item/clothing/head/helmet/) && !istype(defender.head,/obj/item/clothing/head/utility/hardhat))
+ defender.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
A.Stun(rand(10,45))
D.Stun(rand(5,30))
if(5,6)
@@ -61,14 +65,14 @@
D.visible_message(span_danger("[A] [atk_verb]s [D] with such inhuman strength that it sends [D.p_them()] flying backwards!"), \
span_userdanger("You're [atk_verb]ed by [A] with such inhuman strength that it sends you flying backwards!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
to_chat(A, span_danger("You [atk_verb] [D] with such inhuman strength that it sends [D.p_them()] flying backwards!"))
- D.apply_damage(rand(15,30), A.dna.species.attack_type)
+ D.apply_damage(rand(15,30), A.get_attack_type())
playsound(get_turf(D), 'sound/effects/meteorimpact.ogg', 25, 1, -1)
var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
D.Paralyze(60)
if(7,8)
- basic_hit(A,D)
+ return FALSE //Resume default behaviour
if(atk_verb)
log_combat(A, D, "[atk_verb] (Psychotic Brawling)", name)
- return 1
+ return TRUE
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index 30699fa6ec5e5..5020ca2270fec 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -7,37 +7,36 @@
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
id = MARTIALART_SLEEPINGCARP
- deflection_chance = 100
- reroute_deflection = TRUE
- no_guns = TRUE
allow_temp_override = FALSE
- help_verb = /mob/living/carbon/human/proc/sleeping_carp_help
+ help_verb = /mob/living/proc/sleeping_carp_help
smashes_tables = TRUE
+ display_combos = TRUE
+ var/old_grab_state = null
-/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/A, mob/living/D)
if(findtext(streak,WRIST_WRENCH_COMBO))
- streak = ""
+ reset_streak()
wristWrench(A,D)
- return 1
+ return TRUE
if(findtext(streak,BACK_KICK_COMBO))
- streak = ""
+ reset_streak()
backKick(A,D)
- return 1
+ return TRUE
if(findtext(streak,STOMACH_KNEE_COMBO))
- streak = ""
+ reset_streak()
kneeStomach(A,D)
- return 1
+ return TRUE
if(findtext(streak,HEAD_KICK_COMBO))
- streak = ""
+ reset_streak()
headKick(A,D)
- return 1
+ return TRUE
if(findtext(streak,ELBOW_DROP_COMBO))
- streak = ""
+ reset_streak()
elbowDrop(A,D)
- return 1
- return 0
+ return TRUE
+ return FALSE
-/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/A, mob/living/D)
if(!D.stat && !D.IsStun() && !D.IsParalyzed())
log_combat(A, D, "wrist wrenched (Sleeping Carp)", name)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
@@ -51,28 +50,26 @@
D.Stun(60)
return 1
- return basic_hit(A,D)
+ return FALSE
-/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/A, mob/living/D)
if(!D.stat && !D.IsParalyzed())
- if(A.dir == D.dir)
- log_combat(A, D, "back-kicked (Sleeping Carp)", name)
- A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
- D.visible_message(span_warning("[A] kicks [D] in the back!"), \
- span_danger("You're kicked in the back by [A]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
- to_chat(A, span_danger("You kick [D] in the back!"))
- step_to(D,get_step(D,D.dir),1)
- D.Paralyze(80)
- playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
- return 1
- else
+ if(A.dir != D.dir)
log_combat(A, D, "missed a back-kick (Sleeping Carp) on", name)
- D.visible_message(span_warning("[A] tries to kick [D] in the back, but misses!"), \
- span_danger("You avoid a kick in the back by [A]!"), span_hear("You hear a swoosh!"), null, A)
- to_chat(A, span_warning("Your kick to [D]'s back misses!"))
- return basic_hit(A,D)
+ D.visible_message("[A] tries to kick [D] in the back, but misses!", \
+ "[A] tries to kick you in the back, but misses!")
+ return TRUE
+ log_combat(A, D, "back-kicked (Sleeping Carp)", name)
+ A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
+ D.visible_message("[A] kicks [D] in the back!", \
+ "[A] kicks you in the back, making you stumble and fall!")
+ step_to(D,get_step(D,D.dir),1)
+ D.Paralyze(80)
+ playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, TRUE, -1)
+ return TRUE
+ return FALSE
-/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/A, mob/living/D)
if(!D.stat && !D.IsParalyzed())
log_combat(A, D, "stomach kneed (Sleeping Carp)", name)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
@@ -84,24 +81,24 @@
D.Stun(40)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
- return basic_hit(A,D)
+ return FALSE
-/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_HEAD, MELEE)
if(!D.stat && !D.IsParalyzed())
log_combat(A, D, "head kicked (Sleeping Carp)", name)
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
- D.visible_message(span_warning("[A] kicks [D] in the head!"), \
- span_userdanger("Your jaw is kicked by [A]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, A)
- to_chat(A, span_danger("You kick [D] in the jaw!"))
- D.apply_damage(20, A.dna.species.attack_type, BODY_ZONE_HEAD, blocked = def_check)
+ D.visible_message("[A] kicks [D] in the head!", \
+ "Your jaw is kicked by [A]!", "You hear a sickening sound of flesh hitting flesh!", null, A)
+ to_chat(A, "You kick [D] in the jaw!")
+ D.apply_damage(20, A.get_attack_type(), BODY_ZONE_HEAD, blocked = def_check)
D.drop_all_held_items()
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
D.Stun(80)
return 1
- return basic_hit(A,D)
+ return FALSE
-/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
if(D.body_position == LYING_DOWN)
log_combat(A, D, "elbow dropped (Sleeping Carp)", name)
@@ -111,31 +108,29 @@
to_chat(A, span_danger("You piledrive [D] with your elbow!"))
if(D.stat)
D.death() //FINISH HIM!
- D.apply_damage(50, A.dna.species.attack_type, BODY_ZONE_CHEST, blocked = def_check)
+ D.apply_damage(50, A.get_attack_type(), BODY_ZONE_CHEST, blocked = def_check)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1)
return 1
- return basic_hit(A,D)
+ return FALSE
-/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
- if(A==D)
- return 0 //prevents grabbing yourself
- if(A.a_intent == INTENT_GRAB)
+/datum/martial_art/the_sleeping_carp/grab_act(mob/living/A, mob/living/D)
+ if(A.a_intent == INTENT_GRAB && A!=D) // A!=D prevents grabbing yourself
add_to_streak("G",D)
- if(check_streak(A,D)) //doing combos is prioritized over upgrading grabs
- return 1
+ if(check_streak(A,D)) //if a combo is made no grab upgrade is done
+ return TRUE
+ old_grab_state = A.grab_state
D.grabbedby(A, 1)
- if(A.grab_state == GRAB_PASSIVE)
+ if(old_grab_state == GRAB_PASSIVE)
D.drop_all_held_items()
A.setGrabState(GRAB_AGGRESSIVE) //Instant aggressive grab if on grab intent
log_combat(A, D, "grabbed", name, addition="aggressively")
- D.visible_message(span_warning("[A] violently grabs [D]!"), \
- span_userdanger("You're violently grabbed by [A]!"), span_hear("You hear aggressive shuffling!"), null, A)
- to_chat(A, span_danger("You violently grab [D]!"))
- else
- D.grabbedby(A, 1)
- return 1
+ D.visible_message("[A] violently grabs [D]!", \
+ "You're violently grabbed by [A]!", "You hear aggressive shuffling!", null, A)
+ to_chat(A, "You violently grab [D]!")
+ return TRUE
+ return FALSE
-/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/harm_act(mob/living/A, mob/living/D)
var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE)
add_to_streak("H",D)
if(check_streak(A,D))
@@ -151,13 +146,42 @@
return TRUE
-/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/A, mob/living/D)
add_to_streak("D",D)
if(check_streak(A,D))
return TRUE
return ..()
-/mob/living/carbon/human/proc/sleeping_carp_help()
+/datum/martial_art/the_sleeping_carp/on_projectile_hit(mob/living/A, obj/projectile/P, def_zone)
+ . = ..()
+ if(A.incapacitated(FALSE, TRUE)) //NO STUN
+ return BULLET_ACT_HIT
+ if(!(A.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE
+ return BULLET_ACT_HIT
+ var/datum/dna/dna = A.has_dna()
+ if(dna?.check_mutation(HULK)) //NO HULK
+ return BULLET_ACT_HIT
+ if(!P.martial_arts_no_deflect)
+ return BULLET_ACT_HIT
+ if(!isturf(A.loc)) //NO MOTHERFLIPPIN MECHS!
+ return BULLET_ACT_HIT
+ A.visible_message("[A] deflects the projectile; [A.p_they()] can't be hit with ranged weapons!", "You deflect the projectile!")
+ playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
+ P.firer = A
+ P.set_angle(rand(0, 360))//SHING
+ return BULLET_ACT_FORCE_PIERCE
+
+/datum/martial_art/the_sleeping_carp/teach(mob/living/carbon/human/H, make_temporary = FALSE)
+ . = ..()
+ if(!.)
+ return
+ ADD_TRAIT(H, TRAIT_NOGUNS, SLEEPING_CARP_TRAIT)
+
+/datum/martial_art/the_sleeping_carp/on_remove(mob/living/carbon/human/H)
+ . = ..()
+ REMOVE_TRAIT(H, TRAIT_NOGUNS, SLEEPING_CARP_TRAIT)
+
+/mob/living/proc/sleeping_carp_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Sleeping Carp clan."
set category = "Sleeping Carp"
diff --git a/code/datums/martial/tribal_claw.dm b/code/datums/martial/tribal_claw.dm
index f6768b45cc803..b15dfb9a438ea 100644
--- a/code/datums/martial/tribal_claw.dm
+++ b/code/datums/martial/tribal_claw.dm
@@ -66,7 +66,7 @@ Deals 15 brute to head(reduced by armor) and causes a rapid bleeding effect simi
A.do_attack_animation(D, ATTACK_EFFECT_CLAW)
playsound(get_turf(D), 'sound/weapons/slash.ogg', 50, 1, -1)
else
- return basic_hit(A,D)
+ return FALSE
//Tail Grab, instantly puts your target in a T3 grab and makes them unable to talk for a short time.
/datum/martial_art/tribal_claw/proc/tailGrab(mob/living/carbon/human/A, mob/living/carbon/human/D)
diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm
index 85073cb867315..078dac2aa267b 100644
--- a/code/datums/martial/wrestling.dm
+++ b/code/datums/martial/wrestling.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/human/proc/wrestling_help()
+/mob/living/proc/wrestling_help()
set name = "Recall Teachings"
set desc = "Remember how to wrestle."
set category = "Wrestling"
@@ -17,7 +17,7 @@
var/datum/action/strike/strike = new/datum/action/strike()
var/datum/action/drop/drop = new/datum/action/drop()
-/datum/martial_art/wrestling/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/check_streak(mob/living/A, mob/living/D)
switch(streak)
if("drop")
streak = ""
@@ -50,8 +50,7 @@
to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT."))
return
owner.visible_message(span_danger("[owner] prepares to BODY SLAM!"), "Your next attack will be a BODY SLAM.")
- var/mob/living/carbon/human/H = owner
- H.mind.martial_art.streak = "slam"
+ owner.mind.martial_art.streak = "slam"
/datum/action/throw_wrassle
name = "Throw (Cinch) - Spin a cinched opponent around and throw them."
@@ -62,8 +61,7 @@
to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT."))
return
owner.visible_message(span_danger("[owner] prepares to THROW!"), "Your next attack will be a THROW.")
- var/mob/living/carbon/human/H = owner
- H.mind.martial_art.streak = "throw"
+ owner.mind.martial_art.streak = "throw"
/datum/action/kick
name = "Kick - A powerful kick, sends people flying away from you. Also useful for escaping from bad situations."
@@ -74,8 +72,7 @@
to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT."))
return
owner.visible_message(span_danger("[owner] prepares to KICK!"), "Your next attack will be a KICK.")
- var/mob/living/carbon/human/H = owner
- H.mind.martial_art.streak = "kick"
+ owner.mind.martial_art.streak = "kick"
/datum/action/strike
name = "Strike - Hit a neaby opponent with a quick attack."
@@ -86,8 +83,7 @@
to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT."))
return
owner.visible_message(span_danger("[owner] prepares to STRIKE!"), "Your next attack will be a STRIKE.")
- var/mob/living/carbon/human/H = owner
- H.mind.martial_art.streak = "strike"
+ owner.mind.martial_art.streak = "strike"
/datum/action/drop
name = "Drop - Smash down onto an opponent."
@@ -98,34 +94,33 @@
to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT."))
return
owner.visible_message(span_danger("[owner] prepares to LEG DROP!"), "Your next attack will be a LEG DROP.")
- var/mob/living/carbon/human/H = owner
- H.mind.martial_art.streak = "drop"
+ owner.mind.martial_art.streak = "drop"
-/datum/martial_art/wrestling/teach(mob/living/carbon/human/H,make_temporary=0)
+/datum/martial_art/wrestling/teach(mob/living/owner, make_temporary=FALSE)
if(..())
- to_chat(H, span_userdanger("SNAP INTO A THIN TIM!"))
- to_chat(H, span_danger("Place your cursor over a move at the top of the screen to see what it does."))
- drop.Grant(H)
- kick.Grant(H)
- slam.Grant(H)
- throw_wrassle.Grant(H)
- strike.Grant(H)
-
-/datum/martial_art/wrestling/on_remove(mob/living/carbon/human/H)
- to_chat(H, span_userdanger("You no longer feel that the tower of power is too sweet to be sour..."))
- drop.Remove(H)
- kick.Remove(H)
- slam.Remove(H)
- throw_wrassle.Remove(H)
- strike.Remove(H)
-
-/datum/martial_art/wrestling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+ to_chat(owner, span_userdanger("SNAP INTO A THIN TIM!"))
+ to_chat(owner, span_danger("Place your cursor over a move at the top of the screen to see what it does."))
+ drop.Grant(owner)
+ kick.Grant(owner)
+ slam.Grant(owner)
+ throw_wrassle.Grant(owner)
+ strike.Grant(owner)
+
+/datum/martial_art/wrestling/on_remove(mob/living/owner)
+ to_chat(owner, span_userdanger("You no longer feel that the tower of power is too sweet to be sour..."))
+ drop.Remove(owner)
+ kick.Remove(owner)
+ slam.Remove(owner)
+ throw_wrassle.Remove(owner)
+ strike.Remove(owner)
+
+/datum/martial_art/wrestling/harm_act(mob/living/A, mob/living/D)
if(check_streak(A,D))
return 1
log_combat(A, D, "punched with wrestling", name)
..()
-/datum/martial_art/wrestling/proc/throw_wrassle(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/throw_wrassle(mob/living/A, mob/living/D)
if(!D)
return
if(!A.pulling || A.pulling != D)
@@ -197,11 +192,11 @@
if (T && isturf(T))
if (!D.stat)
D.emote("scream")
- D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, TYPE_PROC_REF(/mob/living/carbon/human, Paralyze), 20))
+ D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, TYPE_PROC_REF(/mob/living, Paralyze), 20))
log_combat(A, D, "has thrown with wrestling", name)
return 0
-/datum/martial_art/wrestling/proc/FlipAnimation(mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/FlipAnimation(mob/living/D)
set waitfor = FALSE
if (D)
animate(D, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0)
@@ -209,7 +204,7 @@
if (D)
animate(D, transform = null, time = 1, loop = 0)
-/datum/martial_art/wrestling/proc/slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/slam(mob/living/A, mob/living/D)
if(!D)
return
if(!A.pulling || A.pulling != D)
@@ -321,11 +316,11 @@
log_combat(A, D, "body-slammed", name)
return 0
-/datum/martial_art/wrestling/proc/CheckStrikeTurf(mob/living/carbon/human/A, turf/T)
+/datum/martial_art/wrestling/proc/CheckStrikeTurf(mob/living/A, turf/T)
if (A && (T && isturf(T) && get_dist(A, T) <= 1))
A.forceMove(T)
-/datum/martial_art/wrestling/proc/strike(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/strike(mob/living/A, mob/living/D)
if(!D)
return
var/turf/T = get_turf(A)
@@ -344,7 +339,7 @@
D.Unconscious(20)
log_combat(A, D, "headbutted", name)
-/datum/martial_art/wrestling/proc/kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/kick(mob/living/A, mob/living/D)
if(!D)
return
A.emote("scream")
@@ -363,7 +358,7 @@
D.throw_at(T, 3, 2)
log_combat(A, D, "roundhouse-kicked", name)
-/datum/martial_art/wrestling/proc/drop(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/proc/drop(mob/living/A, mob/living/D)
if(!D)
return
var/obj/surface = null
@@ -439,13 +434,13 @@
log_combat(A, D, "leg-dropped", name)
return
-/datum/martial_art/wrestling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/disarm_act(mob/living/A, mob/living/D)
if(check_streak(A,D))
return 1
log_combat(A, D, "wrestling-disarmed", name)
..()
-/datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
+/datum/martial_art/wrestling/grab_act(mob/living/A, mob/living/D)
if(check_streak(A,D))
return 1
if(A.pulling == D)
@@ -464,17 +459,11 @@
/obj/item/storage/belt/champion/wrestling/equipped(mob/user, slot)
. = ..()
- if(!ishuman(user))
- return
if(slot == ITEM_SLOT_BELT)
- var/mob/living/carbon/human/H = user
- style.teach(H,1)
+ style.teach(user, TRUE)
return
/obj/item/storage/belt/champion/wrestling/dropped(mob/user)
. = ..()
- if(!ishuman(user))
- return
- var/mob/living/carbon/human/H = user
- if(H.get_item_by_slot(ITEM_SLOT_BELT) == src)
- style.remove(H)
+ if(user.get_item_by_slot(ITEM_SLOT_BELT) == src)
+ style.remove(user)
diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm
index 25c3d1fd36da7..e07173b721ad4 100644
--- a/code/datums/mutations/hulk.dm
+++ b/code/datums/mutations/hulk.dm
@@ -25,6 +25,7 @@
return
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "hulk", /datum/mood_event/hulk)
RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech))
+ ADD_TRAIT(owner, TRAIT_CHUNKYFINGERS, TRAIT_HULK)
owner.update_body_parts()
/datum/mutation/hulk/on_attack_hand(atom/target, proximity)
@@ -40,6 +41,7 @@
if(..())
return
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "hulk")
+ REMOVE_TRAIT(owner, TRAIT_CHUNKYFINGERS, TRAIT_HULK)
owner.update_body_parts()
UnregisterSignal(owner, COMSIG_MOB_SAY)
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index 37c0003425ea4..17f102430ffd3 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -78,17 +78,11 @@
if (!user.IsAdvancedToolUser())
to_chat(user, span_warning("You don't have the dexterity to do this!"))
return
- if(HAS_TRAIT(user, TRAIT_NOGUNS))
- to_chat(user, span_warning("Your fingers can't press the button!"))
+ if(HAS_TRAIT(user, TRAIT_CHUNKYFINGERS))
+ to_chat(user, "Your fingers can't press the button!")
return
- if(user.has_dna())
- var/mob/living/carbon/C = user
- if(C.dna.check_mutation(HULK))
- to_chat(user, span_warning("Your fingers can't press the button!"))
- return
-
add_fingerprint(user)
-
+
//nothing happens if the battery is drained
if(recharge_locked)
to_chat(user, span_notice("You point [src] at [target], but it's still charging."))
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index 845fa09cc2932..18ff72fdcdf3f 100644
--- a/code/game/objects/items/granters.dm
+++ b/code/game/objects/items/granters.dm
@@ -439,6 +439,9 @@
name = "empty scroll"
icon_state = "blankscroll"
+/obj/item/book/granter/martial/plasma_fist/nobomb
+ martial = /datum/martial_art/plasma_fist/nobomb
+
// I did not include mushpunch's grant, it is not a book and the item does it just fine.
//Crafting Recipe books
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 4b49d3d1d4e3a..70577fcc7912b 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -168,7 +168,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/table)
/obj/structure/table/proc/tableheadsmash(mob/living/user, mob/living/pushed_mob)
pushed_mob.Knockdown(30)
- pushed_mob.apply_damage(40, BRUTE, BODY_ZONE_HEAD)
+ pushed_mob?.apply_damage(40, BRUTE, BODY_ZONE_HEAD)
pushed_mob.apply_damage(60, STAMINA)
take_damage(50)
if(user.mind?.martial_art?.smashes_tables)
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 44344b0681a6f..9d2f7e37e8d51 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -1210,7 +1210,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/item/shared_storage/blue)
to_chat(user, span_warning("[name] is too far from the source of its power!"))
else
power = 15
- if(user.mind.martial_art.no_guns)
+ if(HAS_TRAIT_FROM(user, TRAIT_NOGUNS, SLEEPING_CARP_TRAIT))
to_chat(user, span_warning("To use this weapon would bring dishonor to the clan."))
return
var/turf/T = get_turf(target)
diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm
index ecb61a4f1db70..120123492f701 100644
--- a/code/modules/mob/living/carbon/alien/alien_defense.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defense.dm
@@ -12,14 +12,18 @@
As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
In all, this is a lot like the monkey code. /N
*/
-/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
+/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/user, list/modifiers)
if(isturf(loc) && istype(loc.loc, /area/start))
- to_chat(M, "No attacking people at spawn, you jackass.")
+ to_chat(user, "No attacking people at spawn, you jackass.")
return
- switch(M.a_intent)
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
+
+ switch(user.a_intent)
if("help")
- if(M == src && check_self_for_injuries())
+ if(user == src && check_self_for_injuries())
return
set_resting(FALSE)
AdjustStun(-60)
@@ -28,23 +32,23 @@ In all, this is a lot like the monkey code. /N
AdjustParalyzed(-60)
AdjustUnconscious(-60)
AdjustSleeping(-100)
- visible_message(span_notice("[M.name] nuzzles [src] trying to wake [p_them()] up!"))
+ visible_message(span_notice("[user.name] nuzzles [src] trying to wake [p_them()] up!"))
if("grab")
- grabbedby(M)
+ grabbedby(user)
else
if(health > 1)
- M.do_attack_animation(src, ATTACK_EFFECT_BITE)
+ user.do_attack_animation(src, ATTACK_EFFECT_BITE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
- visible_message(span_danger("[M.name] playfully bites [src]!"), \
- span_userdanger("[M.name] playfully bites you!"), null, COMBAT_MESSAGE_RANGE)
- to_chat(M, span_danger("You playfully bite [src]!"))
+ visible_message(span_danger("[user.name] playfully bites [src]!"), \
+ span_userdanger("[user.name] playfully bites you!"), null, COMBAT_MESSAGE_RANGE)
+ to_chat(user, span_danger("You playfully bite [src]!"))
adjustBruteLoss(1)
- log_combat(M, src, "attacked", M)
+ log_combat(user, src, "attacked", user)
updatehealth()
else
- to_chat(M, span_warning("[name] is too injured for that."))
+ to_chat(user, span_warning("[name] is too injured for that."))
/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index ac113bf93469b..d411fcf648e5c 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1236,3 +1236,26 @@ CREATION_TEST_IGNORE_SELF(/mob/living/carbon)
set_lying_angle(pick(90, 270))
else
set_lying_angle(new_lying_angle)
+
+
+/mob/living/carbon/vv_edit_var(var_name, var_value)
+ switch(var_name)
+ if(NAMEOF(src, disgust))
+ set_disgust(var_value)
+ . = TRUE
+ if(NAMEOF(src, handcuffed))
+ set_handcuffed(var_value)
+ . = TRUE
+
+ if(!isnull(.))
+ datum_flags |= DF_VAR_EDITED
+ return
+
+ return ..()
+
+
+/mob/living/carbon/get_attack_type()
+ var/datum/species/species = dna?.species
+ if (species)
+ return species.attack_type
+ return ..()
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 0bd8dcad70dda..ddbbdc53185ae 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -71,25 +71,12 @@
if(spec_return)
return spec_return
+ //MARTIAL ART STUFF
if(mind)
- if(mind.martial_art && !incapacitated(FALSE, TRUE) && mind.martial_art.can_use(src) && mind.martial_art.deflection_chance) //Some martial arts users can deflect projectiles!
- if(prob(mind.martial_art.deflection_chance))
- if((mobility_flags & MOBILITY_USE) && dna && !dna.check_mutation(HULK) && !P.martial_arts_no_deflect) //But only if they're otherwise able to use items, and hulks can't do it. Also damageless weapons are not deflected.
- if(!isturf(loc)) //if we're inside something and still got hit
- P.force_hit = TRUE //The thing we're in passed the bullet to us. Pass it back, and tell it to take the damage.
- loc.bullet_act(P)
- return BULLET_ACT_HIT
- if(mind.martial_art.deflection_chance >= 100) //if they can NEVER be hit, lets clue sec in ;)
- visible_message(span_danger("[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!"), span_userdanger("You deflect the projectile!"))
- else
- visible_message(span_danger("[src] deflects the projectile!"), span_userdanger("You deflect the projectile!"))
- playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
- if(!mind.martial_art.reroute_deflection)
- return BULLET_ACT_BLOCK
- else
- P.firer = src
- P.set_angle(rand(0, 360))//SHING
- return BULLET_ACT_FORCE_PIERCE
+ if(mind.martial_art && mind.martial_art.can_use(src)) //Some martial arts users can deflect projectiles!
+ var/martial_art_result = mind.martial_art.on_projectile_hit(src, P, def_zone)
+ if(!(martial_art_result == BULLET_ACT_HIT))
+ return martial_art_result
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
if(P.reflectable & REFLECT_NORMAL)
@@ -232,28 +219,33 @@
var/mob/living/carbon/human/H = user
H.dna.species.spec_attack_hand(H, src)
-/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
- if(check_shields(M, 0, "the [M.name]", UNARMED_ATTACK))
- visible_message(span_danger("[M] attempts to touch [src]!"), \
- span_danger("[M] attempts to touch you!"), span_hear("You hear a swoosh!"), null, M)
- to_chat(M, span_warning("You attempt to touch [src]!"))
+/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/user, list/modifiers)
+ if(check_shields(user, 0, "the [user.name]", UNARMED_ATTACK))
+ visible_message(span_danger("[user] attempts to touch [src]!"), \
+ span_danger("[user] attempts to touch you!"), span_hear("You hear a swoosh!"), null, user)
+ to_chat(user, span_warning("You attempt to touch [src]!"))
return 0
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
- if(M.a_intent == INTENT_HELP)
+
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
+
+ if(user.a_intent == INTENT_HELP)
..() //shaking
return 0
- if(M.a_intent == INTENT_DISARM) //the fact that this fucking works is hilarious to me
- dna.species.disarm(M, src)
+ if(user.a_intent == INTENT_DISARM) //the fact that this fucking works is hilarious to me
+ dna.species.disarm(user, src)
return 1
- if(M.limb_destroyer)
- dismembering_strike(M, affecting.body_zone)
+ if(user.limb_destroyer)
+ dismembering_strike(user, affecting.body_zone)
- if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
+ if(can_inject(user, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3)
if(stat != DEAD)
@@ -336,7 +328,7 @@
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/ex_act(severity, target, origin)
- if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
+ if(TRAIT_BOMBIMMUNE in dna.species.species_traits)
return
..()
if (!severity || QDELETED(src))
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 069ec26960884..a514bf9e75e15 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -237,17 +237,12 @@
. = ..()
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
- if(src.dna.check_mutation(HULK))
- to_chat(src, span_warning("Your meaty finger is much too large for the trigger guard!"))
+ if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS))
+ to_chat(src, "Your meaty finger is much too large for the trigger guard!")
return FALSE
if(HAS_TRAIT(src, TRAIT_NOGUNS))
- to_chat(src, span_warning("Your fingers don't fit in the trigger guard!"))
+ to_chat(src, "You can't bring yourself to use a ranged weapon!")
return FALSE
- if(mind)
- if(mind.martial_art && mind.martial_art.no_guns) //great dishonor to famiry
- to_chat(src, span_warning("Use of ranged weaponry would bring dishonor to the clan."))
- return FALSE
-
return .
/mob/living/carbon/human/proc/get_bank_account()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index cf1b3f57e4779..4378d14f8647d 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1636,7 +1636,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
span_userdanger("You block [user]'s grab!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your grab at [target] was blocked!"))
return FALSE
- if(attacker_style && attacker_style.grab_act(user,target))
+ if(attacker_style?.grab_act(user,target) == MARTIAL_ATTACK_SUCCESS)
return TRUE
else
//Steal them shoes
@@ -1658,7 +1658,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
return TRUE
/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
- if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ if(HAS_TRAIT(user, TRAIT_PACIFISM) && !attacker_style?.pacifist_style)
to_chat(user, span_warning("You don't want to harm [target]!"))
return FALSE
if(target.check_block())
@@ -1666,7 +1666,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
span_userdanger("You block [user]'s attack!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your attack at [target] was blocked!"))
return FALSE
- if(attacker_style && attacker_style.harm_act(user,target))
+ if(attacker_style?.harm_act(user,target) == MARTIAL_ATTACK_SUCCESS)
return TRUE
else
@@ -1732,7 +1732,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
span_danger("You block [user]'s shove!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your shove at [target] was blocked!"))
return FALSE
- if(attacker_style && attacker_style.disarm_act(user,target))
+ if(attacker_style?.disarm_act(user,target) == MARTIAL_ATTACK_SUCCESS)
return TRUE
if(user.resting || user.IsKnockdown())
return FALSE
diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm
index 7191c9bb0aa33..7b14c81f2bf2f 100644
--- a/code/modules/mob/living/carbon/human/species_types/abductors.dm
+++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm
@@ -3,7 +3,12 @@
id = SPECIES_ABDUCTOR
sexes = FALSE
species_traits = list(NOBLOOD,NOEYESPRITES,NOMOUTH)
- inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NOGUNS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
+ inherent_traits = list(
+ TRAIT_VIRUSIMMUNE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_NOHUNGER,
+ TRAIT_NOBREATH
+ )
mutanttongue = /obj/item/organ/tongue/abductor
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 2a25bc7897f02..eaae301e1dd1c 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -3,7 +3,19 @@
name = "\improper Golem"
id = SPECIES_GOLEM_IRON
species_traits = list(NOBLOOD,MUTCOLORS,NO_UNDERWEAR,NOTRANSSTING)
- inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_NONECRODISEASE)
+ inherent_traits = list(
+ TRAIT_RESISTHEAT,
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_NOFIRE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER,
+ TRAIT_NONECRODISEASE
+ )
inherent_biotypes = list(MOB_INORGANIC, MOB_HUMANOID)
mutant_organs = list(/obj/item/organ/adamantine_resonator)
mutanttongue = /obj/item/organ/tongue/golem
@@ -110,7 +122,16 @@
fixed_mut_color = "a3d"
meat = /obj/item/stack/ore/plasma
//Can burn and takes damage from heat
- inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) //no RESISTHEAT, NOFIRE
+ inherent_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER
+ ) //no RESISTHEAT, NOFIRE
info_text = "As a " + span_danger("Plasma Golem") + ", you burn easily. Be careful, if you get hot enough while burning, you'll blow up!"
heatmod = 0 //fine until they blow up
prefix = "Plasma"
@@ -215,7 +236,19 @@
armor = 30
meat = /obj/item/stack/ore/copper
siemens_coeff = 1 //set as conductive, next line sets shock immunity
- inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_SHOCKIMMUNE)
+ inherent_traits = list(
+ TRAIT_RESISTHEAT,
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_NOFIRE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER,
+ TRAIT_SHOCKIMMUNE
+ )
info_text = "As a " + span_danger("Copper Golem") + ", you are faster but less resistant than the average golem. You also act as a conduit for electricity, while not being affected by it."
prefix = "Copper"
special_names = list("Wire")
@@ -320,7 +353,16 @@
fixed_mut_color = "9E704B"
meat = /obj/item/stack/sheet/wood
//Can burn and take damage from heat
- inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
+ inherent_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER
+ )
armor = 30
burnmod = 1.25
heatmod = 1.5
@@ -758,7 +800,16 @@
info_text = "As a " + span_danger("Cloth Golem") + ", you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable. \
Being made of cloth, your body is magic resistant and faster than that of other golems, but weaker and less resilient."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOTRANSSTING) //no mutcolors, and can burn
- inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOGUNS)
+ inherent_traits = list(
+ TRAIT_RESISTCOLD,
+ TRAIT_NOBREATH,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER,
+ TRAIT_CHUNKYFINGERS
+ )
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
armor = 15 //feels no pain, but not too resistant
burnmod = 2 // don't get burned
@@ -1018,7 +1069,16 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/cloth_pile)
special_names = list("Box")
info_text = "As a " + span_danger("Cardboard Golem") + ", you aren't very strong, but you are a bit quicker and can easily create more brethren by using cardboard on yourself."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES,NOFLASH,NOTRANSSTING)
- inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
+ inherent_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER
+ )
attack_verb = "whips"
attack_sound = 'sound/weapons/whip.ogg'
miss_sound = 'sound/weapons/etherealmiss.ogg'
@@ -1067,7 +1127,17 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/cloth_pile)
name = "Leather Golem"
id = SPECIES_GOLEM_LEATHER
special_names = list("Face", "Man", "Belt") //Ah dude 4 strength 4 stam leather belt AHHH
- inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_STRONG_GRABBER)
+ inherent_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER,
+ TRAIT_STRONG_GRABBER
+ )
prefix = "Leather"
fixed_mut_color = "624a2e"
info_text = "As a " + span_danger("Leather Golem") + ", you are flammable, but you can grab things with incredible ease, allowing all your grabs to start at a strong level."
@@ -1081,7 +1151,16 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/cloth_pile)
special_names = list("Boll","Weave")
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES,NOFLASH,NOTRANSSTING)
fixed_mut_color = null
- inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
+ inherent_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER
+ )
info_text = "As a " + span_danger("Durathread Golem") + ", your strikes will cause those your targets to start choking, but your woven body won't withstand fire as well."
species_chest = /obj/item/bodypart/chest/golem/durathread
@@ -1105,7 +1184,19 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/cloth_pile)
mutanttongue = /obj/item/organ/tongue/bone
sexes = FALSE
fixed_mut_color = null
- inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH)
+ inherent_traits = list(
+ TRAIT_RESISTHEAT,
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_NOFIRE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER,
+ TRAIT_FAKEDEATH
+ )
species_language_holder = /datum/language_holder/golem/bone
info_text = "As a " + span_danger("Bone Golem") + ", You have a powerful spell that lets you chill your enemies with fear, and milk heals you! Just make sure to watch our for bone-hurting juice."
var/datum/action/innate/bonechill/bonechill
@@ -1188,7 +1279,16 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/cloth_pile)
prefix = "Snow"
special_names = list("Flake", "Blizzard", "Storm")
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES,NOTRANSSTING) //no mutcolors, no eye sprites
- inherent_traits = list(TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
+ inherent_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_RESISTCOLD,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER
+ )
var/obj/effect/proc_holder/spell/targeted/conjure_item/snowball/ball
var/obj/effect/proc_holder/spell/aimed/cryo/cryo
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index 7b32986dea02a..1589554c80709 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -96,7 +96,7 @@
id = SPECIES_ASHWALKER
examine_limb_id = SPECIES_LIZARD
species_traits = list(MUTCOLORS,EYECOLOR,LIPS, NO_UNDERWEAR)
- inherent_traits = list(TRAIT_NOGUNS)
+ inherent_traits = list(TRAIT_CHUNKYFINGERS)
species_language_holder = /datum/language_holder/lizard/ash
mutantlungs = /obj/item/organ/lungs/ashwalker
digitigrade_customization = DIGITIGRADE_FORCED
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index a89f88441b5f3..778455cbd4046 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -93,7 +93,18 @@
burnmod = 1.5
no_equip = list(ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_SUITSTORE)
species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES,NOFLASH)
- inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
+ inherent_traits = list(
+ TRAIT_RESISTCOLD,
+ TRAIT_NOBREATH,
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_RADIMMUNE,
+ TRAIT_VIRUSIMMUNE,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_NODISMEMBER,
+ TRAIT_NOHUNGER
+ )
mutanteyes = /obj/item/organ/eyes/night_vision/nightmare
mutantheart = /obj/item/organ/heart/nightmare
mutantbrain = /obj/item/organ/brain/nightmare
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 4b383961a5a3b..de3d287d65923 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -258,7 +258,13 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/carbon/monkey)
name = "Teratoma"
id = "teratoma"
species_traits = list(NOTRANSSTING, NO_DNA_COPY, EYECOLOR, HAIR, FACEHAIR, LIPS)
- inherent_traits = list(TRAIT_NOHUNGER, TRAIT_RADIMMUNE, TRAIT_BADDNA, TRAIT_NOGUNS, TRAIT_NONECRODISEASE) //Made of mutated cells
+ inherent_traits = list(
+ TRAIT_NOHUNGER,
+ TRAIT_RADIMMUNE,
+ TRAIT_BADDNA,
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_NONECRODISEASE
+ ) //Made of mutated cells
use_skintones = FALSE
skinned_type = /obj/item/stack/sheet/animalhide/monkey
changesource_flags = MIRROR_BADMIN
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 3bc43dc883409..e463938d51941 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -640,8 +640,43 @@
update_stat()
med_hud_set_health()
med_hud_set_status()
+ update_health_hud()
SEND_SIGNAL(src, COMSIG_LIVING_UPDATE_HEALTH)
+/mob/living/update_health_hud()
+ var/severity = 0
+ var/healthpercent = (health/maxHealth) * 100
+ if(hud_used?.healthdoll) //to really put you in the boots of a simplemob
+ var/atom/movable/screen/healthdoll/living/livingdoll = hud_used.healthdoll
+ switch(healthpercent)
+ if(100 to INFINITY)
+ severity = 0
+ if(80 to 100)
+ severity = 1
+ if(60 to 80)
+ severity = 2
+ if(40 to 60)
+ severity = 3
+ if(20 to 40)
+ severity = 4
+ if(1 to 20)
+ severity = 5
+ else
+ severity = 6
+ livingdoll.icon_state = "living[severity]"
+ if(!livingdoll.filtered)
+ livingdoll.filtered = TRUE
+ var/icon/mob_mask = icon(icon, icon_state)
+ if(mob_mask.Height() > world.icon_size || mob_mask.Width() > world.icon_size)
+ var/health_doll_icon_state = health_doll_icon ? health_doll_icon : "megasprite"
+ mob_mask = icon('icons/hud/screen_gen.dmi', health_doll_icon_state) //swap to something generic if they have no special doll
+ livingdoll.add_filter("mob_shape_mask", 1, alpha_mask_filter(icon = mob_mask))
+ livingdoll.add_filter("inset_drop_shadow", 2, drop_shadow_filter(size = -1))
+ if(severity > 0)
+ overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
+ else
+ clear_fullscreen("brute")
+
//proc used to ressuscitate a mob
/mob/living/proc/revive(full_heal = FALSE, admin_revive = FALSE)
SEND_SIGNAL(src, COMSIG_LIVING_REVIVE, src, full_heal, admin_revive)
@@ -1713,3 +1748,34 @@
/mob/living/proc/on_handsblocked_end()
REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED)
REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED)
+
+/// Returns the attack damage type of a living mob such as [BRUTE].
+/mob/living/proc/get_attack_type()
+ return BRUTE
+
+
+/**
+ * Apply a martial art move from src to target.
+ *
+ * This is used to process martial art attacks against nonhumans.
+ * It is also used to process martial art attacks by nonhumans, even against humans
+ * Human vs human attacks are handled in species code right now.
+ */
+/mob/living/proc/apply_martial_art(mob/living/target, modifiers)
+ if(HAS_TRAIT(target, TRAIT_MARTIAL_ARTS_IMMUNE))
+ return MARTIAL_ATTACK_INVALID
+ var/datum/martial_art/style = mind?.martial_art
+ if (!style)
+ return MARTIAL_ATTACK_INVALID
+ // will return boolean below since it's not invalid
+ switch (a_intent)
+ if (INTENT_GRAB)
+ return style.grab_act(src, target)
+ if (INTENT_HARM)
+ if (HAS_TRAIT(src, TRAIT_PACIFISM))
+ return FALSE
+ return style.harm_act(src, target)
+ if (INTENT_DISARM)
+ return style.disarm_act(src, target)
+ if (INTENT_HELP)
+ return style.help_act(src, target)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index bb39743aa1bd3..45fece17a2761 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -273,27 +273,44 @@
log_combat(M, src, "attacked")
return TRUE
+/mob/living/attack_hand(mob/living/carbon/human/user, list/modifiers)
+ . = ..()
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
-/mob/living/attack_paw(mob/living/carbon/monkey/M)
+/mob/living/attack_paw(mob/living/carbon/monkey/user, list/modifiers)
if(isturf(loc) && istype(loc.loc, /area/start))
- to_chat(M, "No attacking people at spawn, you jackass.")
+ to_chat(user, "No attacking people at spawn, you jackass.")
return FALSE
- if (M.a_intent == INTENT_HARM)
- if(HAS_TRAIT(M, TRAIT_PACIFISM))
- to_chat(M, span_notice("You don't want to hurt anyone!"))
- return FALSE
+ var/martial_result = user.apply_martial_art(src, modifiers)
+ if (martial_result != MARTIAL_ATTACK_INVALID)
+ return martial_result
- if(M.is_muzzled() || M.is_mouth_covered(FALSE, TRUE))
- to_chat(M, span_warning("You can't bite with your mouth covered!"))
+ switch (user.a_intent)
+ if (INTENT_HARM)
+ if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ to_chat(user, "You don't want to hurt anyone!")
+ return FALSE
+
+ if(user.is_muzzled() || user.is_mouth_covered(FALSE, TRUE))
+ to_chat(user, "You can't bite with your mouth covered!")
+ return FALSE
+ user.do_attack_animation(src, ATTACK_EFFECT_BITE)
+ log_combat(user, src, "attacked")
+ playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
+ visible_message("[user.name] bites [src]!", \
+ "[user.name] bites you!", "You hear a chomp!", COMBAT_MESSAGE_RANGE, user)
+ to_chat(user, "You bite [src]!")
+ return TRUE
+ if (INTENT_GRAB)
+ grabbedby(user)
return FALSE
- M.do_attack_animation(src, ATTACK_EFFECT_BITE)
- log_combat(M, src, "attacked")
- playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
- visible_message(span_danger("[M.name] bites [src]!"), \
- span_userdanger("[M.name] bites you!"), span_hear("You hear a chomp!"), COMBAT_MESSAGE_RANGE, M)
- to_chat(M, span_danger("You bite [src]!"))
- return TRUE
+ if (INTENT_DISARM)
+ if (user != src)
+ user.disarm(src)
+ return TRUE
return FALSE
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index c7b849c0c4b69..98ed5a506bb9f 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -6,6 +6,7 @@
pressure_resistance = 10
chat_color = "#CCCCCC" //The say color of the mob, for when ID say isn't available (simplemobs that are not /mob/living/carbon/human)
+ hud_type = /datum/hud/living
var/resize = 1 //Badminnery resize
var/lastattacker = null
@@ -91,6 +92,8 @@
var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob.
var/bubble_icon = "default" //what icon the mob uses for speechbubbles
+ ///if this exists AND the normal sprite is bigger than 32x32, this is the replacement icon state (because health doll size limitations). the icon will always be screen_gen.dmi
+ var/health_doll_icon
var/last_bumped = 0
var/unique_name = 0 //if a mob's name should be appended with an id when created e.g. Mob (666)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 62fdbaaf3c4eb..dc2560425b34a 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -68,6 +68,7 @@
diag_hud_set_health()
create_access_card(default_access_list)
default_access_list = null
+ ADD_TRAIT(src, TRAIT_MARTIAL_ARTS_IMMUNE, ROUNDSTART_TRAIT)
/mob/living/silicon/Destroy()
QDEL_NULL(radio)
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index 2f973fc39852a..cea1a292eac26 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -1,7 +1,9 @@
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
- ..()
+ // so that martial arts don't double dip
+ if (..())
+ return TRUE
switch(M.a_intent)
if("help")
if (health > 0)
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 42e63aa5eaa3a..234bcd1b616e6 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -36,7 +36,6 @@
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
deathmessage = "collapses in a shattered heap."
- hud_type = /datum/hud/constructs
hardattacks = TRUE
var/list/construct_spells = list()
var/playstyle_string = span_bigbold("You are a generic construct!") + " Your job is to not exist, and you should probably adminhelp this."
@@ -128,11 +127,6 @@
/mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
return 0
-/mob/living/simple_animal/hostile/construct/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
- . = ..()
- if(updating_health)
- update_health_hud()
-
/////////////////Juggernaut///////////////
/mob/living/simple_animal/hostile/construct/juggernaut
name = "Juggernaut"
@@ -531,21 +525,3 @@
desc = "Activate to track Nar'Sie!"
button_icon_state = "sintouch"
the_construct.seeking = TRUE
-
-
-/////////////////////////////ui stuff/////////////////////////////
-
-/mob/living/simple_animal/hostile/construct/update_health_hud()
- if(hud_used)
- if(health >= maxHealth)
- hud_used.healths.icon_state = "[icon_state]_health0"
- else if(health > maxHealth*0.8)
- hud_used.healths.icon_state = "[icon_state]_health2"
- else if(health > maxHealth*0.6)
- hud_used.healths.icon_state = "[icon_state]_health3"
- else if(health > maxHealth*0.4)
- hud_used.healths.icon_state = "[icon_state]_health4"
- else if(health > maxHealth*0.2)
- hud_used.healths.icon_state = "[icon_state]_health5"
- else
- hud_used.healths.icon_state = "[icon_state]_health6"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index e5f19e5daa38c..11274c170d4f9 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -176,7 +176,7 @@ Difficulty: Very Hard
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.mind)
- if(H.mind.martial_art && prob(H.mind.martial_art.deflection_chance))
+ if(istype(H.mind.martial_art, /datum/martial_art/the_sleeping_carp))
. = TRUE
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index dadbc5835d15a..71c9bf4c4fd3d 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -52,6 +52,7 @@
if(gps_name && true_spawn)
AddComponent(/datum/component/gps, gps_name)
ADD_TRAIT(src, TRAIT_NO_TELEPORT, MEGAFAUNA_TRAIT)
+ ADD_TRAIT(src, TRAIT_MARTIAL_ARTS_IMMUNE, MEGAFAUNA_TRAIT)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index acddf727e9b7f..cb096d9a79de1 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -18,7 +18,6 @@
stat_attack = HARD_CRIT
layer = LARGE_MOB_LAYER
sentience_type = SENTIENCE_BOSS
- hud_type = /datum/hud/lavaland_elite
var/chosen_attack = 1
var/list/attack_action_types = list()
var/can_talk = FALSE
@@ -82,33 +81,6 @@ While using this makes the system rely on OnFire, it still gives options for tim
elite_owner.chosen_attack = chosen_attack_num
to_chat(elite_owner, chosen_message)
-/mob/living/simple_animal/hostile/asteroid/elite/update_health_hud()
- if(hud_used)
- var/severity = 0
- var/healthpercent = (health/maxHealth) * 100
- switch(healthpercent)
- if(100 to INFINITY)
- hud_used.healths.icon_state = "elite_health0"
- if(80 to 100)
- severity = 1
- if(60 to 80)
- severity = 2
- if(40 to 60)
- severity = 3
- if(20 to 40)
- severity = 4
- if(10 to 20)
- severity = 5
- if(1 to 20)
- severity = 6
- else
- severity = 7
- hud_used.healths.icon_state = "elite_health[severity]"
- if(severity > 0)
- overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
- else
- clear_fullscreen("brute")
-
//The Pulsing Tumor, the actual "spawn-point" of elites, handles the spawning, arena, and procs for dealing with basic scenarios.
/obj/structure/elite_tumor
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 2eb087aa46f87..9c24e2b3a0f0e 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -191,16 +191,6 @@
/mob/living/simple_animal/updatehealth()
. = ..()
health = clamp(health, 0, maxHealth)
- update_health_hud()
-
-/mob/living/simple_animal/update_health_hud()
- if(!hud_used)
- return
- var/severity = 5 - clamp(FLOOR((health / maxHealth) * 5, 1), 0, 5)
- if(severity > 0)
- overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
- else
- clear_fullscreen("brute")
/mob/living/simple_animal/update_stat()
if(status_flags & GODMODE)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 6855314a38879..abf7ce49e01e8 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -45,7 +45,6 @@
footstep_type = FOOTSTEP_MOB_SLIME
- hud_type = /datum/hud/slime
hardattacks = TRUE //A sharp blade wont cut a slime from a mere parry
discovery_points = 1000
@@ -179,36 +178,6 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/simple_animal/slime)
mod += 2
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/slime_healthmod, multiplicative_slowdown = mod)
-/mob/living/simple_animal/slime/update_health_hud()
- if(hud_used)
- var/severity = 0
- var/healthpercent = (health/maxHealth) * 100
- switch(healthpercent)
- if(100 to INFINITY)
- hud_used.healths.icon_state = "slime_health0"
- if(80 to 100)
- hud_used.healths.icon_state = "slime_health1"
- severity = 1
- if(60 to 80)
- hud_used.healths.icon_state = "slime_health2"
- severity = 2
- if(40 to 60)
- hud_used.healths.icon_state = "slime_health3"
- severity = 3
- if(20 to 40)
- hud_used.healths.icon_state = "slime_health4"
- severity = 4
- if(1 to 20)
- hud_used.healths.icon_state = "slime_health5"
- severity = 5
- else
- hud_used.healths.icon_state = "slime_health7"
- severity = 6
- if(severity > 0)
- overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
- else
- clear_fullscreen("brute")
-
/mob/living/simple_animal/slime/adjust_bodytemperature()
. = ..()
var/mod = 0
diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi
index af297187cac97..6489055798643 100644
Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ
diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi
index 1e34ba1144290..68afde5159219 100644
Binary files a/icons/hud/screen_gen.dmi and b/icons/hud/screen_gen.dmi differ
diff --git a/icons/ui/screen_gen.dmi b/icons/ui/screen_gen.dmi
deleted file mode 100644
index a94f53eb96274..0000000000000
Binary files a/icons/ui/screen_gen.dmi and /dev/null differ