diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index b46f14be572..de8a39ffd31 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -177,6 +177,15 @@
/obj/machinery/door/window/attack_ghost(mob/user as mob)
return
+
+/obj/machinery/door/window/mech_melee_attack(obj/mecha/M)
+ if(M.damtype == "brute")
+ playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ M.occupant_message("You hit [src].")
+ visible_message("[src] has been hit by [M.name].")
+ take_damage(M.force)
+ return
+
/obj/machinery/door/window/attack_ai(mob/user as mob)
return src.attack_hand(user)
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index e9be41ae473..d9b26404cad 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -1,8 +1,5 @@
/obj/mecha/combat
force = 30
- var/melee_cooldown = 10
- var/melee_can_hit = 1
- var/list/destroyable_obj = list(/obj/mecha, /obj/structure/window, /obj/structure/grille, /turf/simulated/wall)
var/maxsize = 2
internal_damage_threshold = 50
maint_access = 0
@@ -11,232 +8,6 @@
damage_absorption = list("brute"=0.7,"fire"=1,"bullet"=0.7,"laser"=0.85,"energy"=1,"bomb"=0.8)
var/am = "d3c2fbcadca903a41161ccc9df9cf948"
-/*
-/obj/mecha/combat/range_action(target as obj|mob|turf)
- if(internal_damage&MECHA_INT_CONTROL_LOST)
- target = pick(view(3,target))
- if(selected_weapon)
- selected_weapon.fire(target)
- return
-*/
-
-/obj/mecha/combat/melee_action(target as obj|mob|turf)
- if(internal_damage&MECHA_INT_CONTROL_LOST)
- target = safepick(oview(1,src))
- if(!melee_can_hit || !istype(target, /atom)) return
- if(istype(target, /mob/living))
- var/mob/living/M = target
- if(src.occupant.a_intent == "harm" && !istype(src,/obj/mecha/combat/gygax))
- playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
- if(damtype == "brute")
- step_away(M,src,15)
- /*
- if(M.stat>1)
- M.gib()
- melee_can_hit = 0
- if(do_after(melee_cooldown))
- melee_can_hit = 1
- return
- */
- if(istype(target, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = target
- // if (M.health <= 0) return
-
- var/datum/organ/external/temp = H.get_organ(pick("chest", "chest", "chest", "head"))
- if(temp)
- var/update = 0
- switch(damtype)
- if("brute")
- H.Paralyse(1)
- update |= temp.take_damage(rand(force/2, force), 0)
- if("fire")
- update |= temp.take_damage(0, rand(force/2, force))
- if("tox")
- if(H.reagents)
- if(H.reagents.get_reagent_amount("carpotoxin") + force < force*2)
- H.reagents.add_reagent("carpotoxin", force)
- if(H.reagents.get_reagent_amount("cryptobiolin") + force < force*2)
- H.reagents.add_reagent("cryptobiolin", force)
- else
- return
- if(update) H.UpdateDamageIcon()
- H.updatehealth()
-
- else
- switch(damtype)
- if("brute")
- M.Paralyse(1)
- M.take_overall_damage(rand(force/2, force))
- if("fire")
- M.take_overall_damage(0, rand(force/2, force))
- if("tox")
- if(M.reagents)
- if(M.reagents.get_reagent_amount("carpotoxin") + force < force*2)
- M.reagents.add_reagent("carpotoxin", force)
- if(M.reagents.get_reagent_amount("cryptobiolin") + force < force*2)
- M.reagents.add_reagent("cryptobiolin", force)
- else
- return
- M.updatehealth()
- src.occupant_message("You hit [target].")
- src.visible_message("[src.name] hits [target].")
- else
- step_away(M,src)
- src.occupant_message("You push [target] out of the way.")
- src.visible_message("[src] pushes [target] out of the way.")
-
- melee_can_hit = 0
- if(do_after(melee_cooldown))
- melee_can_hit = 1
- return
-
- else
- if(damtype == "brute")
- for(var/target_type in src.destroyable_obj)
- if(istype(target, target_type) && hascall(target, "attackby"))
- src.occupant_message("You hit [target].")
- src.visible_message("[src.name] hits [target]")
- if(!istype(target, /turf/simulated/wall))
- target:attackby(src,src.occupant)
- else if(prob(5))
- target:dismantle_wall(1)
- src.occupant_message("\blue You smash through the wall.")
- src.visible_message("[src.name] smashes through the wall")
- playsound(src, 'sound/weapons/smash.ogg', 50, 1)
- melee_can_hit = 0
- if(do_after(melee_cooldown))
- melee_can_hit = 1
- break
- return
-
-/*
-/obj/mecha/combat/proc/mega_shake(target)
- if(!istype(target, /obj) && !istype(target, /mob)) return
- if(istype(target, /mob))
- var/mob/M = target
- M.Dizzy(3)
- M.adjustBruteLoss(1)
- M.updatehealth()
- for (var/mob/V in viewers(src))
- V.show_message("[src.name] shakes [M] like a rag doll.")
- return
-*/
-
-/*
- if(energy>0 && can_move)
- if(step(src,direction))
- can_move = 0
- spawn(step_in) can_move = 1
- if(overload)
- energy = energy-2
- health--
- else
- energy--
- return 1
-
- return 0
-*/
-/*
-/obj/mecha/combat/hear_talk(mob/M as mob, text)
- ..()
- if(am && M==occupant)
- if(findtext(text,""))
- sam()
- return
-
-/obj/mecha/combat/proc/sam()
- if(am)
- var/window = {"
-
-
-
-
-
-
-
-
- "}
- occupant << browse(window, "window=sam;size=800x600;")
- onclose(occupant, "sam", src)
- return
-*/
/obj/mecha/combat/moved_inside(var/mob/living/carbon/human/H as mob)
if(..())
if(H.client)
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index ab30fab2269..2c723a2e530 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -16,7 +16,6 @@
internal_damage_threshold = 35
max_equip = 3
maxsize = 2
- force = 10
step_energy_drain = 3
/obj/mecha/combat/gygax/loaded/New()
diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm
index 9fbc7eb67c4..9f68e36ba7b 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -26,16 +26,6 @@
ME.attach(src)
return
-
-
-
-/obj/mecha/combat/honker/melee_action(target)
- if(!melee_can_hit)
- return
- else if(istype(target, /mob))
- step_away(target,src,15)
- return
-
/obj/mecha/combat/honker/get_stats_part()
var/integrity = health/initial(health)*100
var/cell_charge = get_charge()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 57e62d7ef13..6a3f81c461c 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -18,6 +18,7 @@
unacidable = 1 //and no deleting hoomans inside
layer = MOB_LAYER //icon draw layer
infra_luminosity = 15 //byond implementation is bugged.
+ force = 5
var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
var/can_move = 1
var/mob/living/carbon/occupant = null
@@ -71,6 +72,8 @@
var/stepsound = 'sound/mecha/mechturn.ogg'
+ var/melee_cooldown = 10
+ var/melee_can_hit = 1
/obj/mecha/New()
..()
@@ -226,12 +229,15 @@
/obj/mecha/proc/click_action(atom/target,mob/user)
if(!src.occupant || src.occupant != user ) return
- if(user.stat) return
- if(state)
- occupant_message("Maintenance protocols in effect")
+ if(user.stat || !user.canmove)
+ return
+ if(state)
+ occupant_message("Maintenance protocols in effect.")
+ return
+ if(!get_charge())
+ return
+ if(src == target)
return
- if(!get_charge()) return
- if(src == target) return
var/dir_to_target = get_dir(src,target)
if(dir_to_target && !(dir_to_target & src.dir))//wrong direction
return
@@ -239,17 +245,46 @@
target = safepick(view(3,target))
if(!target)
return
- if(get_dist(src, target)>1)
+ if(!target.Adjacent(src))
if(selected && selected.is_ranged())
selected.action(target)
else if(selected && selected.is_melee())
selected.action(target)
else
- src.melee_action(target)
+ if(internal_damage&MECHA_INT_CONTROL_LOST)
+ target = safepick(oview(1,src))
+ if(!melee_can_hit || !istype(target, /atom))
+ return
+ target.mech_melee_attack(src)
+ melee_can_hit = 0
+ if(do_after(melee_cooldown))
+ melee_can_hit = 1
+ return
+
+/obj/mecha/proc/mech_toxin_damage(mob/living/target)
+ playsound(src, 'sound/effects/spray2.ogg', 50, 1)
+ if(target.reagents)
+ if(target.reagents.get_reagent_amount("cryptobiolin") + force < force*2)
+ target.reagents.add_reagent("cryptobiolin", force/2)
+ if(target.reagents.get_reagent_amount("toxin") + force < force*2)
+ target.reagents.add_reagent("toxin", force/2.5)
+
+
+
+/atom/proc/mech_melee_attack(obj/mecha/M)
return
-
-/obj/mecha/proc/melee_action(atom/target)
+/obj/mecha/mech_melee_attack(obj/mecha/M)
+ if(M.damtype =="brute")
+ playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
+ else if(M.damtype == "fire")
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
+ else
+ return
+ M.occupant_message("You hit [src].")
+ visible_message("[src] has been hit by [M.name].")
+ take_damage(M.force, damtype)
+ add_logs(M.occupant, src, "attacked", object=M, addition="(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
return
/obj/mecha/proc/range_action(atom/target)
diff --git a/code/game/objects/items/bluespace_crystal.dm b/code/game/objects/items/bluespace_crystal.dm
index d2b4c6e961c..a5586cf2dcf 100644
--- a/code/game/objects/items/bluespace_crystal.dm
+++ b/code/game/objects/items/bluespace_crystal.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/telescience.dmi'
icon_state = "bluespace_crystal"
w_class = 1
- origin_tech = "bluespace=3;materials=5"
+ origin_tech = "bluespace=4;materials=3"
var/blink_range = 8 // The teleport range when crushed/thrown at someone.
/obj/item/bluespace_crystal/New()
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 1e81e53bdd0..b1df8abe563 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -25,6 +25,13 @@
/obj/structure/Destroy()
if(hascall(src, "unbuckle"))
src:unbuckle()
+
+/obj/structure/mech_melee_attack(obj/mecha/M)
+ if(M.damtype == "brute")
+ M.occupant_message("You hit [src].")
+ visible_message("[src] has been hit by [M.name].")
+ return 1
+ return 0
/obj/structure/New()
..()
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 0ad7fb6f7c1..68e7f0e0efb 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -110,7 +110,12 @@
health -= M.melee_damage_upper
healthcheck()
return
-
+
+/obj/structure/grille/mech_melee_attack(obj/mecha/M)
+ if(..())
+ playsound(loc, 'sound/effects/grillehit.ogg', 80, 1)
+ health -= M.force * 0.5
+ healthcheck()
/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 8786b6ff3e9..5f6eb17013c 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -313,6 +313,11 @@ var/global/wcColored
..()
return
+
+/obj/structure/window/mech_melee_attack(obj/mecha/M)
+ if(..())
+ hit(M.force, 1)
+
/obj/structure/window/proc/hit(var/damage, var/sound_effect = 1)
if(reinf) damage *= 0.5
health = max(0, health - damage)
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index e8dd96e844d..e7006c1d3fe 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -180,6 +180,17 @@
/turf/simulated/wall/blob_act()
take_damage(rand(75, 125))
return
+
+/turf/simulated/wall/mech_melee_attack(obj/mecha/M)
+ if(M.damtype == "brute")
+ playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
+ M.occupant_message("You hit [src].")
+ visible_message("[src] has been hit by [M.name].")
+ if(prob(5) && M.force > 20)
+ dismantle_wall(1)
+ M.occupant_message("You smash through the wall.")
+ visible_message("[src.name] smashes through the wall!")
+ playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
// Wall-rot effect, a nasty fungus that destroys walls.
/turf/simulated/wall/proc/rot()
@@ -265,8 +276,8 @@
/turf/simulated/wall/attack_hand(mob/user as mob)
if (M_HULK in user.mutations)
if (prob(40) || rotting)
- usr << text("\blue You smash through the wall.")
- usr.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
+ user << text("\blue You smash through the wall.")
+ user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
dismantle_wall(1)
return
else
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 616a0d2ba1d..f15c9a5ac65 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -460,3 +460,35 @@ emp_act
var/penetrated_dam = max(0,(damage - max(0,(SS.breach_threshold - SS.damage))))
if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam)
+
+/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
+ if(M.occupant.a_intent == "harm")
+ if(M.damtype == "brute")
+ step_away(src,M,15)
+ var/datum/organ/external/affecting = get_organ(pick("chest", "chest", "chest", "head"))
+ if(affecting)
+ var/update = 0
+ switch(M.damtype)
+ if("brute")
+ if(M.force > 20)
+ Paralyse(1)
+ update |= affecting.take_damage(rand(M.force/2, M.force), 0)
+ playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
+ if("fire")
+ update |= affecting.take_damage(0, rand(M.force/2, M.force))
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
+ if("tox")
+ M.mech_toxin_damage(src)
+ else
+ return
+ updatehealth()
+
+ M.occupant_message("You hit [src].")
+ visible_message("[src] has been hit by [M.name].", \
+ "[src] has been hit by [M.name].")
+ add_logs(M.occupant, src, "attacked", object=M, addition="(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
+
+ else
+ ..()
+
+ return
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index bea2aa63f60..4f99dcc0946 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -168,6 +168,35 @@
visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!")
src.anchored = 1
src.pinned += O
+
+/mob/living/mech_melee_attack(obj/mecha/M)
+ if(M.occupant.a_intent == "harm")
+ if(M.damtype == "brute")
+ step_away(src,M,15)
+ switch(M.damtype)
+ if("brute")
+ Paralyse(1)
+ take_overall_damage(rand(M.force/2, M.force))
+ playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
+ if("fire")
+ take_overall_damage(0, rand(M.force/2, M.force))
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
+ if("tox")
+ M.mech_toxin_damage(src)
+ else
+ return
+ updatehealth()
+ M.occupant_message("You hit [src].")
+ visible_message("[src] has been hit by [M.name].", \
+ "[src] has been hit by [M.name].")
+ add_logs(M.occupant, src, "attacked", object=M, addition="(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
+ else
+ step_away(src,M)
+ add_logs(M.occupant, src, "pushed", object=M, admin=0)
+ M.occupant_message("You push [src] out of the way.")
+ visible_message("[M] pushes [src] out of the way.")
+
+ return
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 6dcafe97873..e5098adf6b5 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -2100,7 +2100,7 @@ datum/design/bluespace_crystal
name = "Artificial Bluespace Crystal"
desc = "A small blue crystal with mystical properties."
id = "bluespace_crystal"
- req_tech = list("bluespace" = 3, "materials" = 5)
+ req_tech = list("bluespace" = 4, "materials" = 6)
build_type = PROTOLATHE
materials = list("$gold" = 1500, "$diamond" = 3000, "$plasma" = 1500)
reliability_base = 100