diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 284b0e4d745..608fcfcce20 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -187,6 +187,7 @@
#define isswarmer(A) (istype((A), /mob/living/simple_animal/hostile/swarmer))
#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian))
#define isnymph(A) (istype((A), /mob/living/simple_animal/diona))
+#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
#define issilicon(A) (istype((A), /mob/living/silicon))
#define isAI(A) (istype((A), /mob/living/silicon/ai))
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index e5d5bb723c1..f451a34a8b7 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -26,7 +26,7 @@
//#define STATUS_EFFECT_WISH_GRANTERS_GIFT /datum/status_effect/wish_granters_gift //If you're currently resurrecting with the Wish Granter
-//#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
+#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
/////////////
// DEBUFFS //
@@ -52,7 +52,7 @@
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
-//#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
+#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
#define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage
@@ -74,6 +74,6 @@
//#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
-//#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
+#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
-//#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
\ No newline at end of file
+#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
\ No newline at end of file
diff --git a/code/datums/components/paintable.dm b/code/datums/components/paintable.dm
new file mode 100644
index 00000000000..ef9a2923cc6
--- /dev/null
+++ b/code/datums/components/paintable.dm
@@ -0,0 +1,31 @@
+/datum/component/spraycan_paintable
+ var/current_paint
+
+/datum/component/spraycan_paintable/Initialize()
+ RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/Repaint)
+
+/datum/component/spraycan_paintable/Destroy()
+ RemoveCurrentCoat()
+ return ..()
+
+/datum/component/spraycan_paintable/proc/RemoveCurrentCoat()
+ var/atom/A = parent
+ A.remove_atom_colour(FIXED_COLOUR_PRIORITY, current_paint)
+
+/datum/component/spraycan_paintable/proc/Repaint(datum/source, obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
+ if(!istype(spraycan) || user.a_intent == INTENT_HARM)
+ return
+ . = COMPONENT_NO_AFTERATTACK
+ if(spraycan.capped)
+ to_chat(user, "Take the cap off first!")
+ return
+ if(spraycan.uses < 2)
+ to_chat(user, "There is not enough paint in the can!")
+ return
+ RemoveCurrentCoat()
+ var/colour = spraycan.colour
+ current_paint = colour
+ var/atom/A = parent
+ A.add_atom_colour(colour, FIXED_COLOUR_PRIORITY)
+ playsound(spraycan, 'sound/effects/spray.ogg', 5, 1, 5)
+ to_chat(user, "You spray [spraycan] on [A], painting it.")
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 387cc70f992..fb336192b38 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -40,6 +40,132 @@
playsound(owner, 'sound/weapons/bite.ogg', 50, 1)
owner.adjustBruteLoss(3)
+/datum/status_effect/blooddrunk
+ id = "blooddrunk"
+ duration = 10
+ tick_interval = 0
+ alert_type = /obj/screen/alert/status_effect/blooddrunk
+ var/last_health = 0
+ var/last_bruteloss = 0
+ var/last_fireloss = 0
+ var/last_toxloss = 0
+ var/last_oxyloss = 0
+ var/last_cloneloss = 0
+ var/last_staminaloss = 0
+
+/obj/screen/alert/status_effect/blooddrunk
+ name = "Blood-Drunk"
+ desc = "You are drunk on blood! Your pulse thunders in your ears! Nothing can harm you!" //not true, and the item description mentions its actual effect
+ icon_state = "blooddrunk"
+
+/datum/status_effect/blooddrunk/on_apply()
+ . = ..()
+ if(.)
+ owner.maxHealth *= 10
+ owner.bruteloss *= 10
+ owner.fireloss *= 10
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ for(var/X in H.bodyparts)
+ var/obj/item/organ/external/BP = X
+ BP.max_damage *= 10
+ BP.min_broken_damage *= 10
+ BP.brute_dam *= 10
+ BP.burn_dam *= 10
+ owner.toxloss *= 10
+ owner.oxyloss *= 10
+ owner.cloneloss *= 10
+ owner.staminaloss *= 10
+ owner.updatehealth()
+ last_health = owner.health
+ last_bruteloss = owner.getBruteLoss()
+ last_fireloss = owner.getFireLoss()
+ last_toxloss = owner.getToxLoss()
+ last_oxyloss = owner.getOxyLoss()
+ last_cloneloss = owner.getCloneLoss()
+ last_staminaloss = owner.getStaminaLoss()
+ add_attack_logs(owner, owner, "gained blood-drunk stun immunity")
+ var/status = CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
+ owner.status_flags &= ~status
+ owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
+
+/datum/status_effect/blooddrunk/tick() //multiply the effect of healing by 10
+ if(owner.health > last_health)
+ var/needs_health_update = FALSE
+ var/new_bruteloss = owner.getBruteLoss()
+ if(new_bruteloss < last_bruteloss)
+ var/heal_amount = (new_bruteloss - last_bruteloss) * 10
+ owner.adjustBruteLoss(heal_amount, updating_health = FALSE)
+ new_bruteloss = owner.getBruteLoss()
+ needs_health_update = TRUE
+ last_bruteloss = new_bruteloss
+
+ var/new_fireloss = owner.getFireLoss()
+ if(new_fireloss < last_fireloss)
+ var/heal_amount = (new_fireloss - last_fireloss) * 10
+ owner.adjustFireLoss(heal_amount, updating_health = FALSE)
+ new_fireloss = owner.getFireLoss()
+ needs_health_update = TRUE
+ last_fireloss = new_fireloss
+
+ var/new_toxloss = owner.getToxLoss()
+ if(new_toxloss < last_toxloss)
+ var/heal_amount = (new_toxloss - last_toxloss) * 10
+ owner.adjustToxLoss(heal_amount, updating_health = FALSE)
+ new_toxloss = owner.getToxLoss()
+ needs_health_update = TRUE
+ last_toxloss = new_toxloss
+
+ var/new_oxyloss = owner.getOxyLoss()
+ if(new_oxyloss < last_oxyloss)
+ var/heal_amount = (new_oxyloss - last_oxyloss) * 10
+ owner.adjustOxyLoss(heal_amount, updating_health = FALSE)
+ new_oxyloss = owner.getOxyLoss()
+ needs_health_update = TRUE
+ last_oxyloss = new_oxyloss
+
+ var/new_cloneloss = owner.getCloneLoss()
+ if(new_cloneloss < last_cloneloss)
+ var/heal_amount = (new_cloneloss - last_cloneloss) * 10
+ owner.adjustCloneLoss(heal_amount, updating_health = FALSE)
+ new_cloneloss = owner.getCloneLoss()
+ needs_health_update = TRUE
+ last_cloneloss = new_cloneloss
+
+ var/new_staminaloss = owner.getStaminaLoss()
+ if(new_staminaloss < last_staminaloss)
+ var/heal_amount = (new_staminaloss - last_staminaloss) * 10
+ owner.adjustStaminaLoss(heal_amount, updating_health = FALSE)
+ new_staminaloss = owner.getStaminaLoss()
+ needs_health_update = TRUE
+ last_staminaloss = new_staminaloss
+
+ if(needs_health_update)
+ owner.updatehealth()
+ owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
+ last_health = owner.health
+
+/datum/status_effect/blooddrunk/on_remove()
+ tick()
+ owner.maxHealth *= 0.1
+ owner.bruteloss *= 0.1
+ owner.fireloss *= 0.1
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ for(var/X in H.bodyparts)
+ var/obj/item/organ/external/BP = X
+ BP.brute_dam *= 0.1
+ BP.burn_dam *= 0.1
+ BP.max_damage /= 10
+ BP.min_broken_damage /= 10
+ owner.toxloss *= 0.1
+ owner.oxyloss *= 0.1
+ owner.cloneloss *= 0.1
+ owner.staminaloss *= 0.1
+ owner.updatehealth()
+ add_attack_logs(owner, owner, "lost blood-drunk stun immunity")
+ owner.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
+
/datum/status_effect/exercised
id = "Exercised"
duration = 1200
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 6e809b32606..3ce68f85250 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -9,6 +9,39 @@
if(owner.reagents)
owner.reagents.del_reagent("holywater") //can't be deconverted
+/datum/status_effect/crusher_mark
+ id = "crusher_mark"
+ duration = 300 //if you leave for 30 seconds you lose the mark, deal with it
+ status_type = STATUS_EFFECT_REPLACE
+ alert_type = null
+ var/mutable_appearance/marked_underlay
+ var/obj/item/twohanded/kinetic_crusher/hammer_synced
+
+/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/kinetic_crusher/new_hammer_synced)
+ . = ..()
+ if(.)
+ hammer_synced = new_hammer_synced
+
+/datum/status_effect/crusher_mark/on_apply()
+ if(owner.mob_size >= MOB_SIZE_LARGE)
+ marked_underlay = mutable_appearance('icons/effects/effects.dmi', "shield2")
+ marked_underlay.pixel_x = -owner.pixel_x
+ marked_underlay.pixel_y = -owner.pixel_y
+ owner.underlays += marked_underlay
+ return TRUE
+ return FALSE
+
+/datum/status_effect/crusher_mark/Destroy()
+ hammer_synced = null
+ if(owner)
+ owner.underlays -= marked_underlay
+ QDEL_NULL(marked_underlay)
+ return ..()
+
+/datum/status_effect/crusher_mark/be_replaced()
+ owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point.
+ ..()
+
/datum/status_effect/saw_bleed
id = "saw_bleed"
duration = -1 //removed under specific conditions
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index eaa14c4d0b0..8f5023e4a74 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -1,5 +1,43 @@
//entirely neutral or internal status effects go here
+/datum/status_effect/crusher_damage //tracks the damage dealt to this mob by kinetic crushers
+ id = "crusher_damage"
+ duration = -1
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = null
+ var/total_damage = 0
+
+/datum/status_effect/syphon_mark
+ id = "syphon_mark"
+ duration = 50
+ status_type = STATUS_EFFECT_MULTIPLE
+ alert_type = null
+ on_remove_on_mob_delete = TRUE
+ var/obj/item/borg/upgrade/modkit/bounty/reward_target
+
+/datum/status_effect/syphon_mark/on_creation(mob/living/new_owner, obj/item/borg/upgrade/modkit/bounty/new_reward_target)
+ . = ..()
+ if(.)
+ reward_target = new_reward_target
+
+/datum/status_effect/syphon_mark/on_apply()
+ if(owner.stat == DEAD)
+ return FALSE
+ return ..()
+
+/datum/status_effect/syphon_mark/proc/get_kill()
+ if(!QDELETED(reward_target))
+ reward_target.get_kill(owner)
+
+/datum/status_effect/syphon_mark/tick()
+ if(owner.stat == DEAD)
+ get_kill()
+ qdel(src)
+
+/datum/status_effect/syphon_mark/on_remove()
+ get_kill()
+ . = ..()
+
/datum/status_effect/high_five
id = "high_five"
duration = 40
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index d349d0b1cd7..7f1683ba415 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -140,6 +140,20 @@
..()
animate(src, alpha = 0, time = duration)
+/obj/effect/temp_visual/fire
+ icon = 'icons/goonstation/effects/fire.dmi'
+ icon_state = "3"
+ light_range = LIGHT_RANGE_FIRE
+ light_color = LIGHT_COLOR_FIRE
+ duration = 10
+ layer = MASSIVE_OBJ_LAYER
+ alpha = 250
+ blend_mode = BLEND_ADD
+
+/obj/effect/temp_visual/fire/New(loc)
+ color = heat2color(FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
+ ..()
+
/obj/effect/temp_visual/revenant
name = "spooky lights"
icon_state = "purplesparkles"
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
new file mode 100644
index 00000000000..47b3fb01501
--- /dev/null
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -0,0 +1,439 @@
+/*********************Mining Hammer****************/
+/obj/item/twohanded/kinetic_crusher
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "crusher"
+ item_state = "crusher0"
+ name = "proto-kinetic crusher"
+ desc = "An early design of the proto-kinetic accelerator, it is little more than a combination of various mining tools cobbled together, forming a high-tech club. \
+ While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna."
+ force = 0 //You can't hit stuff unless wielded
+ w_class = WEIGHT_CLASS_BULKY
+ slot_flags = SLOT_BACK
+ force_unwielded = 0
+ force_wielded = 20
+ throwforce = 5
+ throw_speed = 4
+ armour_penetration = 10
+ materials = list(MAT_METAL = 1150, MAT_GLASS = 2075)
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped")
+ sharp = TRUE
+ actions_types = list(/datum/action/item_action/toggle_light)
+ var/list/trophies = list()
+ var/charged = TRUE
+ var/charge_time = 15
+ var/detonation_damage = 50
+ var/backstab_bonus = 30
+ var/light_on = FALSE
+ var/brightness_on = 5
+
+/obj/item/twohanded/kinetic_crusher/Destroy()
+ QDEL_LIST(trophies)
+ return ..()
+
+/obj/item/twohanded/kinetic_crusher/examine(mob/living/user)
+ ..()
+ to_chat(user, "Mark a large creature with the destabilizing force, then hit them in melee to do [force + detonation_damage] damage.")
+ to_chat(user, "Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage].")
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ to_chat(user, "It has \a [T] attached, which causes [T.effect_desc()].")
+
+/obj/item/twohanded/kinetic_crusher/attackby(obj/item/I, mob/living/user)
+ if(iscrowbar(I))
+ if(LAZYLEN(trophies))
+ to_chat(user, "You remove [src]'s trophies.")
+ playsound(loc, I.usesound, 100, 1)
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.remove_from(src, user)
+ else
+ to_chat(user, "There are no trophies on [src].")
+ else if(istype(I, /obj/item/crusher_trophy))
+ var/obj/item/crusher_trophy/T = I
+ T.add_to(src, user)
+ else
+ return ..()
+
+/obj/item/twohanded/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user)
+ if(!wielded)
+ to_chat(user, "[src] is too heavy to use with one hand. You fumble and drop everything.")
+ user.drop_r_hand()
+ user.drop_l_hand()
+ return
+ var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ var/target_health = target.health
+ ..()
+ for(var/t in trophies)
+ if(!QDELETED(target))
+ var/obj/item/crusher_trophy/T = t
+ T.on_melee_hit(target, user)
+ if(!QDELETED(C) && !QDELETED(target))
+ C.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did
+
+/obj/item/twohanded/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams)
+ . = ..()
+ if(!wielded)
+ return
+ if(!proximity_flag && charged)//Mark a target, or mine a tile.
+ var/turf/proj_turf = user.loc
+ if(!isturf(proj_turf))
+ return
+ var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(proj_turf)
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_projectile_fire(D, user)
+ D.preparePixelProjectile(target, get_turf(target), user, clickparams)
+ D.firer = user
+ D.hammer_synced = src
+ playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
+ D.fire()
+ charged = FALSE
+ update_icon()
+ addtimer(CALLBACK(src, .proc/Recharge), charge_time)
+ return
+ if(proximity_flag && isliving(target))
+ var/mob/living/L = target
+ var/datum/status_effect/crusher_mark/CM = L.has_status_effect(STATUS_EFFECT_CRUSHERMARK)
+ if(!CM || CM.hammer_synced != src || !L.remove_status_effect(STATUS_EFFECT_CRUSHERMARK))
+ return
+ var/datum/status_effect/crusher_damage/C = L.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ var/target_health = L.health
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_mark_detonation(target, user)
+ if(!QDELETED(L))
+ if(!QDELETED(C))
+ C.total_damage += target_health - L.health //we did some damage, but let's not assume how much we did
+ new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
+ var/backstab_dir = get_dir(user, L)
+ var/def_check = L.getarmor(type = "bomb")
+ if((user.dir & backstab_dir) && (L.dir & backstab_dir))
+ if(!QDELETED(C))
+ C.total_damage += detonation_damage + backstab_bonus //cheat a little and add the total before killing it, so certain mobs don't have much lower chances of giving an item
+ L.apply_damage(detonation_damage + backstab_bonus, BRUTE, blocked = def_check)
+ playsound(user, 'sound/weapons/kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
+ else
+ if(!QDELETED(C))
+ C.total_damage += detonation_damage
+ L.apply_damage(detonation_damage, BRUTE, blocked = def_check)
+
+/obj/item/twohanded/kinetic_crusher/proc/Recharge()
+ if(!charged)
+ charged = TRUE
+ update_icon()
+ playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
+
+/obj/item/twohanded/kinetic_crusher/ui_action_click(mob/user, actiontype)
+ light_on = !light_on
+ playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
+ update_brightness(user)
+ update_icon()
+
+/obj/item/twohanded/kinetic_crusher/proc/update_brightness(mob/user = null)
+ if(light_on)
+ set_light(brightness_on)
+ else
+ set_light(0)
+
+/obj/item/twohanded/kinetic_crusher/update_icon()
+ ..()
+ cut_overlays()
+ if(!charged)
+ add_overlay("[icon_state]_uncharged")
+ if(light_on)
+ add_overlay("[icon_state]_lit")
+ spawn(1)
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+ item_state = "crusher[wielded]"
+
+//destablizing force
+/obj/item/projectile/destabilizer
+ name = "destabilizing force"
+ icon_state = "pulse1"
+ nodamage = TRUE
+ damage = 0 //We're just here to mark people. This is still a melee weapon.
+ damage_type = BRUTE
+ flag = "bomb"
+ range = 6
+ log_override = TRUE
+ var/obj/item/twohanded/kinetic_crusher/hammer_synced
+
+/obj/item/projectile/destabilizer/Destroy()
+ hammer_synced = null
+ return ..()
+
+/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = FALSE)
+ if(isliving(target))
+ var/mob/living/L = target
+ var/had_effect = (L.has_status_effect(STATUS_EFFECT_CRUSHERMARK)) //used as a boolean
+ var/datum/status_effect/crusher_mark/CM = L.apply_status_effect(STATUS_EFFECT_CRUSHERMARK, hammer_synced)
+ if(hammer_synced)
+ for(var/t in hammer_synced.trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_mark_application(target, CM, had_effect)
+ var/target_turf = get_turf(target)
+ if(ismineralturf(target_turf))
+ var/turf/simulated/mineral/M = target_turf
+ new /obj/effect/temp_visual/kinetic_blast(M)
+ M.gets_drilled(firer)
+ ..()
+
+//trophies
+/obj/item/crusher_trophy
+ name = "tail spike"
+ desc = "A strange spike with no usage."
+ icon = 'icons/obj/lavaland/artefacts.dmi'
+ icon_state = "tail_spike"
+ var/bonus_value = 10 //if it has a bonus effect, this is how much that effect is
+ var/denied_type = /obj/item/crusher_trophy
+
+/obj/item/crusher_trophy/examine(mob/living/user)
+ ..()
+ to_chat(user, "Causes [effect_desc()] when attached to a kinetic crusher.")
+
+/obj/item/crusher_trophy/proc/effect_desc()
+ return "errors"
+
+/obj/item/crusher_trophy/attackby(obj/item/A, mob/living/user)
+ if(istype(A, /obj/item/twohanded/kinetic_crusher))
+ add_to(A, user)
+ else
+ ..()
+
+/obj/item/crusher_trophy/proc/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ for(var/t in H.trophies)
+ var/obj/item/crusher_trophy/T = t
+ if(istype(T, denied_type) || istype(src, T.denied_type))
+ to_chat(user, "You can't seem to attach [src] to [H]. Maybe remove a few trophies?")
+ return FALSE
+ if(!user.drop_item())
+ return
+ forceMove(H)
+ H.trophies += src
+ to_chat(user, "You attach [src] to [H].")
+ return TRUE
+
+/obj/item/crusher_trophy/proc/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ forceMove(get_turf(H))
+ H.trophies -= src
+ return TRUE
+
+/obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user
+
+/obj/item/crusher_trophy/proc/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user) //the projectile fired and the user
+
+/obj/item/crusher_trophy/proc/on_mark_application(mob/living/target, datum/status_effect/crusher_mark/mark, had_mark) //the target, the mark applied, and if the target had a mark before
+
+/obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user
+
+//goliath
+/obj/item/crusher_trophy/goliath_tentacle
+ name = "goliath tentacle"
+ desc = "A sliced-off goliath tentacle. Suitable as a trophy for a kinetic crusher."
+ icon_state = "goliath_tentacle"
+ denied_type = /obj/item/crusher_trophy/goliath_tentacle
+ bonus_value = 2
+ var/missing_health_ratio = 0.1
+ var/missing_health_desc = 10
+
+/obj/item/crusher_trophy/goliath_tentacle/effect_desc()
+ return "mark detonation to do [bonus_value] more damage for every [missing_health_desc] health you are missing"
+
+/obj/item/crusher_trophy/goliath_tentacle/on_mark_detonation(mob/living/target, mob/living/user)
+ var/missing_health = user.health - user.maxHealth
+ missing_health *= missing_health_ratio //bonus is active at all times, even if you're above 90 health
+ missing_health *= bonus_value //multiply the remaining amount by bonus_value
+ if(missing_health > 0)
+ target.adjustBruteLoss(missing_health) //and do that much damage
+
+//watcher
+/obj/item/crusher_trophy/watcher_wing
+ name = "watcher wing"
+ desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "watcher_wing"
+ denied_type = /obj/item/crusher_trophy/watcher_wing
+ bonus_value = 5
+
+/obj/item/crusher_trophy/watcher_wing/effect_desc()
+ return "mark detonation to prevent certain creatures from using certain attacks for [bonus_value*0.1] second\s"
+
+/obj/item/crusher_trophy/watcher_wing/on_mark_detonation(mob/living/target, mob/living/user)
+ if(ishostile(target))
+ var/mob/living/simple_animal/hostile/H = target
+ if(H.ranged) //briefly delay ranged attacks
+ if(H.ranged_cooldown >= world.time)
+ H.ranged_cooldown += bonus_value
+ else
+ H.ranged_cooldown = bonus_value + world.time
+
+//magmawing watcher
+/obj/item/crusher_trophy/blaster_tubes/magma_wing
+ name = "magmawing watcher wing"
+ desc = "A still-searing wing from a magmawing watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "magma_wing"
+ gender = NEUTER
+ bonus_value = 5
+
+/obj/item/crusher_trophy/blaster_tubes/magma_wing/effect_desc()
+ return "mark detonation to make the next destabilizer shot deal [bonus_value] damage"
+
+/obj/item/crusher_trophy/blaster_tubes/magma_wing/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user)
+ if(deadly_shot)
+ marker.name = "heated [marker.name]"
+ marker.icon_state = "lava"
+ marker.damage = bonus_value
+ marker.nodamage = FALSE
+ deadly_shot = FALSE
+
+//icewing watcher
+/obj/item/crusher_trophy/watcher_wing/ice_wing
+ name = "icewing watcher wing"
+ desc = "A carefully preserved frozen wing from an icewing watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "ice_wing"
+ bonus_value = 8
+
+//legion
+/obj/item/crusher_trophy/legion_skull
+ name = "legion skull"
+ desc = "A dead and lifeless legion skull. Suitable as a trophy for a kinetic crusher."
+ icon_state = "legion_skull"
+ denied_type = /obj/item/crusher_trophy/legion_skull
+ bonus_value = 3
+
+/obj/item/crusher_trophy/legion_skull/effect_desc()
+ return "a kinetic crusher to recharge [bonus_value*0.1] second\s faster"
+
+/obj/item/crusher_trophy/legion_skull/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.charge_time -= bonus_value
+
+/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.charge_time += bonus_value
+
+//blood-drunk hunter
+/obj/item/crusher_trophy/miner_eye
+ name = "eye of a blood-drunk hunter"
+ desc = "Its pupil is collapsed and turned to mush. Suitable as a trophy for a kinetic crusher."
+ icon_state = "hunter_eye"
+ denied_type = /obj/item/crusher_trophy/miner_eye
+
+/obj/item/crusher_trophy/miner_eye/effect_desc()
+ return "mark detonation to grant stun immunity and 90% damage reduction for 1 second"
+
+/obj/item/crusher_trophy/miner_eye/on_mark_detonation(mob/living/target, mob/living/user)
+ user.apply_status_effect(STATUS_EFFECT_BLOODDRUNK)
+
+//ash drake
+/obj/item/crusher_trophy/tail_spike
+ desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher."
+ denied_type = /obj/item/crusher_trophy/tail_spike
+ bonus_value = 5
+
+/obj/item/crusher_trophy/tail_spike/effect_desc()
+ return "mark detonation to do [bonus_value] damage to nearby creatures and push them back"
+
+/obj/item/crusher_trophy/tail_spike/on_mark_detonation(mob/living/target, mob/living/user)
+ for(var/mob/living/L in oview(2, user))
+ if(L.stat == DEAD)
+ continue
+ playsound(L, 'sound/magic/fireball.ogg', 20, 1)
+ new /obj/effect/temp_visual/fire(L.loc)
+ addtimer(CALLBACK(src, .proc/pushback, L, user), 1) //no free backstabs, we push AFTER module stuff is done
+ L.adjustFireLoss(bonus_value)
+
+/obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user)
+ if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed
+ step(target, get_dir(user, target))
+
+//bubblegum
+/obj/item/crusher_trophy/demon_claws
+ name = "demon claws"
+ desc = "A set of blood-drenched claws from a massive demon's hand. Suitable as a trophy for a kinetic crusher."
+ icon_state = "demon_claws"
+ gender = PLURAL
+ denied_type = /obj/item/crusher_trophy/demon_claws
+ bonus_value = 10
+ var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
+
+/obj/item/crusher_trophy/demon_claws/effect_desc()
+ return "melee hits to do [bonus_value * 0.2] more damage and heal you for [bonus_value * 0.1], with 5X effect on mark detonation"
+
+/obj/item/crusher_trophy/demon_claws/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.force += bonus_value * 0.2
+ H.force_unwielded += bonus_value * 0.2
+ H.force_wielded += bonus_value * 0.2
+ H.detonation_damage += bonus_value * 0.8
+
+/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.force -= bonus_value * 0.2
+ H.force_unwielded -= bonus_value * 0.2
+ H.force_wielded -= bonus_value * 0.2
+ H.detonation_damage -= bonus_value * 0.8
+
+/obj/item/crusher_trophy/demon_claws/on_melee_hit(mob/living/target, mob/living/user)
+ user.heal_ordered_damage(bonus_value * 0.1, damage_heal_order)
+
+/obj/item/crusher_trophy/demon_claws/on_mark_detonation(mob/living/target, mob/living/user)
+ user.heal_ordered_damage(bonus_value * 0.4, damage_heal_order)
+
+//colossus
+/obj/item/crusher_trophy/blaster_tubes
+ name = "blaster tubes"
+ desc = "The blaster tubes from a colossus's arm. Suitable as a trophy for a kinetic crusher."
+ icon_state = "blaster_tubes"
+ gender = PLURAL
+ denied_type = /obj/item/crusher_trophy/blaster_tubes
+ bonus_value = 15
+ var/deadly_shot = FALSE
+
+/obj/item/crusher_trophy/blaster_tubes/effect_desc()
+ return "mark detonation to make the next destabilizer shot deal [bonus_value] damage but move slower"
+
+/obj/item/crusher_trophy/blaster_tubes/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user)
+ if(deadly_shot)
+ marker.name = "deadly [marker.name]"
+ marker.icon_state = "chronobolt"
+ marker.damage = bonus_value
+ marker.nodamage = FALSE
+ marker.speed = 2
+ deadly_shot = FALSE
+
+/obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user)
+ deadly_shot = TRUE
+ addtimer(CALLBACK(src, .proc/reset_deadly_shot), 300, TIMER_UNIQUE|TIMER_OVERRIDE)
+
+/obj/item/crusher_trophy/blaster_tubes/proc/reset_deadly_shot()
+ deadly_shot = FALSE
+
+//hierophant
+/obj/item/crusher_trophy/vortex_talisman
+ name = "vortex talisman"
+ desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher."
+ icon_state = "vortex_talisman"
+ denied_type = /obj/item/crusher_trophy/vortex_talisman
+
+/obj/item/crusher_trophy/vortex_talisman/effect_desc()
+ return "mark detonation to create a barrier you can pass"
+
+/obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user)
+ var/turf/T = get_turf(user)
+ new /obj/effect/temp_visual/hierophant/wall/crusher(T, user) //a wall only you can pass!
+ var/turf/otherT = get_step(T, turn(user.dir, 90))
+ if(otherT)
+ new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
+ otherT = get_step(T, turn(user.dir, -90))
+ if(otherT)
+ new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
+
+/obj/effect/temp_visual/hierophant/wall/crusher
+ duration = 75
\ No newline at end of file
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index c821bf84baa..ee42d12a53f 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -421,7 +421,7 @@
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600),
new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750),
- new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/required/kinetic_crusher, 750),
+ new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/kinetic_crusher, 750),
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750),
new /datum/data/mining_equipment("Advanced Scanner", /obj/item/t_scanner/adv_mining_scanner, 800),
new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 800),
@@ -625,7 +625,7 @@
// new /obj/item/stack/marker_beacon/thirty(drop_location)
if("Crusher Kit")
new /obj/item/extinguisher/mini(drop_location)
- new /obj/item/twohanded/required/kinetic_crusher(drop_location)
+ new /obj/item/twohanded/kinetic_crusher(drop_location)
if("Mining Conscription Kit")
new /obj/item/storage/backpack/duffel/mining_conscript(drop_location)
@@ -1148,103 +1148,4 @@
return ..()
C.preserved = 1
to_chat(user, "You inject the hivelord core with the stabilizer. It will no longer go inert.")
- qdel(src)
-
-/*********************Mining Hammer****************/
-/obj/item/twohanded/required/kinetic_crusher
- icon = 'icons/obj/mining.dmi'
- icon_state = "mining_hammer1"
- item_state = "mining_hammer1"
- name = "proto-kinetic crusher"
- desc = "An early design of the proto-kinetic accelerator, it is little more than an combination of various mining tools cobbled together, forming a high-tech club.\
- While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna. \
- \nMark a mob with the destabilizing force, then hit them in melee to activate it for extra damage. Extra damage if backstabbed in this fashion. \
- This weapon is only particularly effective against large creatures."
- force = 20 //As much as a bone spear, but this is significantly more annoying to carry around due to requiring the use of both hands at all times
- w_class = WEIGHT_CLASS_BULKY
- slot_flags = SLOT_BACK
- force_unwielded = 20 //It's never not wielded so these are the same
- force_wielded = 20
- throwforce = 5
- throw_speed = 4
- light_range = 4
- armour_penetration = 10
- materials = list(MAT_METAL=1150, MAT_GLASS=2075)
- hitsound = 'sound/weapons/bladeslice.ogg'
- attack_verb = list("smashes", "crushes", "cleaves", "chops", "pulps")
- sharp = 1
- var/charged = 1
- var/charge_time = 16
- var/atom/mark = null
- var/marked_image = null
-
-/obj/item/projectile/destabilizer
- name = "destabilizing force"
- icon_state = "pulse1"
- damage = 0 //We're just here to mark people. This is still a melee weapon.
- damage_type = BRUTE
- flag = "bomb"
- range = 6
- var/obj/item/twohanded/required/kinetic_crusher/hammer_synced = null
-
-/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0, hit_zone)
- if(hammer_synced)
- if(hammer_synced.mark == target)
- return ..()
- if(isliving(target))
- if(hammer_synced.mark && hammer_synced.marked_image)
- hammer_synced.mark.underlays -= hammer_synced.marked_image
- hammer_synced.marked_image = null
- var/mob/living/L = target
- if(L.mob_size >= MOB_SIZE_LARGE)
- hammer_synced.mark = L
- var/image/I = image('icons/effects/effects.dmi', loc = L, icon_state = "shield2",pixel_y = (-L.pixel_y),pixel_x = (-L.pixel_x))
- L.underlays += I
- hammer_synced.marked_image = I
- var/target_turf = get_turf(target)
- if(istype(target_turf, /turf/simulated/mineral))
- var/turf/simulated/mineral/M = target_turf
- new /obj/effect/temp_visual/kinetic_blast(M)
- M.gets_drilled(firer)
- ..()
-
-/obj/item/twohanded/required/kinetic_crusher/afterattack(atom/target, mob/user, proximity_flag)
- if(!proximity_flag && charged)//Mark a target, or mine a tile.
- var/turf/proj_turf = get_turf(src)
- if(!istype(proj_turf, /turf))
- return
- var/datum/gas_mixture/environment = proj_turf.return_air()
- var/pressure = environment.return_pressure()
- if(pressure > 50)
- playsound(user, 'sound/weapons/empty.ogg', 100, 1)
- return
- var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(user.loc)
- D.preparePixelProjectile(target,get_turf(target), user)
- D.hammer_synced = src
- playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
- D.fire()
- charged = 0
- icon_state = "mining_hammer1_uncharged"
- spawn(charge_time)
- Recharge()
- return
- if(proximity_flag && target == mark && isliving(target))
- var/mob/living/L = target
- new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
- mark = 0
- if(L.mob_size >= MOB_SIZE_LARGE)
- L.underlays -= marked_image
- QDEL_NULL(marked_image)
- var/backstab = check_target_facings(user, L)
- var/def_check = L.getarmor(type = "bomb")
- if(backstab == FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR || backstab == FACING_SAME_DIR)
- L.apply_damage(80, BRUTE, blocked = def_check)
- playsound(user, 'sound/weapons/kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
- else
- L.apply_damage(50, BRUTE, blocked = def_check)
-
-/obj/item/twohanded/required/kinetic_crusher/proc/Recharge()
- if(!charged)
- charged = 1
- icon_state = "mining_hammer1"
- playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
\ No newline at end of file
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/mining/explorer_gear.dm b/code/modules/mining/explorer_gear.dm
index a9464efe959..566694d480d 100644
--- a/code/modules/mining/explorer_gear.dm
+++ b/code/modules/mining/explorer_gear.dm
@@ -41,4 +41,57 @@
"Drask" = 'icons/mob/species/drask/head.dmi',
"Grey" = 'icons/mob/species/grey/head.dmi',
"Skrell" = 'icons/mob/species/skrell/head.dmi'
- )
\ No newline at end of file
+ )
+
+/obj/item/clothing/suit/space/hostile_environment
+ name = "H.E.C.K. suit"
+ desc = "Hostile Environment Cross-Kinetic Suit: A suit designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner."
+ icon_state = "hostile_env"
+ item_state = "hostile_env"
+ flags = THICKMATERIAL //not spaceproof
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ burn_state = FIRE_PROOF | LAVA_PROOF
+ slowdown = 0
+ armor = list(melee = 70, bullet = 40, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 100)
+ allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
+
+/obj/item/clothing/suit/space/hostile_environment/New()
+ ..()
+ AddComponent(/datum/component/spraycan_paintable)
+ START_PROCESSING(SSobj, src)
+
+/obj/item/clothing/suit/space/hostile_environment/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/clothing/suit/space/hostile_environment/process()
+ var/mob/living/carbon/C = loc
+ if(istype(C) && prob(2)) //cursed by bubblegum
+ if(prob(15))
+ new /obj/effect/hallucination/oh_yeah(get_turf(C), C)
+ to_chat(C, "[pick("I AM IMMORTAL.","I SHALL TAKE BACK WHAT'S MINE.","I SEE YOU.","YOU CANNOT ESCAPE ME FOREVER.","DEATH CANNOT HOLD ME.")]")
+ else
+ to_chat(C, "[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]")
+
+/obj/item/clothing/head/helmet/space/hostile_environment
+ name = "H.E.C.K. helmet"
+ desc = "Hostile Environiment Cross-Kinetic Helmet: A helmet designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner."
+ icon_state = "hostile_env"
+ item_state = "hostile_env"
+ w_class = WEIGHT_CLASS_NORMAL
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ flags = THICKMATERIAL // no space protection
+ armor = list(melee = 70, bullet = 40, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 100)
+ burn_state = FIRE_PROOF | LAVA_PROOF
+
+/obj/item/clothing/head/helmet/space/hostile_environment/New()
+ ..()
+ AddComponent(/datum/component/spraycan_paintable)
+ update_icon()
+
+/obj/item/clothing/head/helmet/space/hostile_environment/update_icon()
+ ..()
+ cut_overlays()
+ var/mutable_appearance/glass_overlay = mutable_appearance(icon, "hostile_env_glass")
+ glass_overlay.appearance_flags = RESET_COLOR
+ add_overlay(glass_overlay)
\ No newline at end of file
diff --git a/code/modules/mining/lavaland/loot/ashdragon_loot.dm b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
index 4f8f01498d0..6a30c565547 100644
--- a/code/modules/mining/lavaland/loot/ashdragon_loot.dm
+++ b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
@@ -15,6 +15,15 @@
if(4)
new /obj/item/dragons_blood(src)
+
+/obj/structure/closet/crate/necropolis/dragon/crusher
+ name = "firey dragon chest"
+
+/obj/structure/closet/crate/necropolis/dragon/crusher/New()
+ ..()
+ new /obj/item/crusher_trophy/tail_spike(src)
+
+
// Spectral Blade
/obj/item/melee/ghost_sword
diff --git a/code/modules/mining/lavaland/loot/bubblegum_loot.dm b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
index bb0031ea77d..6cc33e1ad92 100644
--- a/code/modules/mining/lavaland/loot/bubblegum_loot.dm
+++ b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
@@ -3,6 +3,8 @@
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
+ new /obj/item/clothing/suit/space/hostile_environment(src)
+ new /obj/item/clothing/head/helmet/space/hostile_environment(src)
var/loot = rand(1,3)
switch(loot)
if(1)
@@ -12,6 +14,13 @@
if(3)
new /obj/item/gun/magic/staff/spellblade(src)
+/obj/structure/closet/crate/necropolis/bubblegum/crusher
+ name = "bloody bubblegum chest"
+
+/obj/structure/closet/crate/necropolis/bubblegum/crusher/New()
+ ..()
+ new /obj/item/crusher_trophy/demon_claws(src)
+
// Mayhem
/obj/item/mayhem
diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm
index 2490f6f48db..9b6bd8c5893 100644
--- a/code/modules/mining/lavaland/loot/colossus_loot.dm
+++ b/code/modules/mining/lavaland/loot/colossus_loot.dm
@@ -1,3 +1,22 @@
+//Colossus
+/obj/structure/closet/crate/necropolis/colossus
+ name = "colossus chest"
+
+/obj/structure/closet/crate/necropolis/colossus/New()
+ ..()
+ var/list/choices = subtypesof(/obj/machinery/anomalous_crystal)
+ var/random_crystal = pick(choices)
+ new random_crystal(src)
+ new /obj/item/organ/internal/vocal_cords/colossus(src)
+
+/obj/structure/closet/crate/necropolis/colossus/crusher
+ name = "angelic colossus chest"
+
+/obj/structure/closet/crate/necropolis/colossus/crusher/New()
+ ..()
+ new /obj/item/crusher_trophy/blaster_tubes(src)
+
+
//Black Box
/obj/machinery/smartfridge/black_box
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 76f4637473a..ab9b7979d03 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -57,7 +57,10 @@
if(15)
new /obj/item/guardiancreator(src)
if(16)
- new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
+ if(prob(50))
+ new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
+ else
+ new /obj/item/disk/design_disk/modkit_disc/bounty(src)
if(17)
new /obj/item/warp_cube/red(src)
if(18)
@@ -118,6 +121,10 @@
name = "Resonator Blast Mod Disk"
modkit_design = /datum/design/unique_modkit/resonator_blast
+/obj/item/disk/design_disk/modkit_disc/bounty
+ name = "Death Syphon Mod Disk"
+ modkit_design = /datum/design/unique_modkit/bounty
+
/datum/design/unique_modkit
category = list("Mining", "Cyborg Upgrade Modules") //can't be normally obtained
build_type = PROTOLATHE | MECHFAB
@@ -141,4 +148,12 @@
desc = "A device which causes kinetic accelerators to fire shots that leave and detonate resonator blasts."
id = "resonatormod"
materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_SILVER= 5000, MAT_URANIUM = 5000)
- build_path = /obj/item/borg/upgrade/modkit/resonator_blasts
\ No newline at end of file
+ build_path = /obj/item/borg/upgrade/modkit/resonator_blasts
+
+/datum/design/unique_modkit/bounty
+ name = "Kinetic Accelerator Death Syphon Mod"
+ desc = "A device which causes kinetic accelerators to permanently gain damage against creature types killed with it."
+ id = "bountymod"
+ materials = list(MAT_METAL = 4000, MAT_SILVER = 4000, MAT_GOLD = 4000, MAT_BLUESPACE = 4000)
+ reagents_list = list("blood" = 40)
+ build_path = /obj/item/borg/upgrade/modkit/bounty
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 73a76e00420..d573d2a8191 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -586,7 +586,8 @@ var/global/list/damage_icon_parts = list()
standing.overlays += image("icon" = A.sprite_sheets[dna.species.name], "icon_state" = "[A.icon_state]")
else
standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]")
-
+ standing.alpha = w_uniform.alpha
+ standing.color = w_uniform.color
overlays_standing[UNIFORM_LAYER] = standing
else
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
@@ -769,6 +770,8 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "shoeblood")
bloodsies.color = shoes.blood_color
standing.overlays += bloodsies
+ standing.alpha = shoes.alpha
+ standing.color = shoes.color
overlays_standing[SHOES_LAYER] = standing
else
if(feet_blood_DNA)
@@ -819,6 +822,8 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "helmetblood")
bloodsies.color = head.blood_color
standing.overlays += bloodsies
+ standing.alpha = head.alpha
+ standing.color = head.color
overlays_standing[HEAD_LAYER] = standing
apply_overlay(HEAD_LAYER)
@@ -886,6 +891,8 @@ var/global/list/damage_icon_parts = list()
bloodsies.color = wear_suit.blood_color
standing.overlays += bloodsies
+ standing.alpha = wear_suit.alpha
+ standing.color = wear_suit.color
overlays_standing[SUIT_LAYER] = standing
apply_overlay(SUIT_LAYER)
@@ -951,6 +958,8 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "maskblood")
bloodsies.color = wear_mask.blood_color
standing.overlays += bloodsies
+ standing.alpha = wear_mask.alpha
+ standing.color = wear_mask.color
overlays_standing[FACEMASK_LAYER] = standing
apply_overlay(FACEMASK_LAYER)
@@ -973,6 +982,8 @@ var/global/list/damage_icon_parts = list()
standing = mutable_appearance('icons/mob/back.dmi', "[back.icon_state]", layer = -BACK_LAYER)
//create the image
+ standing.alpha = back.alpha
+ standing.color = back.color
overlays_standing[BACK_LAYER] = standing
apply_overlay(BACK_LAYER)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 7fd32bd71ec..d45e6f6ead8 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -37,6 +37,7 @@ Difficulty: Medium
ranged = 1
ranged_cooldown_time = 16
pixel_x = -16
+ crusher_loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator)
wander = FALSE
del_on_death = TRUE
@@ -48,7 +49,7 @@ Difficulty: Medium
var/guidance = FALSE
deathmessage = "falls to the ground, decaying into glowing particles."
death_sound = "bodyfall"
-
+
/obj/item/gps/internal/miner
icon_state = null
gpstag = "Resonant Signal"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index a53b8092e54..ac5e40025c6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -42,6 +42,7 @@ Difficulty: Hard
ranged = 1
pixel_x = -32
del_on_death = 1
+ crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/crusher)
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
var/charging = 0
medal_type = BOSS_MEDAL_BUBBLEGUM
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 5d66061335c..3ebea47e353 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -45,7 +45,8 @@ Difficulty: Very Hard
del_on_death = 1
medal_type = BOSS_MEDAL_COLOSSUS
score_type = COLOSSUS_SCORE
- loot = list(/obj/machinery/anomalous_crystal/random, /obj/item/organ/internal/vocal_cords/colossus)
+ crusher_loot = list(/obj/structure/closet/crate/necropolis/colossus/crusher)
+ loot = list(/obj/structure/closet/crate/necropolis/colossus)
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
deathmessage = "disintegrates, leaving a glowing core in its wake."
death_sound = 'sound/misc/demon_dies.ogg'
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 68db8cb1274..0789d00832d 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -43,6 +43,7 @@ Difficulty: Medium
move_to_delay = 10
ranged = 1
pixel_x = -16
+ crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/crusher)
loot = list(/obj/structure/closet/crate/necropolis/dragon)
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
var/swooping = 0
@@ -271,6 +272,7 @@ Difficulty: Medium
melee_damage_lower = 30
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
loot = list()
+ crusher_loot = list()
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 7f974149556..bb4e9297605 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -53,6 +53,7 @@ Difficulty: Hard
ranged_cooldown_time = 40
aggro_vision_range = 23
loot = list(/obj/item/hierophant_staff)
+ crusher_loot = list(/obj/item/hierophant_staff, /obj/item/crusher_trophy/vortex_talisman)
wander = FALSE
var/burst_range = 3 //range on burst aoe
var/beam_range = 5 //range on cross blast beams
@@ -556,6 +557,37 @@ Difficulty: Hard
playsound(M,'sound/weapons/sear.ogg', 50, 1, -4)
M.take_damage(damage, BURN, 0, 0)
+/obj/effect/temp_visual/hierophant/wall //smoothing and pooling were not friends, but pooling is dead.
+ name = "vortex wall"
+ icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
+ icon_state = "wall"
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ duration = 100
+ smooth = SMOOTH_TRUE
+
+/obj/effect/temp_visual/hierophant/wall/New(loc, new_caster)
+ ..()
+ queue_smooth_neighbors(src)
+ queue_smooth(src)
+
+/obj/effect/temp_visual/hierophant/wall/Destroy()
+ queue_smooth_neighbors(src)
+ return ..()
+
+/obj/effect/temp_visual/hierophant/wall/CanPass(atom/movable/mover, turf/target)
+ if(QDELETED(caster))
+ return FALSE
+ if(mover == caster.pulledby)
+ return TRUE
+ if(istype(mover, /obj/item/projectile))
+ var/obj/item/projectile/P = mover
+ if(P.firer == caster)
+ return TRUE
+ if(mover == caster)
+ return TRUE
+ return FALSE
+
+
/obj/effect/hierophant
name = "hierophant rune"
desc = "A powerful magic mark allowing whomever attunes themself to it to return to it at will."
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 a32aceb33e3..f57559d549a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -31,6 +31,7 @@
/obj/structure/barricade,
/obj/machinery/field,
/obj/machinery/power/emitter)
+ var/list/crusher_loot
var/medal_type
var/score_type = BOSS_SCORE
var/elimination = 0
@@ -43,6 +44,10 @@
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
+/mob/living/simple_animal/hostile/megafauna/New()
+ ..()
+ apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+
/mob/living/simple_animal/hostile/megafauna/Destroy()
QDEL_NULL(internal_gps)
. = ..()
@@ -53,11 +58,17 @@
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
// this happens before the parent call because `del_on_death` may be set
if(can_die() && !admin_spawned)
- feedback_set_details("megafauna_kills","[initial(name)]")
+ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(C && crusher_loot && C.total_damage >= maxHealth * 0.6)
+ spawn_crusher_loot()
if(!elimination) //used so the achievment only occurs for the last legion to die.
grant_achievement(medal_type,score_type)
+ feedback_set_details("megafauna_kills","[initial(name)]")
return ..()
+/mob/living/simple_animal/hostile/megafauna/proc/spawn_crusher_loot()
+ loot = crusher_loot
+
/mob/living/simple_animal/hostile/megafauna/AttackingTarget()
..()
if(isliving(target))
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
index 28aacd37a73..ad8dcf44699 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
@@ -77,6 +77,7 @@
stat_attack = 1
flying = TRUE
robust_searching = 1
+ crusher_loot = /obj/item/crusher_trophy/watcher_wing
loot = list()
butcher_results = list(/obj/item/stack/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1)
@@ -102,6 +103,8 @@
light_power = 2.5
light_color = LIGHT_COLOR_ORANGE
projectiletype = /obj/item/projectile/temp/basilisk/magmawing
+ crusher_loot = /obj/item/crusher_trophy/blaster_tubes/magma_wing
+ crusher_drop_mod = 60
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing
name = "icewing watcher"
@@ -114,6 +117,8 @@
health = 170
projectiletype = /obj/item/projectile/temp/basilisk/icewing
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/bone = 1) //No sinew; the wings are too fragile to be usable
+ crusher_loot = /obj/item/crusher_trophy/watcher_wing/ice_wing
+ crusher_drop_mod = 30
/obj/item/projectile/temp/basilisk/magmawing
name = "scorching blast"
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
index a1c488b4068..dae7a688cb3 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
@@ -83,6 +83,7 @@
icon_dead = "goliath_dead"
throw_message = "does nothing to the tough hide of the"
pre_attack_icon = "goliath2"
+ crusher_loot = /obj/item/crusher_trophy/goliath_tentacle
butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2)
loot = list()
stat_attack = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
index 60c1f5e08e7..44ff6049a71 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
@@ -45,6 +45,9 @@
/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget()
OpenFire()
+/mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot()
+ loot += crusher_loot //we don't butcher
+
/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed)
// Only execute the below if we successfully died
. = ..(gibbed)
@@ -231,6 +234,7 @@
speak_emote = list("echoes")
attack_sound = 'sound/weapons/pierce.ogg'
throw_message = "bounces harmlessly off of"
+ crusher_loot = /obj/item/crusher_trophy/legion_skull
loot = list(/obj/item/organ/internal/hivelord_core/legion)
brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
del_on_death = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
index e23624a5a9d..434869c1d6d 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
@@ -1,4 +1,4 @@
-/mob/living/simple_animal/hostile/asteroid/
+/mob/living/simple_animal/hostile/asteroid
vision_range = 2
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
@@ -13,12 +13,18 @@
response_harm = "strikes"
status_flags = 0
a_intent = INTENT_HARM
+ var/crusher_loot
var/throw_message = "bounces off of"
var/icon_aggro = null // for swapping to when we get aggressive
var/fromtendril = FALSE
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
mob_size = MOB_SIZE_LARGE
+ var/crusher_drop_mod = 25
+
+/mob/living/simple_animal/hostile/asteroid/New()
+ ..()
+ apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
@@ -46,3 +52,12 @@
visible_message("The [T.name] [src.throw_message] [src.name]!")
return
..()
+
+/mob/living/simple_animal/hostile/asteroid/death(gibbed)
+ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 4 creatures before getting the item
+ spawn_crusher_loot()
+ ..(gibbed)
+
+/mob/living/simple_animal/hostile/asteroid/proc/spawn_crusher_loot()
+ butcher_results[crusher_loot] = 1
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 4662062a56e..ff65b67e11c 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -474,6 +474,45 @@
return
new /obj/effect/temp_visual/resonance(target_turf, K.firer, null, 30)
+/obj/item/borg/upgrade/modkit/bounty
+ name = "death syphon"
+ desc = "Killing or assisting in killing a creature permanently increases your damage against that type of creature."
+ denied_type = /obj/item/borg/upgrade/modkit/bounty
+ modifier = 1.25
+ cost = 30
+ var/maximum_bounty = 25
+ var/list/bounties_reaped = list()
+
+/obj/item/borg/upgrade/modkit/bounty/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(isliving(target))
+ var/mob/living/L = target
+ var/list/existing_marks = L.has_status_effect_list(STATUS_EFFECT_SYPHONMARK)
+ for(var/i in existing_marks)
+ var/datum/status_effect/syphon_mark/SM = i
+ if(SM.reward_target == src) //we want to allow multiple people with bounty modkits to use them, but we need to replace our own marks so we don't multi-reward
+ SM.reward_target = null
+ qdel(SM)
+ L.apply_status_effect(STATUS_EFFECT_SYPHONMARK, src)
+
+/obj/item/borg/upgrade/modkit/bounty/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(isliving(target))
+ var/mob/living/L = target
+ if(bounties_reaped[L.type])
+ var/kill_modifier = 1
+ if(K.pressure_decrease_active)
+ kill_modifier *= K.pressure_decrease
+ var/armor = L.run_armor_check(K.def_zone, K.flag, "", "", K.armour_penetration)
+ L.apply_damage(bounties_reaped[L.type]*kill_modifier, K.damage_type, K.def_zone, armor)
+
+/obj/item/borg/upgrade/modkit/bounty/proc/get_kill(mob/living/L)
+ var/bonus_mod = 1
+ if(ismegafauna(L)) //megafauna reward
+ bonus_mod = 4
+ if(!bounties_reaped[L.type])
+ bounties_reaped[L.type] = min(modifier * bonus_mod, maximum_bounty)
+ else
+ bounties_reaped[L.type] = min(bounties_reaped[L.type] + (modifier * bonus_mod), maximum_bounty)
+
//Indoors
/obj/item/borg/upgrade/modkit/indoors
name = "decrease pressure penalty"
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 7f84b29d04e..4bc39d8f80b 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 47cb86a2c89..97d2750029e 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index e4630c2764e..15100e9112e 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index b18cb799817..cb6a2c6bd64 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index f79ca1fb338..abce25ab86f 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index a20cf61eb33..a3d66d4d921 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 8e5a4b8e879..8371295985f 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi
index cd2c6da08ee..8e91b20368f 100644
Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index 29196e625ae..82ab4786c37 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/turf/walls/hierophant_wall_temp.dmi b/icons/turf/walls/hierophant_wall_temp.dmi
new file mode 100644
index 00000000000..9f0d4b8d23c
Binary files /dev/null and b/icons/turf/walls/hierophant_wall_temp.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 86eb2825b04..4475b56343b 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -278,6 +278,7 @@
#include "code\datums\components\ducttape.dm"
#include "code\datums\components\jestosterone.dm"
#include "code\datums\components\material_container.dm"
+#include "code\datums\components\paintable.dm"
#include "code\datums\components\squeak.dm"
#include "code\datums\components\waddling.dm"
#include "code\datums\diseases\_disease.dm"
@@ -1651,6 +1652,7 @@
#include "code\modules\mining\ore.dm"
#include "code\modules\mining\satchel_ore_boxdm.dm"
#include "code\modules\mining\shelters.dm"
+#include "code\modules\mining\equipment\kinetic_crusher.dm"
#include "code\modules\mining\equipment\marker_beacons.dm"
#include "code\modules\mining\equipment\survival_pod.dm"
#include "code\modules\mining\laborcamp\laborshuttle.dm"