* [src.name] \[Toggle\]"
+
+/obj/item/mecha_parts/mecha_equipment/tool/jetpack/Topic(href,href_list)
+ ..()
+ if(href_list["toggle"])
+ toggle()
+
+/obj/item/mecha_parts/mecha_equipment/tool/jetpack/do_after_cooldown()
+ sleep(equip_cooldown)
+ wait = 0
+ return 1
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/orescanner.dm b/code/game/mecha/equipment/tools/orescanner.dm
new file mode 100644
index 0000000000..91027bd264
--- /dev/null
+++ b/code/game/mecha/equipment/tools/orescanner.dm
@@ -0,0 +1,41 @@
+/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
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/passenger.dm b/code/game/mecha/equipment/tools/passenger.dm
new file mode 100644
index 0000000000..1e40da2f30
--- /dev/null
+++ b/code/game/mecha/equipment/tools/passenger.dm
@@ -0,0 +1,151 @@
+/obj/item/mecha_parts/mecha_equipment/tool/passenger
+ name = "passenger compartment"
+ desc = "A mountable passenger compartment for exosuits. Rather cramped."
+ icon_state = "mecha_abooster_ccw"
+ origin_tech = list(TECH_ENGINEERING = 1, TECH_BIO = 1)
+ energy_drain = 10
+ range = MELEE
+ equip_cooldown = 20
+ var/mob/living/carbon/occupant = null
+ var/door_locked = 1
+ salvageable = 0
+ allow_duplicate = TRUE
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/destroy()
+ for(var/atom/movable/AM in src)
+ AM.forceMove(get_turf(src))
+ AM << "You tumble out of the destroyed [src.name]!"
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/Exit(atom/movable/O)
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/proc/move_inside(var/mob/user)
+ if (chassis)
+ chassis.visible_message("[user] starts to climb into [chassis].")
+
+ if(do_after(user, 40, needhand=0))
+ if(!src.occupant)
+ user.forceMove(src)
+ occupant = user
+ log_message("[user] boarded.")
+ occupant_message("[user] boarded.")
+ else if(src.occupant != user)
+ to_chat(user, "[src.occupant] was faster. Try harder next time, loser.")
+ else
+ to_chat(user, "You stop entering the exosuit.")
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/verb/eject()
+ set name = "Eject"
+ set category = "Exosuit Interface"
+ set src = usr.loc
+ set popup_menu = 0
+
+ if(usr != occupant)
+ return
+ to_chat(occupant, "You climb out from \the [src].")
+ go_out()
+ occupant_message("[occupant] disembarked.")
+ log_message("[occupant] disembarked.")
+ add_fingerprint(usr)
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/proc/go_out()
+ if(!occupant)
+ return
+ occupant.forceMove(get_turf(src))
+ occupant.reset_view()
+ /*
+ if(occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+ */
+ occupant = null
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/attach()
+ ..()
+ if (chassis)
+ chassis.verbs |= /obj/mecha/proc/move_inside_passenger
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/detach()
+ if(occupant)
+ occupant_message("Unable to detach [src] - equipment occupied.")
+ return
+
+ var/obj/mecha/M = chassis
+ ..()
+ if (M && !(locate(/obj/item/mecha_parts/mecha_equipment/tool/passenger) in M))
+ M.verbs -= /obj/mecha/proc/move_inside_passenger
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/get_equip_info()
+ return "[..()]
[occupant? "\[Occupant: [occupant]\]|" : ""]Exterior Hatch: Toggle Lock"
+
+/obj/item/mecha_parts/mecha_equipment/tool/passenger/Topic(href,href_list)
+ ..()
+ if (href_list["toggle_lock"])
+ door_locked = !door_locked
+ occupant_message("Passenger compartment hatch [door_locked? "locked" : "unlocked"].")
+ if (chassis)
+ chassis.visible_message("The hatch on \the [chassis] [door_locked? "locks" : "unlocks"].", "You hear something latching.")
+
+
+#define LOCKED 1
+#define OCCUPIED 2
+
+/obj/mecha/proc/move_inside_passenger()
+ set category = "Object"
+ set name = "Enter Passenger Compartment"
+ set src in oview(1)
+
+ //check that usr can climb in
+ if (usr.stat || !ishuman(usr))
+ return
+
+ if (!usr.Adjacent(src))
+ return
+
+ if (!isturf(usr.loc))
+ usr << "You can't reach the passenger compartment from here."
+ return
+
+ if(iscarbon(usr))
+ var/mob/living/carbon/C = usr
+ if(C.handcuffed)
+ usr << "Kinda hard to climb in while handcuffed don't you think?"
+ return
+
+ if(isliving(usr))
+ var/mob/living/L = usr
+ if(L.has_buckled_mobs())
+ to_chat(L, span("warning", "You have other entities attached to yourself. Remove them first."))
+ return
+
+ //search for a valid passenger compartment
+ var/feedback = 0 //for nicer user feedback
+ for(var/obj/item/mecha_parts/mecha_equipment/tool/passenger/P in src)
+ if (P.occupant)
+ feedback |= OCCUPIED
+ continue
+ if (P.door_locked)
+ feedback |= LOCKED
+ continue
+
+ //found a boardable compartment
+ P.move_inside(usr)
+ return
+
+ //didn't find anything
+ switch (feedback)
+ if (OCCUPIED)
+ usr << "The passenger compartment is already occupied!"
+ if (LOCKED)
+ usr << "The passenger compartment hatch is locked!"
+ if (OCCUPIED|LOCKED)
+ usr << "All of the passenger compartments are already occupied or locked!"
+ if (0)
+ usr << "\The [src] doesn't have a passenger compartment."
+
+#undef LOCKED
+#undef OCCUPIED
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/rcd.dm b/code/game/mecha/equipment/tools/rcd.dm
new file mode 100644
index 0000000000..9aa9a8bb40
--- /dev/null
+++ b/code/game/mecha/equipment/tools/rcd.dm
@@ -0,0 +1,45 @@
+/obj/item/mecha_parts/mecha_equipment/tool/rcd
+ name = "mounted RCD"
+ desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)"
+ icon_state = "mecha_rcd"
+ origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_POWER = 4)
+ equip_cooldown = 10
+ energy_drain = 250
+ range = MELEE|RANGED
+ equip_type = EQUIP_SPECIAL
+ var/obj/item/weapon/rcd/electric/mounted/mecha/my_rcd = null
+
+/obj/item/mecha_parts/mecha_equipment/tool/rcd/Initialize()
+ my_rcd = new(src)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/rcd/Destroy()
+ QDEL_NULL(my_rcd)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/rcd/action(atom/target)
+ if(!action_checks(target) || get_dist(chassis, target) > 3)
+ return FALSE
+
+ my_rcd.use_rcd(target, chassis.occupant)
+
+/obj/item/mecha_parts/mecha_equipment/tool/rcd/Topic(href,href_list)
+ ..()
+ if(href_list["mode"])
+ my_rcd.mode_index = text2num(href_list["mode"])
+ occupant_message("RCD reconfigured to '[my_rcd.modes[my_rcd.mode_index]]'.")
+/*
+/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info()
+ return "[..()] \[D|C|A\]"
+*/
+/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info()
+ var/list/content = list(..()) // This is all for one line, in the interest of string tree conservation.
+ var/i = 1
+ content += "
"
+ for(var/mode in my_rcd.modes)
+ content += " [mode]"
+ if(i < my_rcd.modes.len)
+ content += "
"
+ i++
+
+ return content.Join()
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/repair_droid.dm b/code/game/mecha/equipment/tools/repair_droid.dm
new file mode 100644
index 0000000000..f76eeed6f0
--- /dev/null
+++ b/code/game/mecha/equipment/tools/repair_droid.dm
@@ -0,0 +1,94 @@
+/obj/item/mecha_parts/mecha_equipment/repair_droid
+ name = "repair droid"
+ desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost any type of external or internal damage."
+ icon_state = "repair_droid"
+ origin_tech = list(TECH_MAGNET = 3, TECH_DATA = 3)
+ equip_cooldown = 20
+ energy_drain = 100
+ range = 0
+ var/health_boost = 2
+ var/datum/global_iterator/pr_repair_droid
+ var/icon/droid_overlay
+ var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH)
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/New()
+ ..()
+ pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0)
+ pr_repair_droid.set_delay(equip_cooldown)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy()
+ qdel(pr_repair_droid)
+ pr_repair_droid = null
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M as obj)
+ ..()
+ droid_overlay = new(src.icon, icon_state = "repair_droid")
+ M.overlays += droid_overlay
+ return
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/destroy()
+ chassis.overlays -= droid_overlay
+ ..()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
+ chassis.overlays -= droid_overlay
+ pr_repair_droid.stop()
+ ..()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info()
+ if(!chassis) return
+ return "* [src.name] - [pr_repair_droid.active()?"Dea":"A"]ctivate"
+
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list)
+ ..()
+ if(href_list["toggle_repairs"])
+ chassis.overlays -= droid_overlay
+ if(pr_repair_droid.toggle())
+ droid_overlay = new(src.icon, icon_state = "repair_droid_a")
+ log_message("Activated.")
+ else
+ droid_overlay = new(src.icon, icon_state = "repair_droid")
+ log_message("Deactivated.")
+ set_ready_state(1)
+ chassis.overlays += droid_overlay
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+ return
+
+
+/datum/global_iterator/mecha_repair_droid
+
+/datum/global_iterator/mecha_repair_droid/process(var/obj/item/mecha_parts/mecha_equipment/repair_droid/RD as obj)
+ if(!RD.chassis)
+ stop()
+ RD.set_ready_state(1)
+ return
+ var/health_boost = RD.health_boost
+ var/repaired = 0
+ if(RD.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
+ health_boost *= -2
+ else if(RD.chassis.hasInternalDamage() && prob(15))
+ for(var/int_dam_flag in RD.repairable_damage)
+ if(RD.chassis.hasInternalDamage(int_dam_flag))
+ RD.chassis.clearInternalDamage(int_dam_flag)
+ repaired = 1
+ break
+ if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health))
+ RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health)
+ repaired = 1
+ if(repaired)
+ if(RD.chassis.use_power(RD.energy_drain))
+ RD.set_ready_state(0)
+ else
+ stop()
+ RD.set_ready_state(1)
+ return
+ else
+ RD.set_ready_state(1)
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/shield.dm b/code/game/mecha/equipment/tools/shield.dm
new file mode 100644
index 0000000000..1ceab07945
--- /dev/null
+++ b/code/game/mecha/equipment/tools/shield.dm
@@ -0,0 +1,82 @@
+/obj/item/mecha_parts/mecha_equipment/combat_shield
+ name = "linear combat shield"
+ desc = "A shield generator that forms a rectangular, unidirectionally projectile-blocking wall in front of the exosuit."
+ icon_state = "shield"
+ origin_tech = list(TECH_PHORON = 3, TECH_MAGNET = 6, TECH_ILLEGAL = 4)
+ equip_cooldown = 5
+ energy_drain = 20
+ range = 0
+
+ var/obj/item/shield_projector/line/exosuit/my_shield = null
+ var/my_shield_type = /obj/item/shield_projector/line/exosuit
+ var/icon/drone_overlay
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/New()
+ ..()
+ my_shield = new my_shield_type
+ my_shield.shield_regen_delay = equip_cooldown
+ my_shield.my_tool = src
+ return
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/critfail()
+ ..()
+ my_shield.adjust_health(-200)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/Destroy()
+ chassis.overlays -= drone_overlay
+ my_shield.forceMove(src)
+ my_shield.destroy_shields()
+ my_shield.my_tool = null
+ my_shield.my_mecha = null
+ qdel(my_shield)
+ my_shield = null
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/attach(obj/mecha/M as obj)
+ ..()
+ if(chassis)
+ my_shield.shield_health = 0
+ my_shield.my_mecha = chassis
+ my_shield.forceMove(chassis)
+
+ drone_overlay = new(src.icon, icon_state = "shield_droid")
+ M.overlays += drone_overlay
+ return
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/detach()
+ chassis.overlays -= drone_overlay
+ ..()
+ my_shield.destroy_shields()
+ my_shield.my_mecha = null
+ my_shield.shield_health = my_shield.max_shield_health
+ my_shield.forceMove(src)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/handle_movement_action()
+ if(chassis)
+ my_shield.update_shield_positions()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/proc/toggle_shield()
+ ..()
+ if(chassis)
+ my_shield.attack_self(chassis.occupant)
+ if(my_shield.active)
+ set_ready_state(0)
+ log_message("Activated.")
+ else
+ set_ready_state(1)
+ log_message("Deactivated.")
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/Topic(href, href_list)
+ ..()
+ if(href_list["toggle_shield"])
+ toggle_shield()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/combat_shield/get_equip_info()
+ if(!chassis) return
+ return "* [src.name] - [my_shield.active?"Dea":"A"]ctivate"
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/sleeper.dm b/code/game/mecha/equipment/tools/sleeper.dm
new file mode 100644
index 0000000000..861471b6ce
--- /dev/null
+++ b/code/game/mecha/equipment/tools/sleeper.dm
@@ -0,0 +1,247 @@
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper
+ name = "mounted sleeper"
+ desc = "A sleeper. Mountable to an exosuit. (Can be attached to: Medical Exosuits)"
+ icon = 'icons/obj/Cryogenic2.dmi'
+ icon_state = "sleeper_0"
+ origin_tech = list(TECH_DATA = 2, TECH_BIO = 3)
+ energy_drain = 20
+ range = MELEE
+ equip_cooldown = 30
+ var/mob/living/carbon/human/occupant = null
+ var/datum/global_iterator/pr_mech_sleeper
+ var/inject_amount = 5
+ required_type = list(/obj/mecha/medical)
+ salvageable = 0
+ allow_duplicate = TRUE
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/New()
+ ..()
+ pr_mech_sleeper = new /datum/global_iterator/mech_sleeper(list(src),0)
+ pr_mech_sleeper.set_delay(equip_cooldown)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Destroy()
+ qdel(pr_mech_sleeper)
+ for(var/atom/movable/AM in src)
+ AM.forceMove(get_turf(src))
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Exit(atom/movable/O)
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/action(var/mob/living/carbon/human/target)
+ if(!action_checks(target))
+ return
+ if(!istype(target))
+ return
+ if(target.buckled)
+ occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled].")
+ return
+ if(occupant)
+ occupant_message("The sleeper is already occupied")
+ return
+ if(target.has_buckled_mobs())
+ occupant_message(span("warning", "\The [target] has other entities attached to it. Remove them first."))
+ return
+ occupant_message("You start putting [target] into [src].")
+ chassis.visible_message("[chassis] starts putting [target] into the [src].")
+ var/C = chassis.loc
+ var/T = target.loc
+ if(do_after_cooldown(target))
+ if(chassis.loc!=C || target.loc!=T)
+ return
+ if(occupant)
+ occupant_message("The sleeper is already occupied!")
+ return
+ target.forceMove(src)
+ occupant = target
+ target.reset_view(src)
+ occupant.Stasis(3)
+ /*
+ if(target.client)
+ target.client.perspective = EYE_PERSPECTIVE
+ target.client.eye = chassis
+ */
+ set_ready_state(0)
+ pr_mech_sleeper.start()
+ occupant_message("[target] successfully loaded into [src]. Life support functions engaged.")
+ chassis.visible_message("[chassis] loads [target] into [src].")
+ log_message("[target] loaded. Life support functions engaged.")
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/go_out()
+ if(!occupant)
+ return
+ occupant.forceMove(get_turf(src))
+ occupant_message("[occupant] ejected. Life support functions disabled.")
+ log_message("[occupant] ejected. Life support functions disabled.")
+ occupant.reset_view()
+ /*
+ if(occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+ */
+ occupant.Stasis(0)
+ occupant = null
+ pr_mech_sleeper.stop()
+ set_ready_state(1)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/detach()
+ if(occupant)
+ occupant_message("Unable to detach [src] - equipment occupied.")
+ return
+ pr_mech_sleeper.stop()
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/get_equip_info()
+ var/output = ..()
+ if(output)
+ var/temp = ""
+ if(occupant)
+ temp = "
\[Occupant: [occupant] (Health: [occupant.health]%)\]
View stats|Eject"
+ return "[output] [temp]"
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Topic(href,href_list)
+ ..()
+ var/datum/topic_input/top_filter = new /datum/topic_input(href,href_list)
+ if(top_filter.get("eject"))
+ go_out()
+ if(top_filter.get("view_stats"))
+ chassis.occupant << browse(get_occupant_stats(),"window=msleeper")
+ onclose(chassis.occupant, "msleeper")
+ return
+ if(top_filter.get("inject"))
+ inject_reagent(top_filter.getType("inject",/datum/reagent),top_filter.getObj("source"))
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_stats()
+ if(!occupant)
+ return
+ return {"
+
+ [occupant] statistics
+
+
+
+
+ Health statistics
+
+ [get_occupant_dam()]
+
+ Reagents in bloodstream
+
+ [get_occupant_reagents()]
+
+
+ [get_available_reagents()]
+
+
+ "}
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_dam()
+ var/t1
+ switch(occupant.stat)
+ if(0)
+ t1 = "Conscious"
+ if(1)
+ t1 = "Unconscious"
+ if(2)
+ t1 = "*dead*"
+ else
+ t1 = "Unknown"
+ return {"Health: [occupant.health]% ([t1])
+ Core Temperature: [src.occupant.bodytemperature-T0C]°C ([src.occupant.bodytemperature*1.8-459.67]°F)
+ Brute Damage: [occupant.getBruteLoss()]%
+ Respiratory Damage: [occupant.getOxyLoss()]%
+ Toxin Content: [occupant.getToxLoss()]%
+ Burn Severity: [occupant.getFireLoss()]%
+ "}
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_reagents()
+ if(occupant.reagents)
+ for(var/datum/reagent/R in occupant.reagents.reagent_list)
+ if(R.volume > 0)
+ . += "[R]: [round(R.volume,0.01)]
"
+ return . || "None"
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_available_reagents()
+ var/output
+ var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun) in chassis
+ if(SG && SG.reagents && islist(SG.reagents.reagent_list))
+ for(var/datum/reagent/R in SG.reagents.reagent_list)
+ if(R.volume > 0)
+ output += "Inject [R.name]
"
+ return output
+
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/inject_reagent(var/datum/reagent/R,var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG)
+ if(!R || !occupant || !SG || !(SG in chassis.equipment))
+ return 0
+ var/to_inject = min(R.volume, inject_amount)
+ if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject > inject_amount*4)
+ occupant_message("Sleeper safeties prohibit you from injecting more than [inject_amount*4] units of [R.name].")
+ else
+ occupant_message("Injecting [occupant] with [to_inject] units of [R.name].")
+ log_message("Injecting [occupant] with [to_inject] units of [R.name].")
+ //SG.reagents.trans_id_to(occupant,R.id,to_inject)
+ SG.reagents.remove_reagent(R.id,to_inject)
+ occupant.reagents.add_reagent(R.id,to_inject)
+ update_equip_info()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/update_equip_info()
+ if(..())
+ send_byjax(chassis.occupant,"msleeper.browser","lossinfo",get_occupant_dam())
+ send_byjax(chassis.occupant,"msleeper.browser","reagents",get_occupant_reagents())
+ send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents())
+ return 1
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/sleeper/verb/eject()
+ set name = "Sleeper Eject"
+ set category = "Exosuit Interface"
+ set src = usr.loc
+ set popup_menu = 0
+ if(usr!=src.occupant || usr.stat == 2)
+ return
+ to_chat(usr,"Release sequence activated. This will take one minute.")
+ sleep(600)
+ if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already
+ return
+ go_out()//and release him from the eternal prison.
+
+/datum/global_iterator/mech_sleeper
+
+/datum/global_iterator/mech_sleeper/process(var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S)
+ if(!S.chassis)
+ S.set_ready_state(1)
+ return stop()
+ if(!S.chassis.has_charge(S.energy_drain))
+ S.set_ready_state(1)
+ S.log_message("Deactivated.")
+ S.occupant_message("[src] deactivated - no power.")
+ return stop()
+ var/mob/living/carbon/M = S.occupant
+ if(!M)
+ return
+ if(M.health > 0)
+ M.adjustOxyLoss(-1)
+ M.updatehealth()
+ M.AdjustStunned(-4)
+ M.AdjustWeakened(-4)
+ M.AdjustStunned(-4)
+ M.Paralyse(2)
+ M.Weaken(2)
+ M.Stun(2)
+ if(M.reagents.get_reagent_amount("inaprovaline") < 5)
+ M.reagents.add_reagent("inaprovaline", 5)
+ S.chassis.use_power(S.energy_drain)
+ S.update_equip_info()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/speedboost.dm b/code/game/mecha/equipment/tools/speedboost.dm
new file mode 100644
index 0000000000..1cb0df9469
--- /dev/null
+++ b/code/game/mecha/equipment/tools/speedboost.dm
@@ -0,0 +1,21 @@
+/obj/item/mecha_parts/mecha_equipment/speedboost
+ name = "ripley leg actuator overdrive"
+ desc = "System enhancements and overdrives to make a ripley's legs move faster."
+ icon_state = "tesla"
+ origin_tech = list( TECH_POWER = 5, TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
+ required_type = list(/obj/mecha/working/ripley)
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/speedboost/attach(obj/mecha/M as obj)
+ ..()
+ if(enable_special)
+ chassis.step_in = (chassis.step_in-2) // Make the ripley as fast as a durand
+ else
+ chassis.step_in = (chassis.step_in+1) // Improper parts slow the mech down
+ return
+
+/obj/item/mecha_parts/mecha_equipment/speedboost/detach()
+ chassis.step_in = initial(chassis.step_in)
+ ..()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/syringe_gun.dm
similarity index 60%
rename from code/game/mecha/equipment/tools/medical_tools.dm
rename to code/game/mecha/equipment/tools/syringe_gun.dm
index 9f1e522733..31206d7640 100644
--- a/code/game/mecha/equipment/tools/medical_tools.dm
+++ b/code/game/mecha/equipment/tools/syringe_gun.dm
@@ -1,3 +1,4 @@
+<<<<<<< HEAD:code/game/mecha/equipment/tools/medical_tools.dm
/obj/item/mecha_parts/mecha_equipment/tool/sleeper
name = "mounted sleeper"
desc = "A sleeper. Mountable to an exosuit. (Can be attached to: Medical Exosuits)"
@@ -803,3 +804,509 @@
required_type = list(/obj/mecha/medical)
tooltype = /obj/item/device/healthanalyzer/advanced
+=======
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
+ name = "syringe gun"
+ desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)"
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "syringegun"
+ var/list/syringes
+ var/list/known_reagents
+ var/list/processed_reagents
+ var/max_syringes = 10
+ var/max_volume = 75 //max reagent volume
+ var/synth_speed = 5 //[num] reagent units per cycle
+ energy_drain = 10
+ var/mode = 0 //0 - fire syringe, 1 - analyze reagents.
+ var/datum/global_iterator/mech_synth/synth
+ range = MELEE|RANGED
+ equip_cooldown = 10
+ origin_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4, TECH_MAGNET = 4, TECH_DATA = 3)
+ required_type = list(/obj/mecha/medical)
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/New()
+ ..()
+ flags |= NOREACT
+ syringes = new
+ known_reagents = list("inaprovaline"="Inaprovaline","anti_toxin"="Dylovene")
+ processed_reagents = new
+ create_reagents(max_volume)
+ synth = new (list(src),0)
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/detach()
+ synth.stop()
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/critfail()
+ ..()
+ flags &= ~NOREACT
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/get_equip_info()
+ var/output = ..()
+ if(output)
+ return "[output] \[[mode? "Analyze" : "Launch"]\]
\[Syringes: [syringes.len]/[max_syringes] | Reagents: [reagents.total_volume]/[reagents.maximum_volume]\]
Reagents list"
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/action(atom/movable/target)
+ if(!action_checks(target))
+ return
+ if(istype(target,/obj/item/weapon/reagent_containers/syringe))
+ return load_syringe(target)
+ if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes
+ for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents)
+ load_syringe(S)
+ return
+ if(mode)
+ return analyze_reagents(target)
+ if(!syringes.len)
+ occupant_message("No syringes loaded.")
+ return
+ if(reagents.total_volume<=0)
+ occupant_message("No available reagents to load syringe with.")
+ return
+ set_ready_state(0)
+ chassis.use_power(energy_drain)
+ var/turf/trg = get_turf(target)
+ var/obj/item/weapon/reagent_containers/syringe/S = syringes[1]
+ S.forceMove(get_turf(chassis))
+ reagents.trans_to_obj(S, min(S.volume, reagents.total_volume))
+ syringes -= S
+ S.icon = 'icons/obj/chemical.dmi'
+ S.icon_state = "syringeproj"
+ playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
+ log_message("Launched [S] from [src], targeting [target].")
+ spawn(-1)
+ src = null //if src is deleted, still process the syringe
+ for(var/i=0, i<6, i++)
+ if(!S)
+ break
+ if(step_towards(S,trg))
+ var/list/mobs = new
+ for(var/mob/living/carbon/M in S.loc)
+ mobs += M
+ var/mob/living/carbon/M = safepick(mobs)
+ if(M)
+ S.icon_state = initial(S.icon_state)
+ S.icon = initial(S.icon)
+ S.reagents.trans_to_mob(M, S.reagents.total_volume, CHEM_BLOOD)
+ M.take_organ_damage(2)
+ S.visible_message(" [M] was hit by the syringe!")
+ break
+ else if(S.loc == trg)
+ S.icon_state = initial(S.icon_state)
+ S.icon = initial(S.icon)
+ S.update_icon()
+ break
+ else
+ S.icon_state = initial(S.icon_state)
+ S.icon = initial(S.icon)
+ S.update_icon()
+ break
+ sleep(1)
+ do_after_cooldown()
+ return 1
+
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/Topic(href,href_list)
+ ..()
+ var/datum/topic_input/top_filter = new (href,href_list)
+ if(top_filter.get("toggle_mode"))
+ mode = !mode
+ update_equip_info()
+ return
+ if(top_filter.get("select_reagents"))
+ processed_reagents.len = 0
+ var/m = 0
+ var/message
+ for(var/i=1 to known_reagents.len)
+ if(m>=synth_speed)
+ break
+ var/reagent = top_filter.get("reagent_[i]")
+ if(reagent && (reagent in known_reagents))
+ message = "[m ? ", " : null][known_reagents[reagent]]"
+ processed_reagents += reagent
+ m++
+ if(processed_reagents.len)
+ message += " added to production"
+ synth.start()
+ occupant_message(message)
+ occupant_message("Reagent processing started.")
+ log_message("Reagent processing started.")
+ return
+ if(top_filter.get("show_reagents"))
+ chassis.occupant << browse(get_reagents_page(),"window=msyringegun")
+ if(top_filter.get("purge_reagent"))
+ var/reagent = top_filter.get("purge_reagent")
+ if(reagent)
+ reagents.del_reagent(reagent)
+ return
+ if(top_filter.get("purge_all"))
+ reagents.clear_reagents()
+ return
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_page()
+ var/output = {"
+
+ Reagent Synthesizer
+
+
+
+
+ Current reagents:
+
+ [get_current_reagents()]
+
+ Reagents production:
+
+ [get_reagents_form()]
+
+
+
+ "}
+ return output
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_form()
+ var/r_list = get_reagents_list()
+ var/inputs
+ if(r_list)
+ inputs += ""
+ inputs += ""
+ inputs += ""
+ var/output = {"
+ [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null]
+ "}
+ return output
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_list()
+ var/output
+ for(var/i=1 to known_reagents.len)
+ var/reagent_id = known_reagents[i]
+ output += {" [known_reagents[reagent_id]]
"}
+ return output
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_current_reagents()
+ var/output
+ for(var/datum/reagent/R in reagents.reagent_list)
+ if(R.volume > 0)
+ output += "[R]: [round(R.volume,0.001)] - Purge Reagent
"
+ if(output)
+ output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All"
+ return output || "None"
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S)
+ if(syringes.len= 2)
+ occupant_message("The syringe is too far away.")
+ return 0
+ for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows)
+ if(!(D.CanPass(S,src.loc)))
+ occupant_message("Unable to load syringe.")
+ return 0
+ for(var/obj/machinery/door/D in S.loc)//Checks for doors
+ if(!(D.CanPass(S,src.loc)))
+ occupant_message("Unable to load syringe.")
+ return 0
+ S.reagents.trans_to_obj(src, S.reagents.total_volume)
+ S.forceMove(src)
+ syringes += S
+ occupant_message("Syringe loaded.")
+ update_equip_info()
+ return 1
+ occupant_message("The [src] syringe chamber is full.")
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/analyze_reagents(atom/A)
+ if(get_dist(src,A) >= 4)
+ occupant_message("The object is too far away.")
+ return 0
+ if(!A.reagents || istype(A,/mob))
+ occupant_message("No reagent info gained from [A].")
+ return 0
+ occupant_message("Analyzing reagents...")
+ for(var/datum/reagent/R in A.reagents.reagent_list)
+ if(R.reagent_state == 2 && add_known_reagent(R.id,R.name))
+ occupant_message("Reagent analyzed, identified as [R.name] and added to database.")
+ send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form())
+ occupant_message("Analysis complete.")
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/add_known_reagent(r_id,r_name)
+ set_ready_state(0)
+ do_after_cooldown()
+ if(!(r_id in known_reagents))
+ known_reagents += r_id
+ known_reagents[r_id] = r_name
+ return 1
+ return 0
+
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/update_equip_info()
+ if(..())
+ send_byjax(chassis.occupant,"msyringegun.browser","reagents",get_current_reagents())
+ send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form())
+ return 1
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/on_reagent_change()
+ ..()
+ update_equip_info()
+ return
+
+/datum/global_iterator/mech_synth
+ delay = 100
+
+/datum/global_iterator/mech_synth/process(var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/S)
+ if(!S.chassis)
+ return stop()
+ var/energy_drain = S.energy_drain*10
+ if(!S.processed_reagents.len || S.reagents.total_volume >= S.reagents.maximum_volume || !S.chassis.has_charge(energy_drain))
+ S.occupant_message("Reagent processing stopped.")
+ S.log_message("Reagent processing stopped.")
+ return stop()
+ var/amount = S.synth_speed / S.processed_reagents.len
+ for(var/reagent in S.processed_reagents)
+ S.reagents.add_reagent(reagent,amount)
+ S.chassis.use_power(energy_drain)
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone
+ name = "crisis dronebay"
+ desc = "A small shoulder-mounted dronebay containing a rapid response drone capable of moderately stabilizing a patient near the exosuit."
+ icon_state = "mecha_dronebay"
+ origin_tech = list(TECH_PHORON = 3, TECH_MAGNET = 6, TECH_BIO = 5, TECH_DATA = 4)
+ range = MELEE|RANGED
+ equip_cooldown = 3 SECONDS
+ required_type = list(/obj/mecha/medical)
+
+ var/droid_state = "med_droid"
+
+ var/beam_state = "medbeam"
+
+ var/enabled = FALSE
+
+ var/icon/drone_overlay
+
+ var/max_distance = 3
+
+ var/damcap = 60
+ var/heal_dead = FALSE // Does this device heal the dead?
+
+ var/brute_heal = 0.5 // Amount of bruteloss healed.
+ var/burn_heal = 0.5 // Amount of fireloss healed.
+ var/tox_heal = 0.5 // Amount of toxloss healed.
+ var/oxy_heal = 1 // Amount of oxyloss healed.
+ var/rad_heal = 0 // Amount of radiation healed.
+ var/clone_heal = 0 // Amount of cloneloss healed.
+ var/hal_heal = 0.2 // Amount of halloss healed.
+ var/bone_heal = 0 // Percent chance it will heal a broken bone. this does not mean 'make it not instantly re-break'.
+
+ var/mob/living/Target = null
+ var/datum/beam/MyBeam = null
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/Initialize()
+ ..()
+ drone_overlay = new(src.icon, icon_state = droid_state)
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/attach(obj/mecha/M as obj)
+ . = ..(M)
+ if(chassis)
+ START_PROCESSING(SSobj, src)
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/detach(atom/moveto=null)
+ shut_down()
+ . = ..(moveto)
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/critfail()
+ . = ..()
+ STOP_PROCESSING(SSobj, src)
+ shut_down()
+ if(chassis && chassis.occupant)
+ to_chat(chassis.occupant, "\The [chassis] shudders as something jams!")
+ log_message("[src.name] has malfunctioned. Maintenance required.")
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/process() // Will continually try to find the nearest person above the threshold that is a valid target, and try to heal them.
+ if(chassis && enabled && chassis.has_charge(energy_drain) && (chassis.occupant || enable_special))
+ var/mob/living/Targ = Target
+ var/TargDamage = 0
+
+ if(!valid_target(Target))
+ Target = null
+
+ if(Target)
+ TargDamage = (Targ.getOxyLoss() + Targ.getFireLoss() + Targ.getBruteLoss() + Targ.getToxLoss())
+
+ for(var/mob/living/Potential in viewers(max_distance, chassis))
+ if(!valid_target(Potential))
+ continue
+
+ var/tallydamage = 0
+ if(oxy_heal)
+ tallydamage += Potential.getOxyLoss()
+ if(burn_heal)
+ tallydamage += Potential.getFireLoss()
+ if(brute_heal)
+ tallydamage += Potential.getBruteLoss()
+ if(tox_heal)
+ tallydamage += Potential.getToxLoss()
+ if(hal_heal)
+ tallydamage += Potential.getHalLoss()
+ if(clone_heal)
+ tallydamage += Potential.getCloneLoss()
+ if(rad_heal)
+ tallydamage += Potential.radiation / 2
+
+ if(tallydamage > TargDamage)
+ Target = Potential
+
+ if(MyBeam && !valid_target(MyBeam.target))
+ QDEL_NULL(MyBeam)
+
+ if(Target)
+ if(MyBeam && MyBeam.target != Target)
+ QDEL_NULL(MyBeam)
+
+ if(valid_target(Target))
+ if(!MyBeam)
+ MyBeam = chassis.Beam(Target,icon='icons/effects/beam.dmi',icon_state=beam_state,time=3 SECONDS,maxdistance=max_distance,beam_type = /obj/effect/ebeam,beam_sleep_time=2)
+ heal_target(Target)
+
+ else
+ shut_down()
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/proc/valid_target(var/mob/living/L)
+ . = TRUE
+
+ if(!L || !istype(L))
+ return FALSE
+
+ if(get_dist(L, src) > max_distance)
+ return FALSE
+
+ if(!(L in viewers(max_distance, chassis)))
+ return FALSE
+
+ if(!unique_patient_checks(L))
+ return FALSE
+
+ if(L.stat == DEAD && !heal_dead)
+ return FALSE
+
+ var/tallydamage = 0
+ if(oxy_heal)
+ tallydamage += L.getOxyLoss()
+ if(burn_heal)
+ tallydamage += L.getFireLoss()
+ if(brute_heal)
+ tallydamage += L.getBruteLoss()
+ if(tox_heal)
+ tallydamage += L.getToxLoss()
+ if(hal_heal)
+ tallydamage += L.getHalLoss()
+ if(clone_heal)
+ tallydamage += L.getCloneLoss()
+ if(rad_heal)
+ tallydamage += L.radiation / 2
+
+ if(tallydamage < damcap)
+ return FALSE
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/proc/shut_down()
+ if(enabled)
+ chassis.visible_message("\The [chassis]'s [src] buzzes as its drone returns to port.")
+ toggle_drone()
+ if(!isnull(Target))
+ Target = null
+ if(MyBeam)
+ QDEL_NULL(MyBeam)
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/proc/unique_patient_checks(var/mob/living/L) // Anything special for subtypes. Does it only work on Robots? Fleshies? A species?
+ . = TRUE
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/proc/heal_target(var/mob/living/L) // We've done all our special checks, just get to fixing damage.
+ chassis.use_power(energy_drain)
+ if(istype(L))
+ L.adjustBruteLoss(brute_heal * -1)
+ L.adjustFireLoss(burn_heal * -1)
+ L.adjustToxLoss(tox_heal * -1)
+ L.adjustOxyLoss(oxy_heal * -1)
+ L.adjustCloneLoss(clone_heal * -1)
+ L.adjustHalLoss(hal_heal * -1)
+ L.radiation = max(0, L.radiation - rad_heal)
+
+ if(ishuman(L) && bone_heal)
+ var/mob/living/carbon/human/H = L
+
+ if(H.bad_external_organs.len)
+ for(var/obj/item/organ/external/E in H.bad_external_organs)
+ if(prob(bone_heal))
+ E.status &= ~ORGAN_BROKEN
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/proc/toggle_drone()
+ ..()
+ if(chassis)
+ enabled = !enabled
+ if(enabled)
+ set_ready_state(0)
+ log_message("Activated.")
+ chassis.overlays += drone_overlay
+ else
+ set_ready_state(1)
+ log_message("Deactivated.")
+ chassis.overlays -= drone_overlay
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/Topic(href, href_list)
+ ..()
+ if(href_list["toggle_drone"])
+ toggle_drone()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/get_equip_info()
+ if(!chassis) return
+ return "* [src.name] - [enabled?"Dea":"A"]ctivate"
+
+/obj/item/mecha_parts/mecha_equipment/crisis_drone/rad
+ name = "hazmat dronebay"
+ desc = "A small shoulder-mounted dronebay containing a rapid response drone capable of purging a patient near the exosuit of radiation damage."
+ icon_state = "mecha_dronebay_rad"
+
+ droid_state = "rad_drone"
+ beam_state = "g_beam"
+
+ tox_heal = 0.5
+ rad_heal = 5
+ clone_heal = 0.2
+ hal_heal = 0.2
+
+/obj/item/mecha_parts/mecha_equipment/tool/powertool/medanalyzer
+ name = "mounted humanoid scanner"
+ desc = "An exosuit-mounted scanning device."
+ icon_state = "mecha_analyzer_health"
+ origin_tech = list(TECH_MATERIAL = 5, TECH_MAGNET = 5, TECH_BIO = 5)
+ equip_cooldown = 5 SECONDS
+ energy_drain = 100
+ range = MELEE
+ equip_type = EQUIP_UTILITY
+ ready_sound = 'sound/weapons/flash.ogg'
+ required_type = list(/obj/mecha/medical)
+
+ tooltype = /obj/item/device/healthanalyzer/advanced
+>>>>>>> e749b79... Fixes mech projectile armor thinking test projectiles are dangerous (#6480):code/game/mecha/equipment/tools/syringe_gun.dm
diff --git a/code/game/mecha/equipment/tools/teleporter.dm b/code/game/mecha/equipment/tools/teleporter.dm
new file mode 100644
index 0000000000..b77b1c3fdc
--- /dev/null
+++ b/code/game/mecha/equipment/tools/teleporter.dm
@@ -0,0 +1,20 @@
+/obj/item/mecha_parts/mecha_equipment/teleporter
+ name = "teleporter"
+ desc = "An exosuit module that allows exosuits to teleport to any position in view."
+ icon_state = "mecha_teleport"
+ origin_tech = list(TECH_BLUESPACE = 10)
+ equip_cooldown = 150
+ energy_drain = 1000
+ range = RANGED
+
+ equip_type = EQUIP_SPECIAL
+
+/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target)
+ if(!action_checks(target) || src.loc.z == 2) return
+ var/turf/T = get_turf(target)
+ if(T)
+ set_ready_state(0)
+ chassis.use_power(energy_drain)
+ do_teleport(chassis, T, 4)
+ do_after_cooldown()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index 73f7356ade..01aeca691d 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -1,1668 +1,2 @@
/obj/item/mecha_parts/mecha_equipment/tool
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp
- name = "hydraulic clamp"
- icon_state = "mecha_clamp"
- equip_cooldown = 15
- energy_drain = 10
- var/dam_force = 20
- var/obj/mecha/working/ripley/cargo_holder
- 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)
- if(!action_checks(target)) return
- if(!cargo_holder) return
-
- //loading
- if(istype(target,/obj))
- var/obj/O = target
- if(O.has_buckled_mobs())
- return
- if(locate(/mob/living) in O)
- occupant_message("You can't load living things into the cargo compartment.")
- return
- if(O.anchored)
- 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.")
- return
-
- occupant_message("You lift [target] and start to load it into cargo compartment.")
- chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- O.anchored = 1
- var/T = chassis.loc
- if(do_after_cooldown(target))
- if(T == chassis.loc && src == chassis.selected)
- cargo_holder.cargo += O
- O.loc = chassis
- O.anchored = 0
- occupant_message("[target] succesfully loaded.")
- log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
- else
- occupant_message("You must hold still while handling objects.")
- O.anchored = initial(O.anchored)
-
- //attacking
- else if(istype(target,/mob/living))
- var/mob/living/M = target
- if(M.stat>1) return
- if(chassis.occupant.a_intent == I_HURT || istype(chassis.occupant,/mob/living/carbon/brain)) //No tactile feedback for brains
- M.take_overall_damage(dam_force)
- M.adjustOxyLoss(round(dam_force/2))
- M.updatehealth()
- 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.")
- chassis.visible_message("[chassis] pushes [target] out of the way.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill
- name = "drill"
- 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/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target)
- if(!action_checks(target)) return
- if(isobj(target))
- var/obj/target_obj = target
- if(!target_obj.vars.Find("unacidable") || target_obj.unacidable) return
- set_ready_state(0)
- chassis.use_power(energy_drain)
- chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.")
- occupant_message("You start to drill [target]")
- var/T = chassis.loc
- var/C = target.loc //why are these backwards? we may never know -Pete
- 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 drill through.")
- else
- log_message("Drilled through [target]")
- target.ex_act(2)
- else if(istype(target, /turf/simulated/mineral))
- 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
- if(ore_box)
- for(var/obj/item/weapon/ore/ore in range(chassis,1))
- if(get_dir(chassis,ore)&chassis.dir)
- ore.forceMove(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/drill/diamonddrill
- name = "diamond drill"
- 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
- force = 15
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/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 drill [target]", "You hear the drill.")
- occupant_message("You start to drill [target]")
- var/T = chassis.loc
- var/C = target.loc //why are these backwards? we may never know -Pete
- 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 || do_after_cooldown(target))//To slow down how fast mechs can drill through the station
- log_message("Drilled through [target]")
- target.ex_act(3)
- else if(istype(target, /turf/simulated/mineral))
- 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
- if(ore_box)
- for(var/obj/item/weapon/ore/ore in range(chassis,1))
- if(get_dir(chassis,ore)&chassis.dir)
- ore.forceMove(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/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.forceMove(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)"
- icon_state = "mecha_exting"
- equip_cooldown = 5
- energy_drain = 0
- range = MELEE|RANGED
- required_type = list(/obj/mecha/working)
- var/spray_particles = 5
- var/spray_amount = 5 //units of liquid per particle. 5 is enough to wet the floor - it's a big fire extinguisher, so should be fine
- var/max_water = 1000
-
-/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/Initialize()
- . = ..()
- reagents = new/datum/reagents(max_water)
- reagents.my_atom = src
- reagents.add_reagent("water", max_water)
-
-/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch.
- if(!action_checks(target) || get_dist(chassis, target)>3) return
- if(get_dist(chassis, target)>2) return
- set_ready_state(0)
- if(do_after_cooldown(target))
- if( istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1)
- var/obj/o = target
- var/amount = o.reagents.trans_to_obj(src, 200)
- occupant_message("[amount] units transferred into internal tank.")
- playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6)
- return
-
- if (src.reagents.total_volume < 1)
- occupant_message("\The [src] is empty.")
- return
-
- playsound(chassis, 'sound/effects/extinguish.ogg', 75, 1, -3)
-
- var/direction = get_dir(chassis,target)
-
- var/turf/T = get_turf(target)
- var/turf/T1 = get_step(T,turn(direction, 90))
- var/turf/T2 = get_step(T,turn(direction, -90))
-
- var/list/the_targets = list(T,T1,T2)
-
- for(var/a = 1 to 5)
- spawn(0)
- var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(chassis))
- var/turf/my_target
- if(a == 1)
- my_target = T
- else if(a == 2)
- my_target = T1
- else if(a == 3)
- my_target = T2
- else
- my_target = pick(the_targets)
- W.create_reagents(5)
- if(!W || !src)
- return
- reagents.trans_to_obj(W, spray_amount)
- W.set_color()
- W.set_up(my_target)
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/get_equip_info()
- return "[..()] \[[src.reagents.total_volume]\]"
-
-/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)"
- icon_state = "mecha_rcd"
- origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_POWER = 4)
- equip_cooldown = 10
- energy_drain = 250
- range = MELEE|RANGED
- equip_type = EQUIP_SPECIAL
- var/obj/item/weapon/rcd/electric/mounted/mecha/my_rcd = null
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/Initialize()
- my_rcd = new(src)
- return ..()
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/Destroy()
- QDEL_NULL(my_rcd)
- return ..()
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/action(atom/target)
- if(!action_checks(target) || get_dist(chassis, target) > 3)
- return FALSE
-
- my_rcd.use_rcd(target, chassis.occupant)
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/Topic(href,href_list)
- ..()
- if(href_list["mode"])
- my_rcd.mode_index = text2num(href_list["mode"])
- occupant_message("RCD reconfigured to '[my_rcd.modes[my_rcd.mode_index]]'.")
-/*
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info()
- return "[..()] \[D|C|A\]"
-*/
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info()
- var/list/content = list(..()) // This is all for one line, in the interest of string tree conservation.
- var/i = 1
- content += "
"
- for(var/mode in my_rcd.modes)
- content += " [mode]"
- if(i < my_rcd.modes.len)
- content += "
"
- i++
-
- return content.Join()
-
-
-/obj/item/mecha_parts/mecha_equipment/teleporter
- name = "teleporter"
- desc = "An exosuit module that allows exosuits to teleport to any position in view."
- icon_state = "mecha_teleport"
- origin_tech = list(TECH_BLUESPACE = 10)
- equip_cooldown = 150
- energy_drain = 1000
- range = RANGED
-
- equip_type = EQUIP_SPECIAL
-
-/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target)
- if(!action_checks(target) || src.loc.z == 2) return
- var/turf/T = get_turf(target)
- if(T)
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_teleport(chassis, T, 4)
- do_after_cooldown()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/wormhole_generator
- name = "wormhole generator"
- desc = "An exosuit module that allows generating of small quasi-stable wormholes."
- icon_state = "mecha_wholegen"
- origin_tech = list(TECH_BLUESPACE = 3)
- equip_cooldown = 50
- energy_drain = 300
- range = RANGED
-
- equip_type = EQUIP_SPECIAL
-
-/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target)
- if(!action_checks(target) || src.loc.z == 2) return
- var/list/theareas = list()
- for(var/area/AR in orange(100, chassis))
- if(AR in theareas) continue
- theareas += AR
- if(!theareas.len)
- return
- var/area/thearea = pick(theareas)
- var/list/L = list()
- var/turf/pos = get_turf(src)
- for(var/turf/T in get_area_turfs(thearea.type))
- if(!T.density && pos.z == T.z)
- var/clear = 1
- for(var/obj/O in T)
- if(O.density)
- clear = 0
- break
- if(clear)
- L+=T
- if(!L.len)
- return
- var/turf/target_turf = pick(L)
- if(!target_turf)
- return
- chassis.use_power(energy_drain)
- set_ready_state(0)
- var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target))
- P.target = target_turf
- P.creator = null
- P.icon = 'icons/obj/objects.dmi'
- P.failchance = 0
- P.icon_state = "anom"
- P.name = "wormhole"
- do_after_cooldown()
- src = null
- spawn(rand(150,300))
- qdel(P)
- return
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult
- name = "gravitational catapult"
- desc = "An exosuit mounted gravitational catapult."
- icon_state = "mecha_teleport"
- origin_tech = list(TECH_BLUESPACE = 2, TECH_MAGNET = 3)
- equip_cooldown = 10
- energy_drain = 100
- range = MELEE|RANGED
- var/atom/movable/locked
- var/mode = 1 //1 - gravsling 2 - gravpush
-
- var/last_fired = 0 //Concept stolen from guns.
- var/fire_delay = 10 //Used to prevent spam-brute against humans.
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target)
-
- if(world.time >= last_fired + fire_delay)
- last_fired = world.time
- else
- if (world.time % 3)
- occupant_message("[src] is not ready to fire again!")
- return 0
-
- switch(mode)
- if(1)
- if(!action_checks(target) && !locked) return
- if(!locked)
- if(!istype(target) || target.anchored)
- occupant_message("Unable to lock on [target]")
- return
- locked = target
- occupant_message("Locked on [target]")
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- return
- else if(target!=locked)
- if(locked in view(chassis))
- locked.throw_at(target, 14, 1.5, chassis)
- locked = null
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- else
- locked = null
- occupant_message("Lock on [locked] disengaged.")
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- if(2)
- if(!action_checks(target)) return
- var/list/atoms = list()
- if(isturf(target))
- atoms = range(target,3)
- else
- atoms = orange(target,3)
- for(var/atom/movable/A in atoms)
- if(A.anchored) continue
- spawn(0)
- var/iter = 5-get_dist(A,target)
- for(var/i=0 to iter)
- step_away(A,target)
- sleep(2)
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult/get_equip_info()
- return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]"
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult/Topic(href, href_list)
- ..()
- if(href_list["mode"])
- mode = text2num(href_list["mode"])
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants.
- name = "\improper CCW armor booster"
- desc = "Close-combat armor booster. Boosts exosuit armor against armed melee attacks. Requires energy to operate."
- icon_state = "mecha_abooster_ccw"
- origin_tech = list(TECH_MATERIAL = 3)
- equip_cooldown = 10
- energy_drain = 50
- range = 0
- var/deflect_coeff = 1.15
- var/damage_coeff = 0.8
-
- equip_type = EQUIP_HULL
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/can_attach(obj/mecha/M as obj)
- if(..())
- if(!M.proc_res["dynattackby"])
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/attach(obj/mecha/M as obj)
- ..()
- chassis.proc_res["dynattackby"] = src
- return
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/detach()
- chassis.proc_res["dynattackby"] = null
- ..()
- return
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info()
- if(!chassis) return
- return "* [src.name]"
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob)
- if(!action_checks(user))
- return chassis.dynattackby(W,user)
- chassis.log_message("Attacked by [W]. Attacker - [user]")
- if(prob(chassis.deflect_chance*deflect_coeff))
- user << "\The [W] bounces off [chassis] armor."
- chassis.log_append_to_last("Armor saved.")
- else
- chassis.occupant_message("\The [user] hits [chassis] with [W].")
- user.visible_message("\The [user] hits [chassis] with [W].", "You hit [src] with [W].")
- chassis.take_damage(round(W.force*damage_coeff),W.damtype)
- chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster
- name = "\improper RW armor booster"
- desc = "Ranged-weaponry armor booster. Boosts exosuit armor against ranged attacks. Completely blocks taser shots, but requires energy to operate."
- icon_state = "mecha_abooster_proj"
- origin_tech = list(TECH_MATERIAL = 4)
- equip_cooldown = 10
- energy_drain = 50
- range = 0
- var/deflect_coeff = 1.15
- var/damage_coeff = 0.8
-
- equip_type = EQUIP_HULL
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/can_attach(obj/mecha/M as obj)
- if(..())
- if(!M.proc_res["dynbulletdamage"] && !M.proc_res["dynhitby"])
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/attach(obj/mecha/M as obj)
- ..()
- chassis.proc_res["dynbulletdamage"] = src
- chassis.proc_res["dynhitby"] = src
- return
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/detach()
- chassis.proc_res["dynbulletdamage"] = null
- chassis.proc_res["dynhitby"] = null
- ..()
- return
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/get_equip_info()
- if(!chassis) return
- return "* [src.name]"
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynbulletdamage(var/obj/item/projectile/Proj)
- if(!action_checks(src))
- return chassis.dynbulletdamage(Proj)
- if(prob(chassis.deflect_chance*deflect_coeff))
- chassis.occupant_message("The armor deflects incoming projectile.")
- chassis.visible_message("The [chassis.name] armor deflects the projectile")
- chassis.log_append_to_last("Armor saved.")
- else
- chassis.take_damage(round(Proj.damage*src.damage_coeff),Proj.check_armour)
- chassis.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- Proj.on_hit(chassis)
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynhitby(atom/movable/A)
- if(!action_checks(A))
- return chassis.dynhitby(A)
- if(prob(chassis.deflect_chance*deflect_coeff) || istype(A, /mob/living) || istype(A, /obj/item/mecha_parts/mecha_tracking))
- chassis.occupant_message("The [A] bounces off the armor.")
- chassis.visible_message("The [A] bounces off the [chassis] armor")
- chassis.log_append_to_last("Armor saved.")
- if(istype(A, /mob/living))
- var/mob/living/M = A
- M.take_organ_damage(10)
- else if(istype(A, /obj))
- var/obj/O = A
- if(O.throwforce)
- chassis.take_damage(round(O.throwforce*damage_coeff))
- chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid
- name = "repair droid"
- desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost any type of external or internal damage."
- icon_state = "repair_droid"
- origin_tech = list(TECH_MAGNET = 3, TECH_DATA = 3)
- equip_cooldown = 20
- energy_drain = 100
- range = 0
- var/health_boost = 2
- var/datum/global_iterator/pr_repair_droid
- var/icon/droid_overlay
- var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH)
-
- equip_type = EQUIP_HULL
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/New()
- ..()
- pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0)
- pr_repair_droid.set_delay(equip_cooldown)
- return
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy()
- qdel(pr_repair_droid)
- pr_repair_droid = null
- ..()
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M as obj)
- ..()
- droid_overlay = new(src.icon, icon_state = "repair_droid")
- M.overlays += droid_overlay
- return
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/destroy()
- chassis.overlays -= droid_overlay
- ..()
- return
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
- chassis.overlays -= droid_overlay
- pr_repair_droid.stop()
- ..()
- return
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info()
- if(!chassis) return
- return "* [src.name] - [pr_repair_droid.active()?"Dea":"A"]ctivate"
-
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list)
- ..()
- if(href_list["toggle_repairs"])
- chassis.overlays -= droid_overlay
- if(pr_repair_droid.toggle())
- droid_overlay = new(src.icon, icon_state = "repair_droid_a")
- log_message("Activated.")
- else
- droid_overlay = new(src.icon, icon_state = "repair_droid")
- log_message("Deactivated.")
- set_ready_state(1)
- chassis.overlays += droid_overlay
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- return
-
-
-/datum/global_iterator/mecha_repair_droid
-
-/datum/global_iterator/mecha_repair_droid/process(var/obj/item/mecha_parts/mecha_equipment/repair_droid/RD as obj)
- if(!RD.chassis)
- stop()
- RD.set_ready_state(1)
- return
- var/health_boost = RD.health_boost
- var/repaired = 0
- if(RD.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
- health_boost *= -2
- else if(RD.chassis.hasInternalDamage() && prob(15))
- for(var/int_dam_flag in RD.repairable_damage)
- if(RD.chassis.hasInternalDamage(int_dam_flag))
- RD.chassis.clearInternalDamage(int_dam_flag)
- repaired = 1
- break
- if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health))
- RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health)
- repaired = 1
- if(repaired)
- if(RD.chassis.use_power(RD.energy_drain))
- RD.set_ready_state(0)
- else
- stop()
- RD.set_ready_state(1)
- return
- else
- RD.set_ready_state(1)
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
- name = "energy relay"
- desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low."
- icon_state = "tesla"
- origin_tech = list(TECH_MAGNET = 4, TECH_ILLEGAL = 2)
- equip_cooldown = 10
- energy_drain = 0
- range = 0
- var/datum/global_iterator/pr_energy_relay
- var/coeff = 100
- var/list/use_channels = list(EQUIP,ENVIRON,LIGHT)
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/New()
- ..()
- pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0)
- pr_energy_relay.set_delay(equip_cooldown)
- return
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy()
- qdel(pr_energy_relay)
- pr_energy_relay = null
- ..()
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach()
- pr_energy_relay.stop()
-// chassis.proc_res["dynusepower"] = null
- chassis.proc_res["dyngetcharge"] = null
- ..()
- return
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/attach(obj/mecha/M)
- ..()
- chassis.proc_res["dyngetcharge"] = src
-// chassis.proc_res["dynusepower"] = src
- return
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/can_attach(obj/mecha/M)
- if(..())
- if(!M.proc_res["dyngetcharge"])// && !M.proc_res["dynusepower"])
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/dyngetcharge()
- if(equip_ready) //disabled
- return chassis.dyngetcharge()
- var/area/A = get_area(chassis)
- var/pow_chan = get_power_channel(A)
- var/charge = 0
- if(pow_chan)
- charge = 1000 //making magic
- else
- return chassis.dyngetcharge()
- return charge
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A)
- var/pow_chan
- if(A)
- for(var/c in use_channels)
- if(A.powered(c))
- pow_chan = c
- break
- return pow_chan
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Topic(href, href_list)
- ..()
- if(href_list["toggle_relay"])
- if(pr_energy_relay.toggle())
- set_ready_state(0)
- log_message("Activated.")
- else
- set_ready_state(1)
- log_message("Deactivated.")
- return
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info()
- if(!chassis) return
- return "* [src.name] - [pr_energy_relay.active()?"Dea":"A"]ctivate"
-
-/* proc/dynusepower(amount)
- if(!equip_ready) //enabled
- var/area/A = get_area(chassis)
- var/pow_chan = get_power_channel(A)
- if(pow_chan)
- A.master.use_power(amount*coeff, pow_chan)
- return 1
- return chassis.dynusepower(amount)*/
-
-/datum/global_iterator/mecha_energy_relay
-
-/datum/global_iterator/mecha_energy_relay/process(var/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/ER)
- if(!ER.chassis || ER.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
- stop()
- ER.set_ready_state(1)
- return
- var/cur_charge = ER.chassis.get_charge()
- if(isnull(cur_charge) || !ER.chassis.cell)
- stop()
- ER.set_ready_state(1)
- ER.occupant_message("No powercell detected.")
- return
- if(cur_charge* [src.name] - [my_shield.active?"Dea":"A"]ctivate"
-
-
-/obj/item/mecha_parts/mecha_equipment/generator
- name = "phoron generator"
- desc = "Generates power using solid phoron as fuel. Pollutes the environment."
- icon_state = "tesla"
- origin_tech = list(TECH_PHORON = 2, TECH_POWER = 2, TECH_ENGINEERING = 1)
- equip_cooldown = 10
- energy_drain = 0
- range = MELEE
- var/datum/global_iterator/pr_mech_generator
- var/coeff = 100
- var/obj/item/stack/material/fuel
- var/max_fuel = 150000
- var/fuel_per_cycle_idle = 100
- var/fuel_per_cycle_active = 500
- var/power_per_cycle = 20
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/generator/New()
- ..()
- init()
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/Destroy()
- qdel(pr_mech_generator)
- pr_mech_generator = null
- ..()
-
-/obj/item/mecha_parts/mecha_equipment/generator/proc/init()
- fuel = new /obj/item/stack/material/phoron(src)
- fuel.amount = 0
- pr_mech_generator = new /datum/global_iterator/mecha_generator(list(src),0)
- pr_mech_generator.set_delay(equip_cooldown)
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/detach()
- pr_mech_generator.stop()
- ..()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/generator/Topic(href, href_list)
- ..()
- if(href_list["toggle"])
- if(pr_mech_generator.toggle())
- set_ready_state(0)
- log_message("Activated.")
- else
- set_ready_state(1)
- log_message("Deactivated.")
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
- var/output = ..()
- if(output)
- return "[output] \[[fuel]: [round(fuel.amount*fuel.perunit,0.1)] cm3\] - [pr_mech_generator.active()?"Dea":"A"]ctivate"
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/action(target)
- if(chassis)
- var/result = load_fuel(target)
- var/message
- if(isnull(result))
- message = "[fuel] traces in target minimal. [target] cannot be used as fuel."
- else if(!result)
- message = "Unit is full."
- else
- message = "[result] unit\s of [fuel] successfully loaded."
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- occupant_message(message)
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/material/P)
- if(P.type == fuel.type && P.amount)
- var/to_load = max(max_fuel - fuel.amount*fuel.perunit,0)
- if(to_load)
- var/units = min(max(round(to_load / P.perunit),1),P.amount)
- if(units)
- fuel.amount += units
- P.use(units)
- return units
- else
- return 0
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/attackby(weapon,mob/user)
- var/result = load_fuel(weapon)
- if(isnull(result))
- user.visible_message("[user] tries to shove [weapon] into [src]. What a dumb-ass.","[fuel] traces minimal. [weapon] cannot be used as fuel.")
- else if(!result)
- user << "Unit is full."
- else
- user.visible_message("[user] loads [src] with [fuel].","[result] unit\s of [fuel] successfully loaded.")
- return
-
-/obj/item/mecha_parts/mecha_equipment/generator/critfail()
- ..()
- var/turf/simulated/T = get_turf(src)
- if(!T)
- return
- var/datum/gas_mixture/GM = new
- if(prob(10))
- T.assume_gas("phoron", 100, 1500+T0C)
- T.visible_message("The [src] suddenly disgorges a cloud of heated phoron.")
- destroy()
- else
- T.assume_gas("phoron", 5, istype(T) ? T.air.temperature : T20C)
- T.visible_message("The [src] suddenly disgorges a cloud of phoron.")
- T.assume_air(GM)
- return
-
-/datum/global_iterator/mecha_generator
-
-/datum/global_iterator/mecha_generator/process(var/obj/item/mecha_parts/mecha_equipment/generator/EG)
- if(!EG.chassis)
- stop()
- EG.set_ready_state(1)
- return 0
- if(EG.fuel.amount<=0)
- stop()
- EG.log_message("Deactivated - no fuel.")
- EG.set_ready_state(1)
- return 0
- var/cur_charge = EG.chassis.get_charge()
- if(isnull(cur_charge))
- EG.set_ready_state(1)
- EG.occupant_message("No powercell detected.")
- EG.log_message("Deactivated.")
- stop()
- return 0
- var/use_fuel = EG.fuel_per_cycle_idle
- if(cur_charge[target] succesfully loaded.")
- chassis.log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
- else
- chassis.occupant_message("You must hold still while handling objects.")
- O.anchored = initial(O.anchored)
- else
- chassis.occupant_message("Not enough room in cargo compartment.")
- else
- chassis.occupant_message("[target] is firmly secured.")
-
- else if(istype(target,/mob/living))
- var/mob/living/M = target
- if(M.stat>1) return
- if(chassis.occupant.a_intent == I_HURT)
- chassis.occupant_message("You obliterate [target] with [src.name], leaving blood and guts everywhere.")
- chassis.visible_message("[chassis] destroys [target] in an unholy fury.")
- if(chassis.occupant.a_intent == I_DISARM)
- chassis.occupant_message("You tear [target]'s limbs off with [src.name].")
- chassis.visible_message("[chassis] rips [target]'s arms off.")
- else
- step_away(M,chassis)
- chassis.occupant_message("You smash into [target], sending them flying.")
- chassis.visible_message("[chassis] tosses [target] like a piece of paper.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger
- name = "passenger compartment"
- desc = "A mountable passenger compartment for exosuits. Rather cramped."
- icon_state = "mecha_abooster_ccw"
- origin_tech = list(TECH_ENGINEERING = 1, TECH_BIO = 1)
- energy_drain = 10
- range = MELEE
- equip_cooldown = 20
- var/mob/living/carbon/occupant = null
- var/door_locked = 1
- salvageable = 0
- allow_duplicate = TRUE
-
- equip_type = EQUIP_HULL
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/destroy()
- for(var/atom/movable/AM in src)
- AM.forceMove(get_turf(src))
- AM << "You tumble out of the destroyed [src.name]!"
- return ..()
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/Exit(atom/movable/O)
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/proc/move_inside(var/mob/user)
- if (chassis)
- chassis.visible_message("[user] starts to climb into [chassis].")
-
- if(do_after(user, 40, needhand=0))
- if(!src.occupant)
- user.forceMove(src)
- occupant = user
- log_message("[user] boarded.")
- occupant_message("[user] boarded.")
- else if(src.occupant != user)
- to_chat(user, "[src.occupant] was faster. Try harder next time, loser.")
- else
- to_chat(user, "You stop entering the exosuit.")
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/verb/eject()
- set name = "Eject"
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(usr != occupant)
- return
- to_chat(occupant, "You climb out from \the [src].")
- go_out()
- occupant_message("[occupant] disembarked.")
- log_message("[occupant] disembarked.")
- add_fingerprint(usr)
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/proc/go_out()
- if(!occupant)
- return
- occupant.forceMove(get_turf(src))
- occupant.reset_view()
- /*
- if(occupant.client)
- occupant.client.eye = occupant.client.mob
- occupant.client.perspective = MOB_PERSPECTIVE
- */
- occupant = null
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/attach()
- ..()
- if (chassis)
- chassis.verbs |= /obj/mecha/proc/move_inside_passenger
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/detach()
- if(occupant)
- occupant_message("Unable to detach [src] - equipment occupied.")
- return
-
- var/obj/mecha/M = chassis
- ..()
- if (M && !(locate(/obj/item/mecha_parts/mecha_equipment/tool/passenger) in M))
- M.verbs -= /obj/mecha/proc/move_inside_passenger
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/get_equip_info()
- return "[..()]
[occupant? "\[Occupant: [occupant]\]|" : ""]Exterior Hatch: Toggle Lock"
-
-/obj/item/mecha_parts/mecha_equipment/tool/passenger/Topic(href,href_list)
- ..()
- if (href_list["toggle_lock"])
- door_locked = !door_locked
- occupant_message("Passenger compartment hatch [door_locked? "locked" : "unlocked"].")
- if (chassis)
- chassis.visible_message("The hatch on \the [chassis] [door_locked? "locks" : "unlocks"].", "You hear something latching.")
-
-
-#define LOCKED 1
-#define OCCUPIED 2
-
-/obj/mecha/proc/move_inside_passenger()
- set category = "Object"
- set name = "Enter Passenger Compartment"
- set src in oview(1)
-
- //check that usr can climb in
- if (usr.stat || !ishuman(usr))
- return
-
- if (!usr.Adjacent(src))
- return
-
- if (!isturf(usr.loc))
- usr << "You can't reach the passenger compartment from here."
- return
-
- if(iscarbon(usr))
- var/mob/living/carbon/C = usr
- if(C.handcuffed)
- usr << "Kinda hard to climb in while handcuffed don't you think?"
- return
-
- if(isliving(usr))
- var/mob/living/L = usr
- if(L.has_buckled_mobs())
- to_chat(L, span("warning", "You have other entities attached to yourself. Remove them first."))
- return
-
- //search for a valid passenger compartment
- var/feedback = 0 //for nicer user feedback
- for(var/obj/item/mecha_parts/mecha_equipment/tool/passenger/P in src)
- if (P.occupant)
- feedback |= OCCUPIED
- continue
- if (P.door_locked)
- feedback |= LOCKED
- continue
-
- //found a boardable compartment
- P.move_inside(usr)
- return
-
- //didn't find anything
- switch (feedback)
- if (OCCUPIED)
- usr << "The passenger compartment is already occupied!"
- if (LOCKED)
- usr << "The passenger compartment hatch is locked!"
- if (OCCUPIED|LOCKED)
- usr << "All of the passenger compartments are already occupied or locked!"
- if (0)
- usr << "\The [src] doesn't have a passenger compartment."
-
-#undef LOCKED
-#undef OCCUPIED
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack
- name = "ion jetpack"
- desc = "Using directed ion bursts and cunning solar wind reflection technique, this device enables controlled space flight."
- icon_state = "mecha_jetpack"
- equip_cooldown = 5
- energy_drain = 50
- var/wait = 0
- var/datum/effect/effect/system/ion_trail_follow/ion_trail
-
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/can_attach(obj/mecha/M as obj)
- if(!(locate(src.type) in M.equipment) && !M.proc_res["dyndomove"])
- return ..()
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/detach()
- ..()
- chassis.proc_res["dyndomove"] = null
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/attach(obj/mecha/M as obj)
- ..()
- if(!ion_trail)
- ion_trail = new
- ion_trail.set_up(chassis)
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/proc/toggle()
- if(!chassis)
- return
- !equip_ready? turn_off() : turn_on()
- return equip_ready
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/proc/turn_on()
- set_ready_state(0)
- chassis.proc_res["dyndomove"] = src
- ion_trail.start()
- occupant_message("Activated")
- log_message("Activated")
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/proc/turn_off()
- set_ready_state(1)
- chassis.proc_res["dyndomove"] = null
- ion_trail.stop()
- occupant_message("Deactivated")
- log_message("Deactivated")
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/proc/dyndomove(direction)
- if(!action_checks())
- return chassis.dyndomove(direction)
- var/move_result = 0
- if(chassis.hasInternalDamage(MECHA_INT_CONTROL_LOST))
- move_result = step_rand(chassis)
- else if(chassis.dir!=direction)
- chassis.set_dir(direction)
- move_result = 1
- else
- move_result = step(chassis,direction)
- if(chassis.occupant)
- for(var/obj/effect/speech_bubble/B in range(1, chassis))
- if(B.parent == chassis.occupant)
- B.loc = chassis.loc
- if(move_result)
- wait = 1
- chassis.use_power(energy_drain)
- if(!chassis.pr_inertial_movement.active())
- chassis.pr_inertial_movement.start(list(chassis,direction))
- else
- chassis.pr_inertial_movement.set_process_args(list(chassis,direction))
- do_after_cooldown()
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/action_checks()
- if(equip_ready || wait)
- return 0
- if(energy_drain && !chassis.has_charge(energy_drain))
- return 0
- if(chassis.check_for_support())
- return 0
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/get_equip_info()
- if(!chassis) return
- return "* [src.name] \[Toggle\]"
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/Topic(href,href_list)
- ..()
- if(href_list["toggle"])
- toggle()
-
-/obj/item/mecha_parts/mecha_equipment/tool/jetpack/do_after_cooldown()
- sleep(equip_cooldown)
- wait = 0
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/speedboost
- name = "ripley leg actuator overdrive"
- desc = "System enhancements and overdrives to make a ripley's legs move faster."
- icon_state = "tesla"
- origin_tech = list( TECH_POWER = 5, TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
- required_type = list(/obj/mecha/working/ripley)
-
- equip_type = EQUIP_HULL
-
-/obj/item/mecha_parts/mecha_equipment/speedboost/attach(obj/mecha/M as obj)
- ..()
- if(enable_special)
- chassis.step_in = (chassis.step_in-2) // Make the ripley as fast as a durand
- else
- chassis.step_in = (chassis.step_in+1) // Improper parts slow the mech down
- return
-
-/obj/item/mecha_parts/mecha_equipment/speedboost/detach()
- chassis.step_in = initial(chassis.step_in)
- ..()
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer
- name = "Cable Layer"
- icon_state = "mecha_wire"
- var/turf/old_turf
- var/obj/structure/cable/last_piece
- var/obj/item/stack/cable_coil/cable
- var/max_cable = 1000
- required_type = list(/obj/mecha/working)
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/New()
- cable = new(src)
- cable.amount = 0
- ..()
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/MoveAction()
- layCable()
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/action(var/obj/item/stack/cable_coil/target)
- if(!action_checks(target))
- return
- var/result = load_cable(target)
- var/message
- if(isnull(result))
- message = "Unable to load [target] - no cable found."
- else if(!result)
- message = "Reel is full."
- else
- message = "[result] meters of cable successfully loaded."
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- occupant_message(message)
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/Topic(href,href_list)
- ..()
- if(href_list["toggle"])
- set_ready_state(!equip_ready)
- occupant_message("[src] [equip_ready?"dea":"a"]ctivated.")
- log_message("[equip_ready?"Dea":"A"]ctivated.")
- return
- if(href_list["cut"])
- if(cable && cable.amount)
- var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1)
- m = min(m, cable.amount)
- if(m)
- use_cable(m)
- var/obj/item/stack/cable_coil/CC = new (get_turf(chassis))
- CC.amount = m
- else
- occupant_message("There's no more cable on the reel.")
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/get_equip_info()
- var/output = ..()
- if(output)
- return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]"
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/load_cable(var/obj/item/stack/cable_coil/CC)
- if(istype(CC) && CC.amount)
- var/cur_amount = cable? cable.amount : 0
- var/to_load = max(max_cable - cur_amount,0)
- if(to_load)
- to_load = min(CC.amount, to_load)
- if(!cable)
- cable = new(src)
- cable.amount = 0
- cable.amount += to_load
- CC.use(to_load)
- return to_load
- else
- return 0
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/use_cable(amount)
- if(!cable || cable.amount<1)
- set_ready_state(1)
- occupant_message("Cable depleted, [src] deactivated.")
- log_message("Cable depleted, [src] deactivated.")
- return
- if(cable.amount < amount)
- occupant_message("No enough cable to finish the task.")
- return
- cable.use(amount)
- update_equip_info()
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/reset()
- last_piece = null
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/dismantleFloor(var/turf/new_turf)
- new_turf = get_turf(chassis)
- if(istype(new_turf, /turf/simulated/floor))
- var/turf/simulated/floor/T = new_turf
- if(!T.is_plating())
- T.make_plating(!(T.broken || T.burnt))
- return new_turf.is_plating()
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(var/turf/new_turf)
- new_turf = get_turf(chassis)
- if(equip_ready || !istype(new_turf, /turf/simulated/floor) || !dismantleFloor(new_turf))
- return reset()
- var/fdirn = turn(chassis.dir,180)
- for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already
- if(LC.d1 == fdirn || LC.d2 == fdirn)
- return reset()
- if(!use_cable(1))
- return reset()
- var/obj/structure/cable/NC = new(new_turf)
- NC.cableColor("red")
- NC.d1 = 0
- NC.d2 = fdirn
- NC.update_icon()
-
- var/datum/powernet/PN
- if(last_piece && last_piece.d2 != chassis.dir)
- last_piece.d1 = min(last_piece.d2, chassis.dir)
- last_piece.d2 = max(last_piece.d2, chassis.dir)
- last_piece.update_icon()
- PN = last_piece.powernet
-
- if(!PN)
- PN = new()
- PN.add_cable(NC)
- NC.mergeConnectedNetworks(NC.d2)
-
- //NC.mergeConnectedNetworksOnTurf()
- last_piece = NC
- return 1
\ No newline at end of file
+ equip_type = EQUIP_UTILITY
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/wormhole.dm b/code/game/mecha/equipment/tools/wormhole.dm
new file mode 100644
index 0000000000..eef3c6a52a
--- /dev/null
+++ b/code/game/mecha/equipment/tools/wormhole.dm
@@ -0,0 +1,50 @@
+/obj/item/mecha_parts/mecha_equipment/wormhole_generator
+ name = "wormhole generator"
+ desc = "An exosuit module that allows generating of small quasi-stable wormholes."
+ icon_state = "mecha_wholegen"
+ origin_tech = list(TECH_BLUESPACE = 3)
+ equip_cooldown = 50
+ energy_drain = 300
+ range = RANGED
+
+ equip_type = EQUIP_SPECIAL
+
+/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target)
+ if(!action_checks(target) || src.loc.z == 2) return
+ var/list/theareas = list()
+ for(var/area/AR in orange(100, chassis))
+ if(AR in theareas) continue
+ theareas += AR
+ if(!theareas.len)
+ return
+ var/area/thearea = pick(theareas)
+ var/list/L = list()
+ var/turf/pos = get_turf(src)
+ for(var/turf/T in get_area_turfs(thearea.type))
+ if(!T.density && pos.z == T.z)
+ var/clear = 1
+ for(var/obj/O in T)
+ if(O.density)
+ clear = 0
+ break
+ if(clear)
+ L+=T
+ if(!L.len)
+ return
+ var/turf/target_turf = pick(L)
+ if(!target_turf)
+ return
+ chassis.use_power(energy_drain)
+ set_ready_state(0)
+ var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target))
+ P.target = target_turf
+ P.creator = null
+ P.icon = 'icons/obj/objects.dmi'
+ P.failchance = 0
+ P.icon_state = "anom"
+ P.name = "wormhole"
+ do_after_cooldown()
+ src = null
+ spawn(rand(150,300))
+ qdel(P)
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/wrench.dm b/code/game/mecha/equipment/tools/wrench.dm
new file mode 100644
index 0000000000..605c2ee33d
--- /dev/null
+++ b/code/game/mecha/equipment/tools/wrench.dm
@@ -0,0 +1,41 @@
+/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'
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/ballistic/automatic.dm b/code/game/mecha/equipment/weapons/ballistic/automatic.dm
new file mode 100644
index 0000000000..3578592511
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/ballistic/automatic.dm
@@ -0,0 +1,22 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg
+ name = "\improper Ultra AC 2"
+ desc = "A superior version of the standard Solgov Autocannon MK2 design."
+ icon_state = "mecha_uac2"
+ equip_cooldown = 10
+ projectile = /obj/item/projectile/bullet/pistol/medium
+ fire_sound = 'sound/weapons/Gunshot_machinegun.ogg'
+ projectiles = 30 //10 bursts, matching the Scattershot's 10. Also, conveniently, doesn't eat your powercell when reloading like 300 bullets does.
+ projectiles_per_shot = 3
+ deviation = 0.3
+ projectile_energy_cost = 20
+ fire_cooldown = 2
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg/rigged
+ name = "jury-rigged machinegun"
+ desc = "The cross between a jackhammer and a whole lot of zipguns."
+ icon_state = "mecha_uac2-rig"
+ equip_cooldown = 12
+ projectile = /obj/item/projectile/bullet/pistol
+ deviation = 0.5
+
+ equip_type = EQUIP_UTILITY
diff --git a/code/game/mecha/equipment/weapons/ballistic/ballistic.dm b/code/game/mecha/equipment/weapons/ballistic/ballistic.dm
new file mode 100644
index 0000000000..99ef24aab7
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/ballistic/ballistic.dm
@@ -0,0 +1,23 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic
+ name = "general ballisic weapon"
+ var/projectile_energy_cost
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info()
+ return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]"
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/proc/rearm()
+ if(projectiles < initial(projectiles))
+ var/projectiles_to_add = initial(projectiles) - projectiles
+ while(chassis.get_charge() >= projectile_energy_cost && projectiles_to_add)
+ projectiles++
+ projectiles_to_add--
+ chassis.use_power(projectile_energy_cost)
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+ log_message("Rearmed [src.name].")
+ return
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/Topic(href, href_list)
+ ..()
+ if (href_list["rearm"])
+ src.rearm()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/ballistic/mortar.dm b/code/game/mecha/equipment/weapons/ballistic/mortar.dm
new file mode 100644
index 0000000000..86928c9da5
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/ballistic/mortar.dm
@@ -0,0 +1,22 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar
+ name = "\improper HEP RC 4 \"Skyfall\""
+ desc = "A Hephaestus exosuit-mounted mortar for use on planetary-or-similar bodies."
+ description_info = "This weapon cannot be fired indoors, underground, or on-station."
+ icon_state = "mecha_mortar"
+ equip_cooldown = 30
+ fire_sound = 'sound/weapons/Gunshot_cannon.ogg'
+ fire_volume = 100
+ projectiles = 3
+ deviation = 0.6
+ projectile = /obj/item/projectile/arc/fragmentation/mortar
+ projectile_energy_cost = 600
+
+ origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_ILLEGAL = 3)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar/action_checks(atom/target)
+ var/turf/MT = get_turf(chassis)
+ var/turf/TT = get_turf(target)
+ if(!MT.outdoors || !TT.outdoors)
+ to_chat(chassis.occupant, "\The [src]'s control system prevents you from firing due to a blocked firing arc.")
+ return 0
+ return ..()
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/ballistic/shotgun.dm b/code/game/mecha/equipment/weapons/ballistic/shotgun.dm
new file mode 100644
index 0000000000..d2232d0004
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/ballistic/shotgun.dm
@@ -0,0 +1,25 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
+ name = "\improper LBX AC 10 \"Scattershot\""
+ desc = "A massive shotgun designed to fill a large area with pellets."
+ icon_state = "mecha_scatter"
+ equip_cooldown = 20
+ projectile = /obj/item/projectile/bullet/pellet/shotgun/flak
+ fire_sound = 'sound/weapons/Gunshot_shotgun.ogg'
+ fire_volume = 80
+ projectiles = 40
+ projectiles_per_shot = 4
+ deviation = 0.7
+ projectile_energy_cost = 25
+
+ origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/rigged
+ name = "jury-rigged shrapnel cannon"
+ desc = "The remains of some unfortunate RCD now doomed to kill, rather than construct."
+ icon_state = "mecha_scatter-rig"
+ equip_cooldown = 30
+ fire_volume = 100
+ projectiles = 20
+ deviation = 1
+
+ equip_type = EQUIP_UTILITY
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/defense/shocker.dm b/code/game/mecha/equipment/weapons/defense/shocker.dm
new file mode 100644
index 0000000000..af120167d2
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/defense/shocker.dm
@@ -0,0 +1,33 @@
+//////////////
+//Defensive//
+//////////////
+
+/obj/item/mecha_parts/mecha_equipment/shocker
+ name = "exosuit electrifier"
+ desc = "A device to electrify the external portions of a mecha in order to increase its defensive capabilities."
+ icon_state = "mecha_coil"
+ equip_cooldown = 10
+ energy_drain = 100
+ range = RANGED
+ origin_tech = list(TECH_COMBAT = 3, TECH_POWER = 6)
+ var/shock_damage = 15
+ var/active
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/shocker/can_attach(obj/mecha/M as obj)
+ if(..())
+ if(!M.proc_res["dynattackby"] && !M.proc_res["dynattackhand"] && !M.proc_res["dynattackalien"])
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/shocker/attach(obj/mecha/M as obj)
+ ..()
+ chassis.proc_res["dynattackby"] = src
+ return
+
+/obj/item/mecha_parts/mecha_equipment/shocker/proc/dynattackby(obj/item/weapon/W, mob/living/user)
+ if(!action_checks(user) || !active)
+ return
+ user.electrocute_act(shock_damage, src)
+ return chassis.dynattackby(W,user)
diff --git a/code/game/mecha/equipment/weapons/energy/energy.dm b/code/game/mecha/equipment/weapons/energy/energy.dm
new file mode 100644
index 0000000000..091e8dcc7b
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/energy/energy.dm
@@ -0,0 +1,3 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy
+ name = "general energy weapon"
+ auto_rearm = 1
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/energy/ion.dm b/code/game/mecha/equipment/weapons/energy/ion.dm
new file mode 100644
index 0000000000..7d5be8ef2c
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/energy/ion.dm
@@ -0,0 +1,20 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion
+ equip_cooldown = 40
+ name = "mkIV ion heavy cannon"
+ desc = "An upscaled variant of anti-mechanical weaponry constructed by NT, such as the EW Halicon."
+ icon_state = "mecha_ion"
+ energy_drain = 120
+ projectile = /obj/item/projectile/ion
+ fire_sound = 'sound/weapons/Laser.ogg'
+
+ origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion/rigged
+ equip_cooldown = 30
+ name = "jury-rigged ion cannon"
+ desc = "A tesla coil modified to amplify an ionic wave, and use it as a projectile."
+ icon_state = "mecha_ion-rig"
+ energy_drain = 100
+ projectile = /obj/item/projectile/ion/pistol
+
+ equip_type = EQUIP_UTILITY
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/energy/laser.dm b/code/game/mecha/equipment/weapons/energy/laser.dm
new file mode 100644
index 0000000000..8bdcbcf71f
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/energy/laser.dm
@@ -0,0 +1,68 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
+ equip_cooldown = 8
+ name = "\improper CH-PS \"Immolator\" laser"
+ desc = "A laser carbine's firing system mounted on a high-powered exosuit weapon socket."
+ icon_state = "mecha_laser"
+ energy_drain = 30
+ projectile = /obj/item/projectile/beam
+ fire_sound = 'sound/weapons/Laser.ogg'
+
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 3, TECH_MAGNET = 3)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/xray
+ equip_cooldown = 6
+ name = "\improper CH-XS \"Penetrator\" laser"
+ desc = "A large, mounted variant of the anti-armor xray rifle."
+ icon_state = "mecha_xray"
+ energy_drain = 150
+ projectile = /obj/item/projectile/beam/xray
+ fire_sound = 'sound/weapons/eluger.ogg'
+
+ origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 3, TECH_PHORON = 3, TECH_POWER = 3)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/xray/rigged
+ equip_cooldown = 12
+ name = "jury-rigged xray rifle"
+ desc = "A modified wormhole modulation array and meson-scanning control system allow this abomination to produce concentrated blasts of xrays."
+ energy_drain = 175
+ icon_state = "mecha_xray-rig"
+
+ equip_type = EQUIP_UTILITY
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser
+ equip_cooldown = 15
+ name = "jury-rigged welder-laser"
+ desc = "While not regulation, this inefficient weapon can be attached to working exo-suits in desperate, or malicious, times."
+ icon_state = "mecha_laser-rig"
+ energy_drain = 60
+ projectile = /obj/item/projectile/beam
+ fire_sound = 'sound/weapons/Laser.ogg'
+ required_type = list(/obj/mecha/combat, /obj/mecha/working)
+
+ equip_type = EQUIP_UTILITY
+
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 2, TECH_MAGNET = 2)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy
+ equip_cooldown = 15
+ name = "\improper CH-LC \"Solaris\" laser cannon"
+ desc = "In the Solaris, the lasing medium is enclosed in a tube lined with plutonium-239 and subjected to extreme neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with massive laser volumes!"
+ icon_state = "mecha_laser"
+ energy_drain = 60
+ projectile = /obj/item/projectile/beam/heavylaser
+ fire_sound = 'sound/weapons/lasercannonfire.ogg'
+
+ origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/rigged
+ equip_cooldown = 25
+ name = "jury-rigged emitter cannon"
+ desc = "While not regulation, this mining tool can be used as an inefficient weapon on working exo-suits in desperate, or malicious, times."
+ icon_state = "mecha_emitter"
+ energy_drain = 80
+ projectile = /obj/item/projectile/beam/heavylaser/fakeemitter
+ fire_sound = 'sound/weapons/emitter.ogg'
+
+ equip_type = EQUIP_UTILITY
+
+ origin_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4, TECH_PHORON = 3, TECH_ILLEGAL = 1)
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/energy/phased.dm b/code/game/mecha/equipment/weapons/energy/phased.dm
new file mode 100644
index 0000000000..423755705f
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/energy/phased.dm
@@ -0,0 +1,13 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/phase
+ equip_cooldown = 6
+ name = "\improper NT-PE \"Scorpio\" phase-emitter"
+ desc = "A specialist energy weapon intended for use against hostile wildlife."
+ description_fluff = "Essentially an Orion mounted inside a modified Gaia case."
+ icon_state = "mecha_phase"
+ energy_drain = 25
+ projectile = /obj/item/projectile/energy/phase/heavy
+ fire_sound = 'sound/weapons/Taser.ogg'
+
+ equip_type = EQUIP_UTILITY
+
+ origin_tech = list(TECH_MATERIAL = 1, TECH_COMBAT = 2, TECH_MAGNET = 2)
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/energy/pulse.dm b/code/game/mecha/equipment/weapons/energy/pulse.dm
new file mode 100644
index 0000000000..99f7f1d0ce
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/energy/pulse.dm
@@ -0,0 +1,21 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse
+ equip_cooldown = 30
+ name = "eZ-13 mk2 heavy pulse rifle"
+ desc = "An experimental Anti-Everything weapon."
+ icon_state = "mecha_pulse"
+ energy_drain = 120
+ origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 6, TECH_POWER = 4)
+ projectile = /obj/item/projectile/beam/pulse/heavy
+ fire_sound = 'sound/weapons/gauss_shoot.ogg'
+
+/obj/item/projectile/beam/pulse/heavy
+ name = "heavy pulse laser"
+ icon_state = "pulse1_bl"
+ var/life = 20
+
+/obj/item/projectile/beam/pulse/heavy/Bump(atom/A)
+ A.bullet_act(src, def_zone)
+ src.life -= 10
+ if(life <= 0)
+ qdel(src)
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/energy/stun.dm b/code/game/mecha/equipment/weapons/energy/stun.dm
new file mode 100644
index 0000000000..f73e439249
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/energy/stun.dm
@@ -0,0 +1,17 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser
+ name = "\improper PBT \"Pacifier\" mounted taser"
+ desc = "A large taser of similar design as those used in standard NT turrets, for use on an Exosuit."
+ icon_state = "mecha_taser"
+ energy_drain = 20
+ equip_cooldown = 8
+ projectile = /obj/item/projectile/beam/stun
+ fire_sound = 'sound/weapons/Taser.ogg'
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser/rigged
+ name = "jury-rigged static rifle"
+ desc = "A vaguely functional taser analog, inside an extinguisher casing."
+ icon_state = "mecha_taser-rig"
+ energy_drain = 30
+ projectile = /obj/item/projectile/beam/stun/weak
+
+ equip_type = EQUIP_UTILITY
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/explosive/grenade.dm b/code/game/mecha/equipment/weapons/explosive/grenade.dm
new file mode 100644
index 0000000000..930000fe3a
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/explosive/grenade.dm
@@ -0,0 +1,70 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade
+ name = "\improper SGL-6 grenade launcher"
+ desc = "A grenade launcher produced for SWAT use; fires flashbangs."
+ icon_state = "mecha_grenadelnchr"
+ projectile = /obj/item/weapon/grenade/flashbang
+ fire_sound = 'sound/effects/bang.ogg'
+ projectiles = 6
+ missile_speed = 1.5
+ projectile_energy_cost = 800
+ equip_cooldown = 60
+ var/det_time = 20
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/rigged
+ name = "jury-rigged pneumatic flashlauncher"
+ desc = "A grenade launcher constructed out of estranged blueprints; fires flashbangs."
+ icon_state = "mecha_grenadelnchr-rig"
+ projectiles = 3
+ missile_speed = 1
+ det_time = 25
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/Fire(atom/movable/AM, atom/target, turf/aimloc)
+ var/obj/item/weapon/grenade/G = AM
+ if(istype(G))
+ G.det_time = det_time
+ G.activate(chassis.occupant) //Grenades actually look primed and dangerous, handle their own stuff.
+ AM.throw_at(target,missile_range, missile_speed, chassis)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang//Because I am a heartless bastard -Sieve
+ name = "\improper SOP-6 grenade launcher"
+ desc = "A grenade launcher produced for use by government uprising subjugation forces, or that's what you might guess; fires matryoshka flashbangs."
+ projectile = /obj/item/weapon/grenade/flashbang/clusterbang
+
+ origin_tech = list(TECH_COMBAT= 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang/limited/get_equip_info()//Limited version of the clusterbang launcher that can't reload
+ return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]\[[src.projectiles]\]"
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang/limited/rearm()
+ return//Extra bit of security
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/concussion
+ name = "\improper SGL-9 grenade launcher"
+ desc = "A military-grade grenade launcher that fires disorienting concussion grenades."
+ icon_state = "mecha_grenadelnchr"
+ projectile = /obj/item/weapon/grenade/concussion
+ missile_speed = 1
+ projectile_energy_cost = 900
+ equip_cooldown = 50
+ det_time = 25
+
+ origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_ILLEGAL = 1)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/frag
+ name = "\improper HEP-I 5 grenade launcher"
+ desc = "A military-grade grenade launcher that fires anti-personnel fragmentation grenades."
+ icon_state = "mecha_fraglnchr"
+ projectile = /obj/item/weapon/grenade/explosive
+ projectiles = 4
+ missile_speed = 1
+
+ origin_tech = list(TECH_COMBAT = 5, TECH_ENGINEERING = 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/frag/mini
+ name = "\improper HEP-MI 6 grenade launcher"
+ desc = "A military-grade grenade launcher that fires miniaturized anti-personnel fragmentation grenades."
+ projectile = /obj/item/weapon/grenade/explosive/mini
+ projectile_energy_cost = 500
+ equip_cooldown = 25
+
+ origin_tech = list(TECH_COMBAT = 4, TECH_ENGINEERING = 2, TECH_MATERIAL = 3, TECH_ILLEGAL = 2)
diff --git a/code/game/mecha/equipment/weapons/explosive/missile.dm b/code/game/mecha/equipment/weapons/explosive/missile.dm
new file mode 100644
index 0000000000..1c14a8c1dd
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/explosive/missile.dm
@@ -0,0 +1,80 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack
+ var/missile_speed = 2
+ var/missile_range = 30
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
+ AM.throw_at(target,missile_range, missile_speed, chassis)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare
+ name = "\improper BNI Flare Launcher"
+ desc = "A flare-gun, but bigger."
+ icon_state = "mecha_flaregun"
+ projectile = /obj/item/device/flashlight/flare
+ fire_sound = 'sound/weapons/tablehit1.ogg'
+ auto_rearm = 1
+ fire_cooldown = 20
+ projectiles_per_shot = 1
+ projectile_energy_cost = 20
+ missile_speed = 1
+ missile_range = 15
+ required_type = /obj/mecha //Why restrict it to just mining or combat mechs?
+
+ equip_type = EQUIP_UTILITY
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc)
+ var/obj/item/device/flashlight/flare/fired = AM
+ fired.ignite()
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
+ name = "\improper SRM-8 missile rack"
+ desc = "A missile battery that holds eight missiles."
+ icon_state = "mecha_missilerack"
+ projectile = /obj/item/missile
+ fire_sound = 'sound/weapons/rpg.ogg'
+ projectiles = 8
+ projectile_energy_cost = 1000
+ equip_cooldown = 60
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/Fire(atom/movable/AM, atom/target)
+ var/obj/item/missile/M = AM
+ M.primed = 1
+ ..()
+
+/obj/item/missile
+ icon = 'icons/obj/grenade.dmi'
+ icon_state = "missile"
+ var/primed = null
+ throwforce = 15
+ catchable = 0
+ var/devastation = 0
+ var/heavy_blast = 1
+ var/light_blast = 2
+ var/flash_blast = 4
+ does_spin = FALSE // No fun corkscrew missiles.
+
+/obj/item/missile/proc/warhead_special(var/target)
+ explosion(target, devastation, heavy_blast, light_blast, flash_blast)
+ return
+
+/obj/item/missile/throw_impact(atom/hit_atom)
+ if(primed)
+ warhead_special(hit_atom)
+ qdel(src)
+ else
+ ..()
+ return
+
+/obj/item/missile/light
+ throwforce = 10
+ heavy_blast = 0
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/rigged
+ name = "jury-rigged rocket pod"
+ desc = "A series of pipes, tubes, and cables that resembles a rocket pod."
+ icon_state = "mecha_missilerack-rig"
+ projectile = /obj/item/missile/light
+ projectiles = 3
+ projectile_energy_cost = 800
+
+ equip_type = EQUIP_UTILITY
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/fire/flamethrower.dm b/code/game/mecha/equipment/weapons/fire/flamethrower.dm
new file mode 100644
index 0000000000..f97f598e24
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/fire/flamethrower.dm
@@ -0,0 +1,27 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer
+ equip_cooldown = 30
+ name = "\improper CR-3 Mark 8"
+ desc = "An imposing device, this weapon hurls balls of fire."
+ description_fluff = "A weapon designed by Hephaestus for anti-infantry combat, the CR-3 is capable of outputting a large volume of synthesized fuel. Initially designed by a small company, later purchased by Aether, on Earth as a device made for clearing underbrush and co-operating with firefighting operations. Obviously, Hephaestus has found an 'improved' use for the Aether designs."
+ icon_state = "mecha_cremate"
+
+ energy_drain = 30
+
+ projectile = /obj/item/projectile/bullet/incendiary/flamethrower/large
+ fire_sound = 'sound/weapons/towelwipe.ogg'
+
+ origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 6, TECH_PHORON = 4, TECH_ILLEGAL = 4)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer/rigged
+ name = "\improper AA-CR-1 Mark 4"
+ description_fluff = "A firefighting tool maintained by Aether Atmospherics, whose initial design originated from a small Earth company. This one seems to have been jury rigged."
+ icon_state = "mecha_cremate-rig"
+
+ energy_drain = 50
+ required_type = list(/obj/mecha/combat, /obj/mecha/working)
+
+ projectile = /obj/item/projectile/bullet/incendiary/flamethrower
+
+ origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 3, TECH_PHORON = 3, TECH_ILLEGAL = 2)
+
+ equip_type = EQUIP_UTILITY
diff --git a/code/game/mecha/equipment/weapons/fire/incendiary.dm b/code/game/mecha/equipment/weapons/fire/incendiary.dm
new file mode 100644
index 0000000000..3d3c174839
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/fire/incendiary.dm
@@ -0,0 +1,18 @@
+//////////////
+//Fire-based//
+//////////////
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/incendiary
+ name = "\improper DR-AC 3"
+ desc = "Dual-barrel rotary machinegun that fires small, incendiary rounds. Ages ten and up."
+ description_fluff = "A weapon designed by Hephaestus Industries, the DR-AC 3's design was plagued by prototype faults including but not limited to: Spontaneous combustion, spontaneous detonation, and excessive collateral conflagration."
+ icon_state = "mecha_drac3"
+ equip_cooldown = 20
+ projectile = /obj/item/projectile/bullet/incendiary
+ fire_sound = 'sound/weapons/Gunshot_machinegun.ogg'
+ projectiles = 30
+ projectiles_per_shot = 2
+ deviation = 0.4
+ projectile_energy_cost = 40
+ fire_cooldown = 3
+ origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_PHORON = 2, TECH_ILLEGAL = 1)
diff --git a/code/game/mecha/equipment/weapons/honk.dm b/code/game/mecha/equipment/weapons/honk.dm
new file mode 100644
index 0000000000..921111a6cd
--- /dev/null
+++ b/code/game/mecha/equipment/weapons/honk.dm
@@ -0,0 +1,37 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/honker
+ name = "sound emission device"
+ desc = "A perfectly normal bike-horn, for your exosuit."
+ icon_state = "mecha_honker"
+ energy_drain = 300
+ equip_cooldown = 150
+ origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 4, TECH_ILLEGAL = 1)
+
+ equip_type = EQUIP_SPECIAL
+
+/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target)
+ if(!chassis)
+ return 0
+ if(energy_drain && chassis.get_charge() < energy_drain)
+ return 0
+ if(!equip_ready)
+ return 0
+
+ playsound(chassis, 'sound/effects/bang.ogg', 30, 1, 30)
+ chassis.occupant_message("You emit a high-pitched noise from the mech.")
+ for(var/mob/living/carbon/M in ohearers(6, chassis))
+ if(istype(M, /mob/living/carbon/human))
+ var/ear_safety = 0
+ ear_safety = M.get_ear_protection()
+ if(ear_safety > 0)
+ return
+ to_chat(M, "Your ears feel like they're bleeding!")
+ playsound(M, 'sound/effects/bang.ogg', 70, 1, 30)
+ M.sleeping = 0
+ M.ear_deaf += 30
+ M.ear_damage += rand(5, 20)
+ M.Weaken(3)
+ M.Stun(5)
+ chassis.use_power(energy_drain)
+ log_message("Used a sound emission device.")
+ do_after_cooldown()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 5df2c54d10..cbbc702adf 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -89,519 +89,4 @@
if(!isnull(M.accuracy))
P.accuracy += M.accuracy
if(!isnull(M.accuracy_dispersion))
- P.dispersion = max(P.dispersion + M.accuracy_dispersion, 0)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy
- name = "general energy weapon"
- auto_rearm = 1
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
- equip_cooldown = 8
- name = "\improper CH-PS \"Immolator\" laser"
- desc = "A laser carbine's firing system mounted on a high-powered exosuit weapon socket."
- icon_state = "mecha_laser"
- energy_drain = 30
- projectile = /obj/item/projectile/beam
- fire_sound = 'sound/weapons/Laser.ogg'
-
- origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 3, TECH_MAGNET = 3)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/xray
- equip_cooldown = 6
- name = "\improper CH-XS \"Penetrator\" laser"
- desc = "A large, mounted variant of the anti-armor xray rifle."
- icon_state = "mecha_xray"
- energy_drain = 150
- projectile = /obj/item/projectile/beam/xray
- fire_sound = 'sound/weapons/eluger.ogg'
-
- origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 3, TECH_PHORON = 3, TECH_POWER = 3)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/xray/rigged
- equip_cooldown = 12
- name = "jury-rigged xray rifle"
- desc = "A modified wormhole modulation array and meson-scanning control system allow this abomination to produce concentrated blasts of xrays."
- energy_drain = 175
- icon_state = "mecha_xray-rig"
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser
- equip_cooldown = 15
- name = "jury-rigged welder-laser"
- desc = "While not regulation, this inefficient weapon can be attached to working exo-suits in desperate, or malicious, times."
- icon_state = "mecha_laser-rig"
- energy_drain = 60
- projectile = /obj/item/projectile/beam
- fire_sound = 'sound/weapons/Laser.ogg'
- required_type = list(/obj/mecha/combat, /obj/mecha/working)
-
- equip_type = EQUIP_UTILITY
-
- origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 2, TECH_MAGNET = 2)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy
- equip_cooldown = 15
- name = "\improper CH-LC \"Solaris\" laser cannon"
- desc = "In the Solaris, the lasing medium is enclosed in a tube lined with plutonium-239 and subjected to extreme neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with massive laser volumes!"
- icon_state = "mecha_laser"
- energy_drain = 60
- projectile = /obj/item/projectile/beam/heavylaser
- fire_sound = 'sound/weapons/lasercannonfire.ogg'
-
- origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/rigged
- equip_cooldown = 25
- name = "jury-rigged emitter cannon"
- desc = "While not regulation, this mining tool can be used as an inefficient weapon on working exo-suits in desperate, or malicious, times."
- icon_state = "mecha_emitter"
- energy_drain = 80
- projectile = /obj/item/projectile/beam/heavylaser/fakeemitter
- fire_sound = 'sound/weapons/emitter.ogg'
-
- equip_type = EQUIP_UTILITY
-
- origin_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4, TECH_PHORON = 3, TECH_ILLEGAL = 1)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/phase
- equip_cooldown = 6
- name = "\improper NT-PE \"Scorpio\" phase-emitter"
- desc = "A specialist energy weapon intended for use against hostile wildlife."
- description_fluff = "Essentially an Orion mounted inside a modified Gaia case."
- icon_state = "mecha_phase"
- energy_drain = 25
- projectile = /obj/item/projectile/energy/phase/heavy
- fire_sound = 'sound/weapons/Taser.ogg'
-
- equip_type = EQUIP_UTILITY
-
- origin_tech = list(TECH_MATERIAL = 1, TECH_COMBAT = 2, TECH_MAGNET = 2)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion
- equip_cooldown = 40
- name = "mkIV ion heavy cannon"
- desc = "An upscaled variant of anti-mechanical weaponry constructed by NT, such as the EW Halicon."
- icon_state = "mecha_ion"
- energy_drain = 120
- projectile = /obj/item/projectile/ion
- fire_sound = 'sound/weapons/Laser.ogg'
-
- origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion/rigged
- equip_cooldown = 30
- name = "jury-rigged ion cannon"
- desc = "A tesla coil modified to amplify an ionic wave, and use it as a projectile."
- icon_state = "mecha_ion-rig"
- energy_drain = 100
- projectile = /obj/item/projectile/ion/pistol
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse
- equip_cooldown = 30
- name = "eZ-13 mk2 heavy pulse rifle"
- desc = "An experimental Anti-Everything weapon."
- icon_state = "mecha_pulse"
- energy_drain = 120
- origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 6, TECH_POWER = 4)
- projectile = /obj/item/projectile/beam/pulse/heavy
- fire_sound = 'sound/weapons/gauss_shoot.ogg'
-
-/obj/item/projectile/beam/pulse/heavy
- name = "heavy pulse laser"
- icon_state = "pulse1_bl"
- var/life = 20
-
-/obj/item/projectile/beam/pulse/heavy/Bump(atom/A)
- A.bullet_act(src, def_zone)
- src.life -= 10
- if(life <= 0)
- qdel(src)
- return
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser
- name = "\improper PBT \"Pacifier\" mounted taser"
- desc = "A large taser of similar design as those used in standard NT turrets, for use on an Exosuit."
- icon_state = "mecha_taser"
- energy_drain = 20
- equip_cooldown = 8
- projectile = /obj/item/projectile/beam/stun
- fire_sound = 'sound/weapons/Taser.ogg'
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser/rigged
- name = "jury-rigged static rifle"
- desc = "A vaguely functional taser analog, inside an extinguisher casing."
- icon_state = "mecha_taser-rig"
- energy_drain = 30
- projectile = /obj/item/projectile/beam/stun/weak
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/honker
- name = "sound emission device"
- desc = "A perfectly normal bike-horn, for your exosuit."
- icon_state = "mecha_honker"
- energy_drain = 300
- equip_cooldown = 150
- origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 4, TECH_ILLEGAL = 1)
-
- equip_type = EQUIP_SPECIAL
-
-/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target)
- if(!chassis)
- return 0
- if(energy_drain && chassis.get_charge() < energy_drain)
- return 0
- if(!equip_ready)
- return 0
-
- playsound(chassis, 'sound/effects/bang.ogg', 30, 1, 30)
- chassis.occupant_message("You emit a high-pitched noise from the mech.")
- for(var/mob/living/carbon/M in ohearers(6, chassis))
- if(istype(M, /mob/living/carbon/human))
- var/ear_safety = 0
- ear_safety = M.get_ear_protection()
- if(ear_safety > 0)
- return
- to_chat(M, "Your ears feel like they're bleeding!")
- playsound(M, 'sound/effects/bang.ogg', 70, 1, 30)
- M.sleeping = 0
- M.ear_deaf += 30
- M.ear_damage += rand(5, 20)
- M.Weaken(3)
- M.Stun(5)
- chassis.use_power(energy_drain)
- log_message("Used a sound emission device.")
- do_after_cooldown()
- return
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic
- name = "general ballisic weapon"
- var/projectile_energy_cost
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info()
- return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]"
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/proc/rearm()
- if(projectiles < initial(projectiles))
- var/projectiles_to_add = initial(projectiles) - projectiles
- while(chassis.get_charge() >= projectile_energy_cost && projectiles_to_add)
- projectiles++
- projectiles_to_add--
- chassis.use_power(projectile_energy_cost)
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- log_message("Rearmed [src.name].")
- return
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/Topic(href, href_list)
- ..()
- if (href_list["rearm"])
- src.rearm()
- return
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar
- name = "\improper HEP RC 4 \"Skyfall\""
- desc = "A Hephaestus exosuit-mounted mortar for use on planetary-or-similar bodies."
- description_info = "This weapon cannot be fired indoors, underground, or on-station."
- icon_state = "mecha_mortar"
- equip_cooldown = 30
- fire_sound = 'sound/weapons/Gunshot_cannon.ogg'
- fire_volume = 100
- projectiles = 3
- deviation = 0.6
- projectile = /obj/item/projectile/arc/fragmentation/mortar
- projectile_energy_cost = 600
-
- origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_ILLEGAL = 3)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar/action_checks(atom/target)
- var/turf/MT = get_turf(chassis)
- var/turf/TT = get_turf(target)
- if(!MT.outdoors || !TT.outdoors)
- to_chat(chassis.occupant, "\The [src]'s control system prevents you from firing due to a blocked firing arc.")
- return 0
- return ..()
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
- name = "\improper LBX AC 10 \"Scattershot\""
- desc = "A massive shotgun designed to fill a large area with pellets."
- icon_state = "mecha_scatter"
- equip_cooldown = 20
- projectile = /obj/item/projectile/bullet/pellet/shotgun/flak
- fire_sound = 'sound/weapons/Gunshot_shotgun.ogg'
- fire_volume = 80
- projectiles = 40
- projectiles_per_shot = 4
- deviation = 0.7
- projectile_energy_cost = 25
-
- origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/rigged
- name = "jury-rigged shrapnel cannon"
- desc = "The remains of some unfortunate RCD now doomed to kill, rather than construct."
- icon_state = "mecha_scatter-rig"
- equip_cooldown = 30
- fire_volume = 100
- projectiles = 20
- deviation = 1
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg
- name = "\improper Ultra AC 2"
- desc = "A superior version of the standard Solgov Autocannon MK2 design."
- icon_state = "mecha_uac2"
- equip_cooldown = 10
- projectile = /obj/item/projectile/bullet/pistol/medium
- fire_sound = 'sound/weapons/Gunshot_machinegun.ogg'
- projectiles = 30 //10 bursts, matching the Scattershot's 10. Also, conveniently, doesn't eat your powercell when reloading like 300 bullets does.
- projectiles_per_shot = 3
- deviation = 0.3
- projectile_energy_cost = 20
- fire_cooldown = 2
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg/rigged
- name = "jury-rigged machinegun"
- desc = "The cross between a jackhammer and a whole lot of zipguns."
- icon_state = "mecha_uac2-rig"
- equip_cooldown = 12
- projectile = /obj/item/projectile/bullet/pistol
- deviation = 0.5
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack
- var/missile_speed = 2
- var/missile_range = 30
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
- AM.throw_at(target,missile_range, missile_speed, chassis)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare
- name = "\improper BNI Flare Launcher"
- desc = "A flare-gun, but bigger."
- icon_state = "mecha_flaregun"
- projectile = /obj/item/device/flashlight/flare
- fire_sound = 'sound/weapons/tablehit1.ogg'
- auto_rearm = 1
- fire_cooldown = 20
- projectiles_per_shot = 1
- projectile_energy_cost = 20
- missile_speed = 1
- missile_range = 15
- required_type = /obj/mecha //Why restrict it to just mining or combat mechs?
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc)
- var/obj/item/device/flashlight/flare/fired = AM
- fired.ignite()
- ..()
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
- name = "\improper SRM-8 missile rack"
- desc = "A missile battery that holds eight missiles."
- icon_state = "mecha_missilerack"
- projectile = /obj/item/missile
- fire_sound = 'sound/weapons/rpg.ogg'
- projectiles = 8
- projectile_energy_cost = 1000
- equip_cooldown = 60
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/Fire(atom/movable/AM, atom/target)
- var/obj/item/missile/M = AM
- M.primed = 1
- ..()
-
-/obj/item/missile
- icon = 'icons/obj/grenade.dmi'
- icon_state = "missile"
- var/primed = null
- throwforce = 15
- catchable = 0
- var/devastation = 0
- var/heavy_blast = 1
- var/light_blast = 2
- var/flash_blast = 4
- does_spin = FALSE // No fun corkscrew missiles.
-
-/obj/item/missile/proc/warhead_special(var/target)
- explosion(target, devastation, heavy_blast, light_blast, flash_blast)
- return
-
-/obj/item/missile/throw_impact(atom/hit_atom)
- if(primed)
- warhead_special(hit_atom)
- qdel(src)
- else
- ..()
- return
-
-/obj/item/missile/light
- throwforce = 10
- heavy_blast = 0
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/rigged
- name = "jury-rigged rocket pod"
- desc = "A series of pipes, tubes, and cables that resembles a rocket pod."
- icon_state = "mecha_missilerack-rig"
- projectile = /obj/item/missile/light
- projectiles = 3
- projectile_energy_cost = 800
-
- equip_type = EQUIP_UTILITY
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade
- name = "\improper SGL-6 grenade launcher"
- desc = "A grenade launcher produced for SWAT use; fires flashbangs."
- icon_state = "mecha_grenadelnchr"
- projectile = /obj/item/weapon/grenade/flashbang
- fire_sound = 'sound/effects/bang.ogg'
- projectiles = 6
- missile_speed = 1.5
- projectile_energy_cost = 800
- equip_cooldown = 60
- var/det_time = 20
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/rigged
- name = "jury-rigged pneumatic flashlauncher"
- desc = "A grenade launcher constructed out of estranged blueprints; fires flashbangs."
- icon_state = "mecha_grenadelnchr-rig"
- projectiles = 3
- missile_speed = 1
- det_time = 25
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/Fire(atom/movable/AM, atom/target, turf/aimloc)
- var/obj/item/weapon/grenade/G = AM
- if(istype(G))
- G.det_time = det_time
- G.activate(chassis.occupant) //Grenades actually look primed and dangerous, handle their own stuff.
- AM.throw_at(target,missile_range, missile_speed, chassis)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang//Because I am a heartless bastard -Sieve
- name = "\improper SOP-6 grenade launcher"
- desc = "A grenade launcher produced for use by government uprising subjugation forces, or that's what you might guess; fires matryoshka flashbangs."
- projectile = /obj/item/weapon/grenade/flashbang/clusterbang
-
- origin_tech = list(TECH_COMBAT= 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang/limited/get_equip_info()//Limited version of the clusterbang launcher that can't reload
- return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]\[[src.projectiles]\]"
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang/limited/rearm()
- return//Extra bit of security
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/concussion
- name = "\improper SGL-9 grenade launcher"
- desc = "A military-grade grenade launcher that fires disorienting concussion grenades."
- icon_state = "mecha_grenadelnchr"
- projectile = /obj/item/weapon/grenade/concussion
- missile_speed = 1
- projectile_energy_cost = 900
- equip_cooldown = 50
- det_time = 25
-
- origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_ILLEGAL = 1)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/frag
- name = "\improper HEP-I 5 grenade launcher"
- desc = "A military-grade grenade launcher that fires anti-personnel fragmentation grenades."
- icon_state = "mecha_fraglnchr"
- projectile = /obj/item/weapon/grenade/explosive
- projectiles = 4
- missile_speed = 1
-
- origin_tech = list(TECH_COMBAT = 5, TECH_ENGINEERING = 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/frag/mini
- name = "\improper HEP-MI 6 grenade launcher"
- desc = "A military-grade grenade launcher that fires miniaturized anti-personnel fragmentation grenades."
- projectile = /obj/item/weapon/grenade/explosive/mini
- projectile_energy_cost = 500
- equip_cooldown = 25
-
- origin_tech = list(TECH_COMBAT = 4, TECH_ENGINEERING = 2, TECH_MATERIAL = 3, TECH_ILLEGAL = 2)
-
-//////////////
-//Fire-based//
-//////////////
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/incendiary
- name = "\improper DR-AC 3"
- desc = "Dual-barrel rotary machinegun that fires small, incendiary rounds. Ages ten and up."
- description_fluff = "A weapon designed by Hephaestus Industries, the DR-AC 3's design was plagued by prototype faults including but not limited to: Spontaneous combustion, spontaneous detonation, and excessive collateral conflagration."
- icon_state = "mecha_drac3"
- equip_cooldown = 20
- projectile = /obj/item/projectile/bullet/incendiary
- fire_sound = 'sound/weapons/Gunshot_machinegun.ogg'
- projectiles = 30
- projectiles_per_shot = 2
- deviation = 0.4
- projectile_energy_cost = 40
- fire_cooldown = 3
- origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_PHORON = 2, TECH_ILLEGAL = 1)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer
- equip_cooldown = 30
- name = "\improper CR-3 Mark 8"
- desc = "An imposing device, this weapon hurls balls of fire."
- description_fluff = "A weapon designed by Hephaestus for anti-infantry combat, the CR-3 is capable of outputting a large volume of synthesized fuel. Initially designed by a small company, later purchased by Aether, on Earth as a device made for clearing underbrush and co-operating with firefighting operations. Obviously, Hephaestus has found an 'improved' use for the Aether designs."
- icon_state = "mecha_cremate"
-
- energy_drain = 30
-
- projectile = /obj/item/projectile/bullet/incendiary/flamethrower/large
- fire_sound = 'sound/weapons/towelwipe.ogg'
-
- origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 6, TECH_PHORON = 4, TECH_ILLEGAL = 4)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer/rigged
- name = "\improper AA-CR-1 Mark 4"
- description_fluff = "A firefighting tool maintained by Aether Atmospherics, whose initial design originated from a small Earth company. This one seems to have been jury rigged."
- icon_state = "mecha_cremate-rig"
-
- energy_drain = 50
- required_type = list(/obj/mecha/combat, /obj/mecha/working)
-
- projectile = /obj/item/projectile/bullet/incendiary/flamethrower
-
- origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 3, TECH_PHORON = 3, TECH_ILLEGAL = 2)
-
- equip_type = EQUIP_UTILITY
-
-//////////////
-//Defensive//
-//////////////
-
-/obj/item/mecha_parts/mecha_equipment/shocker
- name = "exosuit electrifier"
- desc = "A device to electrify the external portions of a mecha in order to increase its defensive capabilities."
- icon_state = "mecha_coil"
- equip_cooldown = 10
- energy_drain = 100
- range = RANGED
- origin_tech = list(TECH_COMBAT = 3, TECH_POWER = 6)
- var/shock_damage = 15
- var/active
-
- equip_type = EQUIP_HULL
-
-/obj/item/mecha_parts/mecha_equipment/shocker/can_attach(obj/mecha/M as obj)
- if(..())
- if(!M.proc_res["dynattackby"] && !M.proc_res["dynattackhand"] && !M.proc_res["dynattackalien"])
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/shocker/attach(obj/mecha/M as obj)
- ..()
- chassis.proc_res["dynattackby"] = src
- return
-
-/obj/item/mecha_parts/mecha_equipment/shocker/proc/dynattackby(obj/item/weapon/W, mob/living/user)
- if(!action_checks(user) || !active)
- return
- user.electrocute_act(shock_damage, src)
- return chassis.dynattackby(W,user)
+ P.dispersion = max(P.dispersion + M.accuracy_dispersion, 0)
\ No newline at end of file
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 5dd88eb7e7..938a720c4f 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -56,7 +56,7 @@
/obj/mecha/working/ripley/deathripley/Initialize()
..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/safety
ME.attach(src)
return
diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm
index f74770664b..e3607fdeea 100644
--- a/code/game/objects/structures/loot_piles.dm
+++ b/code/game/objects/structures/loot_piles.dm
@@ -680,7 +680,7 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
)
uncommon_loot = list(
- /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp,
+ /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/safety,
/obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser,
/obj/item/mecha_parts/mecha_equipment/repair_droid,
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
diff --git a/vorestation.dme b/vorestation.dme
index e54bf5a45c..61c330d021 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -882,10 +882,50 @@
#include "code\game\mecha\combat\marauder.dm"
#include "code\game\mecha\combat\phazon.dm"
#include "code\game\mecha\equipment\mecha_equipment.dm"
+<<<<<<< HEAD:vorestation.dme
#include "code\game\mecha\equipment\tools\medical_tools.dm"
#include "code\game\mecha\equipment\tools\medical_tools_vr.dm"
+=======
+#include "code\game\mecha\equipment\tools\armor_melee.dm"
+#include "code\game\mecha\equipment\tools\armor_ranged.dm"
+#include "code\game\mecha\equipment\tools\cable_layer.dm"
+#include "code\game\mecha\equipment\tools\catapult.dm"
+#include "code\game\mecha\equipment\tools\clamp.dm"
+#include "code\game\mecha\equipment\tools\drill.dm"
+#include "code\game\mecha\equipment\tools\energy_relay.dm"
+#include "code\game\mecha\equipment\tools\extinguisher.dm"
+#include "code\game\mecha\equipment\tools\generator.dm"
+#include "code\game\mecha\equipment\tools\jetpack.dm"
+#include "code\game\mecha\equipment\tools\orescanner.dm"
+#include "code\game\mecha\equipment\tools\passenger.dm"
+#include "code\game\mecha\equipment\tools\rcd.dm"
+#include "code\game\mecha\equipment\tools\repair_droid.dm"
+#include "code\game\mecha\equipment\tools\shield.dm"
+#include "code\game\mecha\equipment\tools\sleeper.dm"
+#include "code\game\mecha\equipment\tools\speedboost.dm"
+#include "code\game\mecha\equipment\tools\syringe_gun.dm"
+#include "code\game\mecha\equipment\tools\teleporter.dm"
+>>>>>>> e749b79... Fixes mech projectile armor thinking test projectiles are dangerous (#6480):polaris.dme
#include "code\game\mecha\equipment\tools\tools.dm"
+#include "code\game\mecha\equipment\tools\wormhole.dm"
+#include "code\game\mecha\equipment\tools\wrench.dm"
+#include "code\game\mecha\equipment\weapons\honk.dm"
#include "code\game\mecha\equipment\weapons\weapons.dm"
+#include "code\game\mecha\equipment\weapons\ballistic\automatic.dm"
+#include "code\game\mecha\equipment\weapons\ballistic\ballistic.dm"
+#include "code\game\mecha\equipment\weapons\ballistic\mortar.dm"
+#include "code\game\mecha\equipment\weapons\ballistic\shotgun.dm"
+#include "code\game\mecha\equipment\weapons\defense\shocker.dm"
+#include "code\game\mecha\equipment\weapons\energy\energy.dm"
+#include "code\game\mecha\equipment\weapons\energy\ion.dm"
+#include "code\game\mecha\equipment\weapons\energy\laser.dm"
+#include "code\game\mecha\equipment\weapons\energy\phased.dm"
+#include "code\game\mecha\equipment\weapons\energy\pulse.dm"
+#include "code\game\mecha\equipment\weapons\energy\stun.dm"
+#include "code\game\mecha\equipment\weapons\explosive\grenade.dm"
+#include "code\game\mecha\equipment\weapons\explosive\missile.dm"
+#include "code\game\mecha\equipment\weapons\fire\flamethrower.dm"
+#include "code\game\mecha\equipment\weapons\fire\incendiary.dm"
#include "code\game\mecha\medical\medical.dm"
#include "code\game\mecha\medical\odysseus.dm"
#include "code\game\mecha\micro\mecha_construction_paths_vr.dm"