diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm
index 96c97ec9f6..d149abdebe 100644
--- a/code/_helpers/mobs.dm
+++ b/code/_helpers/mobs.dm
@@ -235,6 +235,12 @@ Proc for attack log creation, because really why not
var/atom/original_loc = user.loc
+ var/obj/mecha/M = null
+
+ if(istype(user.loc, /obj/mecha))
+ original_loc = get_turf(original_loc)
+ M = user.loc
+
var/holding = user.get_active_hand()
var/datum/progressbar/progbar
@@ -253,7 +259,11 @@ Proc for attack log creation, because really why not
. = FALSE
break
- if(user.loc != original_loc && !ignore_movement)
+ if(M && (user.loc != M || (M.loc != original_loc && !ignore_movement))) // Mech coooooode.
+ . = FALSE
+ break
+
+ else if(user.loc != original_loc && !ignore_movement)
. = FALSE
break
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index 54e2b9c87b..a3532a1b32 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -63,6 +63,8 @@
H.reagents.add_reagent("carpotoxin", force)
if(H.reagents.get_reagent_amount("cryptobiolin") + force < force*2)
H.reagents.add_reagent("cryptobiolin", force)
+ if("halloss")
+ H.stun_effect_act(1, force / 2, BP_TORSO, src)
else
return
if(update) H.UpdateDamageIcon()
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index 35ee1cd7b6..5df31c4302 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -11,6 +11,7 @@
icon_state = "mecha_equip"
force = 5
origin_tech = list(TECH_MATERIAL = 2)
+ description_info = "Some equipment may gain new abilities or advantages if equipped to certain types of Exosuits."
var/equip_cooldown = 0
var/equip_ready = 1
var/energy_drain = 0
@@ -21,6 +22,7 @@
var/equip_type = null //mechaequip2
var/allow_duplicate = FALSE
var/ready_sound = 'sound/mecha/mech_reload_default.ogg' //Sound to play once the fire delay passed.
+ var/enable_special = FALSE // Will the tool do its special?
/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1)
sleep(equip_cooldown)
@@ -110,6 +112,15 @@
/obj/item/mecha_parts/mecha_equipment/proc/is_melee()
return range&MELEE
+/obj/item/mecha_parts/mecha_equipment/proc/enable_special_checks(atom/target)
+ if(ispath(required_type))
+ return istype(target, required_type)
+
+ for (var/path in required_type)
+ if (istype(target, path))
+ return 1
+
+ return 0
/obj/item/mecha_parts/mecha_equipment/proc/action_checks(atom/target)
if(!target)
@@ -176,6 +187,10 @@
M.equipment += src
chassis = M
src.loc = M
+
+ if(enable_special_checks(M))
+ enable_special = TRUE
+
M.log_message("[src] initialized.")
if(!M.selected)
M.selected = src
@@ -203,6 +218,7 @@
chassis.log_message("[src] removed from equipment.")
chassis = null
set_ready_state(1)
+ enable_special = FALSE
return
/obj/item/mecha_parts/mecha_equipment/Topic(href,href_list)
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index b621d97cba..189acaac62 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -8,11 +8,13 @@
energy_drain = 10
var/dam_force = 20
var/obj/mecha/working/ripley/cargo_holder
- required_type = /obj/mecha/working
+ required_type = list(/obj/mecha/working)
+ ready_sound = 'sound/mecha/gasdisconnected.ogg'
/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/attach(obj/mecha/M as obj)
..()
cargo_holder = M
+
return
/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target)
@@ -28,7 +30,48 @@
occupant_message("You can't load living things into the cargo compartment.")
return
if(O.anchored)
- occupant_message("[target] is firmly secured.")
+ if(enable_special)
+ if(istype(O, /obj/machinery/door/firedoor)) // I love doors.
+ var/obj/machinery/door/firedoor/FD = O
+ if(FD.blocked)
+ FD.visible_message("\The [chassis] begins prying on \the [FD]!")
+ if(do_after(chassis.occupant,10 SECONDS,FD))
+ playsound(FD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ FD.blocked = 0
+ FD.update_icon()
+ FD.open(1)
+ FD.visible_message("\The [chassis] tears \the [FD] open!")
+ else if(FD.density)
+ FD.visible_message("\The [chassis] begins forcing \the [FD] open!")
+ if(do_after(chassis.occupant, 5 SECONDS,FD))
+ playsound(FD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ FD.visible_message("\The [chassis] forces \the [FD] open!")
+ FD.open(1)
+ else
+ FD.visible_message("\The [chassis] forces \the [FD] closed!")
+ FD.close(1)
+ else if(istype(O, /obj/machinery/door/airlock)) // D o o r s.
+ var/obj/machinery/door/airlock/AD = O
+ if(AD.locked)
+ occupant_message("The airlock's bolts prevent it from being forced.")
+ else if(!AD.operating)
+ if(AD.welded)
+ AD.visible_message("\The [chassis] begins prying on \the [AD]!")
+ if(do_after(chassis.occupant, 15 SECONDS,AD) && chassis.Adjacent(AD))
+ AD.welded = FALSE
+ AD.update_icon()
+ playsound(AD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ AD.visible_message("\The [chassis] tears \the [AD] open!")
+ if(!AD.welded)
+ if(density)
+ spawn(0)
+ AD.open(1)
+ else
+ spawn(0)
+ AD.close(1)
+ return
+ else
+ occupant_message("[target] is firmly secured.")
return
if(cargo_holder.cargo.len >= cargo_holder.cargo_capacity)
occupant_message("Not enough room in cargo compartment.")
@@ -62,6 +105,15 @@
occupant_message("You squeeze [target] with [src.name]. Something cracks.")
playsound(src.loc, "fracture", 5, 1, -2) //CRACK
chassis.visible_message("[chassis] squeezes [target].")
+ else if(chassis.occupant.a_intent == I_DISARM && enable_special)
+ playsound(src.loc, 'sound/mecha/hydraulic.ogg', 10, 1, -2)
+ M.take_overall_damage(dam_force/2)
+ M.adjustOxyLoss(round(dam_force/3))
+ M.updatehealth()
+ occupant_message("You slam [target] with [src.name]. Something cracks.")
+ playsound(src.loc, "fracture", 3, 1, -2) //CRACK 2
+ chassis.visible_message("[chassis] slams [target].")
+ M.throw_at(get_step(M,get_dir(src, M)), 14, 1.5, chassis)
else
step_away(M,chassis)
occupant_message("You push [target] out of the way.")
@@ -73,12 +125,12 @@
/obj/item/mecha_parts/mecha_equipment/tool/drill
name = "drill"
- desc = "This is the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)"
+ desc = "This is the drill that'll pierce the heavens!"
icon_state = "mecha_drill"
equip_cooldown = 30
energy_drain = 10
force = 15
- required_type = list(/obj/mecha/working/ripley, /obj/mecha/combat)
+ required_type = list(/obj/mecha/working/ripley)
/obj/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target)
if(!action_checks(target)) return
@@ -101,9 +153,13 @@
log_message("Drilled through [target]")
target.ex_act(2)
else if(istype(target, /turf/simulated/mineral))
- for(var/turf/simulated/mineral/M in range(chassis,1))
- if(get_dir(chassis,M)&chassis.dir)
- M.GetDrilled()
+ if(enable_special)
+ for(var/turf/simulated/mineral/M in range(chassis,1))
+ if(get_dir(chassis,M)&chassis.dir)
+ M.GetDrilled()
+ else
+ var/turf/simulated/mineral/M1 = target
+ M1.GetDrilled()
log_message("Drilled through [target]")
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
@@ -125,7 +181,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
name = "diamond drill"
- desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)"
+ desc = "This is an upgraded version of the drill that'll pierce the heavens!"
icon_state = "mecha_diamond_drill"
origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
equip_cooldown = 10
@@ -150,9 +206,13 @@
log_message("Drilled through [target]")
target.ex_act(3)
else if(istype(target, /turf/simulated/mineral))
- for(var/turf/simulated/mineral/M in range(chassis,1))
- if(get_dir(chassis,M)&chassis.dir)
- M.GetDrilled()
+ if(enable_special)
+ for(var/turf/simulated/mineral/M in range(chassis,1))
+ if(get_dir(chassis,M)&chassis.dir)
+ M.GetDrilled()
+ else
+ var/turf/simulated/mineral/M1 = target
+ M1.GetDrilled()
log_message("Drilled through [target]")
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
@@ -165,6 +225,102 @@
target.ex_act(2)
return 1
+/obj/item/mecha_parts/mecha_equipment/tool/drill/bore
+ name = "depth bore"
+ desc = "This is the drill that'll pierce the depths!"
+ icon_state = "mecha_bore"
+ equip_cooldown = 5 SECONDS
+ energy_drain = 30
+ force = 20
+ required_type = list(/obj/mecha/working/ripley)
+
+/obj/item/mecha_parts/mecha_equipment/tool/drill/bore/action(atom/target)
+ if(!action_checks(target)) return
+ if(isobj(target))
+ var/obj/target_obj = target
+ if(target_obj.unacidable) return
+ set_ready_state(0)
+ chassis.use_power(energy_drain)
+ chassis.visible_message("[chassis] starts to bore into \the [target]", "You hear the bore.")
+ occupant_message("You start to bore into \the [target]")
+ var/T = chassis.loc
+ var/C = target.loc
+ if(do_after_cooldown(target))
+ if(T == chassis.loc && src == chassis.selected)
+ if(istype(target, /turf/simulated/wall))
+ var/turf/simulated/wall/W = target
+ if(W.reinf_material)
+ occupant_message("[target] is too durable to bore through.")
+ else
+ log_message("Bored through [target]")
+ target.ex_act(2)
+ else if(istype(target, /turf/simulated/mineral))
+ var/turf/simulated/mineral/M = target
+ if(enable_special && !M.density)
+ M.ex_act(2)
+ log_message("Bored into [target]")
+ else
+ M.GetDrilled()
+ log_message("Bored through [target]")
+ if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
+ var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
+ if(ore_box)
+ for(var/obj/item/weapon/ore/ore in range(chassis,1))
+ if(get_dir(chassis,ore)&chassis.dir)
+ ore.Move(ore_box)
+ if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
+ var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
+ if(ore_box)
+ for(var/obj/item/weapon/ore/ore in range(chassis,1))
+ if(get_dir(chassis,ore)&chassis.dir)
+ ore.Move(ore_box)
+ else if(target.loc == C)
+ log_message("Drilled through [target]")
+ target.ex_act(2)
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/tool/orescanner
+ name = "mounted ore scanner"
+ desc = "An exosuit-mounted ore scanner."
+ icon_state = "mecha_analyzer"
+ origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2, TECH_POWER = 2)
+ equip_cooldown = 5
+ energy_drain = 30
+ range = MELEE|RANGED
+ equip_type = EQUIP_SPECIAL
+ ready_sound = 'sound/items/goggles_charge.ogg'
+ required_type = list(/obj/mecha/working/ripley)
+
+ var/obj/item/weapon/mining_scanner/my_scanner = null
+ var/exact_scan = FALSE
+
+/obj/item/mecha_parts/mecha_equipment/tool/orescanner/Initialize()
+ my_scanner = new(src)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/orescanner/Destroy()
+ QDEL_NULL(my_scanner)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/orescanner/action(var/atom/target)
+ if(!action_checks(target) || get_dist(chassis, target) > 5)
+ return FALSE
+
+ if(!enable_special)
+ target = get_turf(chassis)
+
+ var/datum/beam/ScanBeam = chassis.Beam(target,"g_beam",'icons/effects/beam.dmi',time=2 SECONDS,10,/obj/effect/ebeam,2)
+
+ if(do_after(chassis.occupant, 2 SECONDS))
+ my_scanner.ScanTurf(target, chassis.occupant, exact_scan)
+
+ QDEL_NULL(ScanBeam)
+
+/obj/item/mecha_parts/mecha_equipment/tool/orescanner/advanced
+ name = "advanced ore scanner"
+ icon_state = "mecha_analyzer_adv"
+ exact_scan = TRUE
+
/obj/item/mecha_parts/mecha_equipment/tool/extinguisher
name = "extinguisher"
desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)"
@@ -235,6 +391,48 @@
/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/on_reagent_change()
return
+/obj/item/mecha_parts/mecha_equipment/tool/powertool
+ name = "pneumatic wrench"
+ desc = "An exosuit-mounted hydraulic wrench."
+ icon_state = "mecha_wrench"
+ origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2, TECH_POWER = 2)
+ equip_cooldown = 3
+ energy_drain = 15
+ range = MELEE
+ equip_type = EQUIP_UTILITY
+ ready_sound = 'sound/items/Ratchet.ogg'
+ required_type = list(/obj/mecha/working/ripley)
+
+ var/obj/item/my_tool = null
+ var/tooltype = /obj/item/weapon/tool/wrench/power
+
+/obj/item/mecha_parts/mecha_equipment/tool/powertool/Initialize()
+ my_tool = new tooltype(src)
+ my_tool.name = name
+ my_tool.anchored = TRUE
+ my_tool.canremove = FALSE
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/powertool/Destroy()
+ QDEL_NULL(my_tool)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/powertool/action(var/atom/target)
+ if(!action_checks(target))
+ return FALSE
+
+ if(isliving(target))
+ my_tool.attack(target, chassis.occupant, BP_TORSO)
+
+ target.attackby(my_tool,chassis.occupant)
+
+/obj/item/mecha_parts/mecha_equipment/tool/powertool/prybar
+ name = "pneumatic prybar"
+ desc = "An exosuit-mounted pneumatic prybar."
+ icon_state = "mecha_crowbar"
+ tooltype = /obj/item/weapon/tool/crowbar/power
+ ready_sound = 'sound/mecha/gasdisconnected.ogg'
+
/obj/item/mecha_parts/mecha_equipment/tool/rcd
name = "mounted RCD"
desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)"
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 86e3badc6f..43e7e0f90c 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -13,6 +13,10 @@
var/atom/target = null
var/open_panel = 0
var/image_overlay = null
+ var/blast_dev = -1
+ var/blast_heavy = -1
+ var/blast_light = 2
+ var/blast_flash = 3
/obj/item/weapon/plastique/New()
wires = new(src)
@@ -72,7 +76,7 @@
if(!target)
target = src
if(location)
- explosion(location, -1, -1, 2, 3)
+ explosion(location, blast_dev, blast_heavy, blast_light, blast_flash)
if(target)
if (istype(target, /turf/simulated/wall))
@@ -88,3 +92,11 @@
/obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone)
return
+
+/obj/item/weapon/plastique/seismic
+ name = "seismic charge"
+ desc = "Used to dig holes in specific areas without too much extra hole."
+
+ blast_heavy = 3
+ blast_light = 5
+ blast_flash = 8
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
index 7d725c36bb..625fb11e0c 100644
--- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
@@ -41,6 +41,19 @@
/obj/item/weapon/grenade/spawnergrenade/manhacks/raider
spawner_type = /mob/living/simple_mob/mechanical/viscerator/raider
+/obj/item/weapon/grenade/spawnergrenade/manhacks/station
+ desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones."
+ deliveryamt = 3
+ spawner_type = /mob/living/simple_mob/mechanical/viscerator/station
+ origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ILLEGAL = 1)
+
+/obj/item/weapon/grenade/spawnergrenade/ward
+ name = "sentry delivery grenade"
+ desc = "It is set to detonate in 5 seconds. It will deploy a single thermal-optic sentry drone."
+ spawner_type = /mob/living/simple_mob/mechanical/ward/monitor/crew
+ deliveryamt = 1
+ origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_BLUESPACE = 2)
+
/obj/item/weapon/grenade/spawnergrenade/spesscarp
name = "carp delivery grenade"
spawner_type = /mob/living/simple_mob/animal/space/carp
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 2230e14603..e0167527f0 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -200,6 +200,24 @@ BLIND // can't see anything
name = "prescription optical material scanner"
prescription = 1
+/obj/item/clothing/glasses/graviton
+ name = "graviton goggles"
+ desc = "The secrets of space travel are.. not quite yours."
+ icon_state = "grav"
+ item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses")
+ origin_tech = list(TECH_MAGNET = 2, TECH_BLUESPACE = 1)
+ darkness_view = 5
+ toggleable = 1
+ action_button_name = "Toggle Goggles"
+ off_state = "denight"
+ vision_flags = SEE_OBJS | SEE_TURFS
+ flash_protection = FLASH_PROTECTION_REDUCED
+ enables_planes = list(VIS_FULLBRIGHT, VIS_MESONS)
+
+/obj/item/clothing/glasses/graviton/New()
+ ..()
+ overlay = global_hud.material
+
/obj/item/clothing/glasses/regular
name = "prescription glasses"
desc = "Made by Nerd. Co."
diff --git a/code/modules/clothing/spacesuits/rig/modules/combat.dm b/code/modules/clothing/spacesuits/rig/modules/combat.dm
index 3e8cb36a6c..890da50468 100644
--- a/code/modules/clothing/spacesuits/rig/modules/combat.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/combat.dm
@@ -89,6 +89,19 @@
new_grenade.activate(H)
new_grenade.throw_at(target,fire_force,fire_distance)
+/obj/item/rig_module/grenade_launcher/smoke
+ name = "mounted smoke-bomb launcher"
+ desc = "A shoulder-mounted smoke-bomb dispenser."
+
+ interface_name = "integrated smoke-bomb launcher"
+ interface_desc = "Discharges loaded smoke-bombs against the wearer's location."
+
+ fire_force = 15
+
+ charges = list(
+ list("smoke bomb", "smoke bomb", /obj/item/weapon/grenade/smokebomb, 6)
+ )
+
/obj/item/rig_module/mounted
name = "mounted laser cannon"
diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm
index b5d58c8da6..704ed7a47b 100644
--- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm
@@ -192,8 +192,6 @@
smoke = null
return ..()
-
-
/obj/item/rig_module/self_destruct/activate()
return
diff --git a/code/modules/clothing/spacesuits/rig/modules/vision.dm b/code/modules/clothing/spacesuits/rig/modules/vision.dm
index 572f861d5a..57ad4026ef 100644
--- a/code/modules/clothing/spacesuits/rig/modules/vision.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/vision.dm
@@ -15,29 +15,40 @@
/datum/rig_vision/nvg
mode = "night vision"
+
/datum/rig_vision/nvg/New()
glasses = new /obj/item/clothing/glasses/night
/datum/rig_vision/thermal
mode = "thermal scanner"
+
/datum/rig_vision/thermal/New()
glasses = new /obj/item/clothing/glasses/thermal
/datum/rig_vision/meson
mode = "meson scanner"
+
/datum/rig_vision/meson/New()
glasses = new /obj/item/clothing/glasses/meson
/datum/rig_vision/sechud
mode = "security HUD"
+
/datum/rig_vision/sechud/New()
glasses = new /obj/item/clothing/glasses/hud/security
/datum/rig_vision/medhud
mode = "medical HUD"
+
/datum/rig_vision/medhud/New()
glasses = new /obj/item/clothing/glasses/hud/health
+/datum/rig_vision/material
+ mode = "material scanner"
+
+/datum/rig_vision/material/New()
+ glasses = new /obj/item/clothing/glasses/material
+
/obj/item/rig_module/vision
name = "hardsuit visor"
@@ -76,6 +87,7 @@
interface_desc = "An integrated multi-mode vision system."
vision_modes = list(/datum/rig_vision/meson,
+ /datum/rig_vision/material,
/datum/rig_vision/nvg,
/datum/rig_vision/thermal,
/datum/rig_vision/sechud,
@@ -94,6 +106,33 @@
vision_modes = list(/datum/rig_vision/meson)
+/obj/item/rig_module/vision/material
+
+ name = "hardsuit material scanner"
+ desc = "A layered, translucent visor system for a hardsuit."
+ icon_state = "meson"
+
+ usable = 0
+
+ interface_name = "material scanner"
+ interface_desc = "An integrated material scanner."
+
+ vision_modes = list(/datum/rig_vision/material)
+
+/obj/item/rig_module/vision/mining
+
+ name = "hardsuit mining scanners"
+ desc = "A layered, translucent visor system for a hardsuit."
+ icon_state = "optics"
+
+ usable = 0
+
+ interface_name = "mining scanners"
+ interface_desc = "An integrated mining scanner array."
+
+ vision_modes = list(/datum/rig_vision/material,
+ /datum/rig_vision/meson)
+
/obj/item/rig_module/vision/thermal
name = "hardsuit thermal scanner"
diff --git a/code/modules/mining/drilling/scanner.dm b/code/modules/mining/drilling/scanner.dm
index 56f371fe91..bbcc65cc16 100644
--- a/code/modules/mining/drilling/scanner.dm
+++ b/code/modules/mining/drilling/scanner.dm
@@ -6,14 +6,18 @@
item_state = "electronic"
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
matter = list(DEFAULT_WALL_MATERIAL = 150)
+ var/scan_time = 5 SECONDS
/obj/item/weapon/mining_scanner/attack_self(mob/user as mob)
user << "You begin sweeping \the [src] about, scanning for metal deposits."
playsound(loc, 'sound/items/goggles_charge.ogg', 50, 1, -6)
- if(!do_after(user, 50))
+ if(!do_after(user, scan_time))
return
+ ScanTurf(user, get_turf(user))
+
+/obj/item/weapon/mining_scanner/proc/ScanTurf(var/atom/target, var/mob/user, var/exact = FALSE)
var/list/metals = list(
"surface minerals" = 0,
"precious metals" = 0,
@@ -22,7 +26,9 @@
"anomalous matter" = 0
)
- for(var/turf/simulated/T in range(2, get_turf(user)))
+ var/turf/Turf = get_turf(target)
+
+ for(var/turf/simulated/T in range(2, Turf))
if(!T.has_resources)
continue
@@ -39,14 +45,18 @@
if(ore_type) metals[ore_type] += T.resources[metal]
- user << "\icon[src] The scanner beeps and displays a readout."
+ to_chat(user, "\icon[src] The scanner beeps and displays a readout.")
for(var/ore_type in metals)
var/result = "no sign"
- switch(metals[ore_type])
- if(1 to 25) result = "trace amounts"
- if(26 to 75) result = "significant amounts"
- if(76 to INFINITY) result = "huge quantities"
+ if(!exact)
+ switch(metals[ore_type])
+ if(1 to 25) result = "trace amounts"
+ if(26 to 75) result = "significant amounts"
+ if(76 to INFINITY) result = "huge quantities"
- user << "- [result] of [ore_type]."
\ No newline at end of file
+ else
+ result = metals[ore_type]
+
+ to_chat(user, "- [result] of [ore_type].")
diff --git a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm
index 2362586051..7f7b896345 100644
--- a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm
+++ b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm
@@ -19,21 +19,43 @@
new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 150),
new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 200),
new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 900),
+ new /datum/data/mining_equipment("Geiger Counter", /obj/item/device/geiger, 750),
new /datum/data/mining_equipment("Plush Toy", /obj/random/plushie, 300),
+ new /datum/data/mining_equipment("Umbrella", /obj/item/weapon/melee/umbrella/random, 200),
// new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 500),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
// new /datum/data/mining_equipment("Fulton Pack", /obj/item/extraction_pack, 1200),
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/weapon/pickaxe/silver, 1200),
-// new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c1000, 2000),
-// new /datum/data/mining_equipment("Industrial Hardsuit - Control Module", /obj/item/weapon/rig/industrial, 2000),
-// new /datum/data/mining_equipment("Industrial Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800),
-// new /datum/data/mining_equipment("Industrial Hardsuit - Drill", /obj/item/rig_module/device/drill, 2000),
-// new /datum/data/mining_equipment("Industrial Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000),
-// new /datum/data/mining_equipment("Industrial Hardsuit - Material Scanner", /obj/item/rig_module/vision/material, 500),
-// new /datum/data/mining_equipment("Industrial Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250),
-// new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
+ new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
new /datum/data/mining_equipment("Fishing Net", /obj/item/weapon/material/fishing_net, 500),
- new /datum/data/mining_equipment("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 1000)
+ new /datum/data/mining_equipment("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 1000),
+// new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c1000, 2000),
+ new /datum/data/mining_equipment("Industrial Hardsuit - Control Module", /obj/item/weapon/rig/industrial, 10000),
+ new /datum/data/mining_equipment("Industrial Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800),
+ new /datum/data/mining_equipment("Industrial Hardsuit - Drill", /obj/item/rig_module/device/drill, 2000),
+ new /datum/data/mining_equipment("Industrial Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000),
+ new /datum/data/mining_equipment("Industrial Hardsuit - Advanced Optics", /obj/item/rig_module/vision/mining, 1250),
+ new /datum/data/mining_equipment("Industrial Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250),
+ new /datum/data/mining_equipment("Hardsuit - Intelligence Storage", /obj/item/rig_module/ai_container, 2500),
+ new /datum/data/mining_equipment("Hardsuit - Smoke Bomb Deployer", /obj/item/rig_module/grenade_launcher/smoke, 2000),
+ new /datum/data/mining_equipment("Industrial Equipment - Sheet-Snatcher", /obj/item/weapon/gun/magnetic/matfed, 3000),
+ new /datum/data/mining_equipment("Industrial Equipment - Phoron Bore",/obj/item/weapon/storage/bag/sheetsnatcher, 500),
+ new /datum/data/mining_equipment("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 500),
+ new /datum/data/mining_equipment("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 1000),
+ new /datum/data/mining_equipment("Fine Excavation Kit - Chisels",/obj/item/weapon/storage/excavation, 500),
+ new /datum/data/mining_equipment("Fine Excavation Kit - Measuring Tape",/obj/item/device/measuring_tape, 125),
+ new /datum/data/mining_equipment("Fine Excavation Kit - Hand Pick",/obj/item/weapon/pickaxe/hand, 375),
+ new /datum/data/mining_equipment("Explosive Excavation Kit - Plastic Charge",/obj/item/weapon/plastique/seismic, 750),
+ new /datum/data/mining_equipment("Injector (L) - Glucose",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose, 500),
+ new /datum/data/mining_equipment("Injector (L) - Panacea",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity, 500),
+ new /datum/data/mining_equipment("Injector (L) - Trauma",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute, 500),
+ new /datum/data/mining_equipment("Nanopaste Tube", /obj/item/stack/nanopaste, 1000),
+ new /datum/data/mining_equipment("Misc: Graviton Visor", /obj/item/clothing/glasses/graviton, 1500),
+ new /datum/data/mining_equipment("Defense Equipment - Phase Pistol",/obj/item/weapon/gun/energy/phasegun/pistol, 400),
+ new /datum/data/mining_equipment("Defense Equipment - Smoke Bomb",/obj/item/weapon/grenade/smokebomb, 100),
+ new /datum/data/mining_equipment("Defense Equipment - Razor Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/manhacks/station, 1000),
+ new /datum/data/mining_equipment("Defense Equipment - Sentry Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/ward, 1500),
+ new /datum/data/mining_equipment("Defense Equipment - Steel Machete", /obj/item/weapon/material/knife/machete, 500)
)
/datum/data/mining_equipment
diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm
index 347e64c093..b7f552db51 100644
--- a/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm
@@ -63,4 +63,24 @@
. = ..()
if(!.) // Not friendly, see if they're a baddie first.
if(L.mind && raiders.is_antagonist(L.mind))
- return TRUE
\ No newline at end of file
+ return TRUE
+
+// Variant that is neutral, and thus on the station's side. It checks records.
+/mob/living/simple_mob/mechanical/viscerator/station
+ icon_state = "viscerator_b_attack"
+ icon_living = "viscerator_b_attack"
+
+ faction = "station"
+ maxHealth = 20
+ health = 20
+
+ melee_damage_lower = 2
+ melee_damage_upper = 5
+ base_attack_cooldown = 8
+
+/mob/living/simple_mob/mechanical/viscerator/station/IIsAlly(mob/living/L)
+ . = ..()
+ if(!.)
+ if(isrobot(L)) // They ignore synths.
+ return TRUE
+ return L.assess_perp(src, FALSE, FALSE, TRUE, FALSE) >= 4
diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm
index 519ad4ce88..fb6cbd2a5d 100644
--- a/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm
@@ -43,7 +43,20 @@
faction = "syndicate"
/mob/living/simple_mob/mechanical/ward/monitor/crew
- faction = "neutral"
+ icon_state = "ward-nt"
+
+/mob/living/simple_mob/mechanical/ward/monitor/crew/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(istype(O, /obj/item/weapon/card/id) && !owner)
+ owner = user
+ return
+ ..()
+
+/mob/living/simple_mob/mechanical/ward/monitor/crew/IIsAlly(mob/living/L)
+ . = ..()
+ if(!.)
+ if(isrobot(L)) // They ignore synths.
+ return TRUE
+ return L.assess_perp(src, FALSE, FALSE, TRUE, FALSE) >= 4
/mob/living/simple_mob/mechanical/ward/monitor/death()
if(owner)
@@ -55,10 +68,10 @@
/mob/living/simple_mob/mechanical/ward/monitor/update_icon()
if(seen_mobs.len)
- icon_living = "ward_spotted"
+ icon_living = "[initial(icon_state)]_spotted"
glow_color = "#FF0000"
else
- icon_living = "ward"
+ icon_living = "[initial(icon_state)]_ward"
glow_color = "#00FF00"
handle_light() // Update the light immediately.
..()
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 9073ead831..c892175c9a 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -63,7 +63,7 @@
icon_state = "emitter"
fire_sound = 'sound/weapons/emitter.ogg'
light_color = "#00CC33"
- excavation_amount = 70 // 3 shots to mine a turf
+ excavation_amount = 140 // 2 shots to dig a standard rock turf. Superior due to being a mounted tool beam, to make it actually viable.
muzzle_type = /obj/effect/projectile/muzzle/emitter
tracer_type = /obj/effect/projectile/tracer/emitter
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index 98d3500c6e..8a2e9796cd 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -136,7 +136,7 @@
if(isrobot(user))
return
- if(!I)
+ if(!I || I.anchored || !I.canremove)
return
user.drop_item()
diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm
index e67172fa94..436d5e85d9 100644
--- a/code/modules/research/mechfab_designs.dm
+++ b/code/modules/research/mechfab_designs.dm
@@ -616,6 +616,46 @@
materials = list(DEFAULT_WALL_MATERIAL = 7500, "diamond" = 4875)
build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
+/datum/design/item/mecha/ground_drill
+ name = "Surface Bore"
+ desc = "A heavy duty bore. Bigger, better, stronger than the core sampler, but not quite as good as a large drill."
+ id = "mech_ground_drill"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 2, TECH_PHORON = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 7000, "silver" = 3000, "phoron" = 2000)
+ build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/bore
+
+/datum/design/item/mecha/orescanner
+ name = "Ore Scanner"
+ desc = "A hefty device used to scan for subterranean veins of ore."
+ id = "mech_ore_scanner"
+ req_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 1000)
+ build_path = /obj/item/mecha_parts/mecha_equipment/tool/orescanner
+
+/datum/design/item/mecha/advorescanner
+ name = "Advanced Ore Scanner"
+ desc = "A hefty device used to scan for the exact volumes of subterranean veins of ore."
+ id = "mech_ore_scanner_adv"
+ req_tech = list(TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_POWER = 4, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "osmium" = 3000, "silver" = 1000)
+ build_path = /obj/item/mecha_parts/mecha_equipment/tool/orescanner/advanced
+
+/datum/design/item/mecha/powerwrench
+ name = "hydraulic wrench"
+ desc = "A large, hydraulic wrench."
+ id = "mech_wrench"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "plastic" = 2000, "glass" = 1250)
+ build_path = /obj/item/mecha_parts/mecha_equipment/tool/powertool
+
+/datum/design/item/mecha/powercrowbar
+ name = "hydraulic prybar"
+ desc = "A large, hydraulic prybar."
+ id = "mech_crowbar"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000, "osmium" = 3000, "glass" = 1000)
+ build_path = /obj/item/mecha_parts/mecha_equipment/tool/powertool/prybar
+
/datum/design/item/mecha/generator_nuclear
name = "Nuclear Reactor"
desc = "Exosuit-held nuclear reactor. Converts uranium and everyone's health to energy."
diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi
index 2b96c7d492..2f15024c6a 100644
Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ
diff --git a/icons/mob/critter.dmi b/icons/mob/critter.dmi
index 4f249e2e8a..7098d1a3a8 100644
Binary files a/icons/mob/critter.dmi and b/icons/mob/critter.dmi differ
diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi
index 85c5a39320..d2a5879eeb 100644
Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ
diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi
index d8418a50a5..da5436c8d7 100644
Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ