[get_available_reagents()]
@@ -151,9 +136,9 @@
"}
-/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_dam()
+/obj/item/mecha_parts/mecha_equipment/sleeper/proc/get_patient_dam()
var/t1
- switch(occupant.stat)
+ switch(patient.stat)
if(0)
t1 = "Conscious"
if(1)
@@ -162,26 +147,26 @@
t1 = "*dead*"
else
t1 = "Unknown"
- return {"
Health: [occupant.stat > 1 ? "[t1]" : "[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()]%
-
[occupant.getCloneLoss() ? "Subject appears to have cellular damage." : ""]
-
[occupant.getBrainLoss() ? "Significant brain damage detected." : ""]
+ return {"
Health: [patient.stat > 1 ? "[t1]" : "[patient.health]% ([t1])"]
+
Core Temperature: [patient.bodytemperature-T0C]°C ([patient.bodytemperature*1.8-459.67]°F)
+
Brute Damage: [patient.getBruteLoss()]%
+
Respiratory Damage: [patient.getOxyLoss()]%
+
Toxin Content: [patient.getToxLoss()]%
+
Burn Severity: [patient.getFireLoss()]%
+
[patient.getCloneLoss() ? "Subject appears to have cellular damage." : ""]
+
[patient.getBrainLoss() ? "Significant brain damage detected." : ""]
"}
-/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)
+/obj/item/mecha_parts/mecha_equipment/sleeper/proc/get_patient_reagents()
+ if(patient.reagents)
+ for(var/datum/reagent/R in patient.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()
+/obj/item/mecha_parts/mecha_equipment/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
+ var/obj/item/mecha_parts/mecha_equipment/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/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)
@@ -189,41 +174,41 @@
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))
+/obj/item/mecha_parts/mecha_equipment/sleeper/proc/inject_reagent(var/datum/reagent/R,var/obj/item/mecha_parts/mecha_equipment/syringe_gun/SG)
+ if(!R || !patient || !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*2)
- occupant_message("Injecting [occupant] with [to_inject] units of [R.name].")
- log_message("Injecting [occupant] with [to_inject] units of [R.name].")
- add_logs(chassis.occupant, occupant, "injected", object="[name] ([R] - [to_inject] units)")
- SG.reagents.trans_id_to(occupant,R.id,to_inject)
+ if(to_inject && patient.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2)
+ occupant_message("Injecting [patient] with [to_inject] units of [R.name].")
+ log_message("Injecting [patient] with [to_inject] units of [R.name].")
+ add_logs(chassis.occupant, patient, "injected", object="[name] ([R] - [to_inject] units)")
+ SG.reagents.trans_id_to(patient,R.id,to_inject)
update_equip_info()
return
-/obj/item/mecha_parts/mecha_equipment/tool/sleeper/update_equip_info()
+/obj/item/mecha_parts/mecha_equipment/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","lossinfo",get_patient_dam())
+ send_byjax(chassis.occupant,"msleeper.browser","reagents",get_patient_reagents())
send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents())
return 1
return
-/obj/item/mecha_parts/mecha_equipment/tool/sleeper/container_resist()
+/obj/item/mecha_parts/mecha_equipment/sleeper/container_resist()
go_out()
-/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
+/obj/item/mecha_parts/mecha_equipment/sleeper/process()
+ if(!chassis)
+ SSobj.processing.Remove(src)
+ return
+ if(!chassis.has_charge(energy_drain))
+ set_ready_state(1)
+ log_message("Deactivated.")
+ occupant_message("[src] deactivated - no power.")
+ SSobj.processing.Remove(src)
+ return
+ var/mob/living/carbon/M = patient
if(!M)
return
if(M.health > 0)
@@ -234,11 +219,16 @@
M.AdjustStunned(-4)
if(M.reagents.get_reagent_amount("epinephrine") < 5)
M.reagents.add_reagent("epinephrine", 5)
- S.chassis.use_power(S.energy_drain)
- S.update_equip_info()
- return
+ chassis.use_power(energy_drain)
+ update_equip_info()
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
+
+
+
+///////////////////////////////// Syringe Gun ///////////////////////////////////////////////////////////////
+
+
+/obj/item/mecha_parts/mecha_equipment/syringe_gun
name = "exosuit syringe gun"
desc = "Equipment for medical exosuits. A chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur."
icon = 'icons/obj/guns/projectile.dmi'
@@ -251,42 +241,44 @@
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 = "materials=3;biotech=4;magnets=4;programming=3"
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/New()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/New()
..()
flags |= NOREACT
syringes = new
known_reagents = list("epinephrine"="Epinephrine","charcoal"="Charcoal")
processed_reagents = new
create_reagents(max_volume)
- synth = new (list(src),0)
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/detach()
- synth.stop()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/detach()
+ SSobj.processing.Remove(src)
return ..()
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/critfail()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/Destroy()
+ SSobj.processing.Remove(src)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/critfail()
..()
flags &= ~NOREACT
return
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/can_attach(obj/mecha/medical/M)
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/can_attach(obj/mecha/medical/M)
if(..())
if(istype(M))
return 1
return 0
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/get_equip_info()
+/obj/item/mecha_parts/mecha_equipment/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)
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/action(atom/movable/target)
if(!action_checks(target))
return
if(istype(target,/obj/item/weapon/reagent_containers/syringe))
@@ -303,8 +295,6 @@
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/mechsyringe = syringes[1]
mechsyringe.forceMove(get_turf(chassis))
@@ -315,7 +305,7 @@
playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
log_message("Launched [mechsyringe] from [src], targeting [target].")
var/mob/originaloccupant = chassis.occupant
- spawn(-1)
+ spawn(0)
src = null //if src is deleted, still process the syringe
for(var/i=0, i<6, i++)
if(!mechsyringe)
@@ -350,11 +340,10 @@
mechsyringe.update_icon()
break
sleep(1)
- do_after_cooldown()
return 1
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/Topic(href,href_list)
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/Topic(href,href_list)
..()
var/datum/topic_input/filter = new (href,href_list)
if(filter.get("toggle_mode"))
@@ -375,7 +364,7 @@
m++
if(processed_reagents.len)
message += " added to production"
- synth.start()
+ SSobj.processing |= src
occupant_message(message)
occupant_message("Reagent processing started.")
log_message("Reagent processing started.")
@@ -392,7 +381,7 @@
return
return
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_page()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/proc/get_reagents_page()
var/output = {"
Reagent Synthesizer
@@ -420,7 +409,7 @@
"}
return output
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_form()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/proc/get_reagents_form()
var/r_list = get_reagents_list()
var/inputs
if(r_list)
@@ -435,14 +424,14 @@
"}
return output
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_list()
+/obj/item/mecha_parts/mecha_equipment/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()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/proc/get_current_reagents()
var/output
for(var/datum/reagent/R in reagents.reagent_list)
if(R.volume > 0)
@@ -451,7 +440,7 @@
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)
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S)
if(syringes.len
= 2)
occupant_message("The syringe is too far away.")
@@ -473,7 +462,7 @@
occupant_message("The [src] syringe chamber is full.")
return 0
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/analyze_reagents(atom/A)
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/proc/analyze_reagents(atom/A)
if(get_dist(src,A) >= 4)
occupant_message("The object is too far away.")
return 0
@@ -488,42 +477,38 @@
occupant_message("Analyzis 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()
+/obj/item/mecha_parts/mecha_equipment/syringe_gun/proc/add_known_reagent(r_id,r_name)
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()
+/obj/item/mecha_parts/mecha_equipment/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()
+/obj/item/mecha_parts/mecha_equipment/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()
- if(anyprob(S.reliability))
- S.critfail()
- 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/syringe_gun/process()
+ if(!chassis)
+ SSobj.processing.Remove(src)
+ return
+ if(!processed_reagents.len || reagents.total_volume >= reagents.maximum_volume || !chassis.has_charge(energy_drain))
+ occupant_message("Reagent processing stopped.")
+ log_message("Reagent processing stopped.")
+ SSobj.processing.Remove(src)
+ if(anyprob(reliability))
+ critfail()
+ var/amount = synth_speed / processed_reagents.len
+ for(var/reagent in processed_reagents)
+ reagents.add_reagent(reagent,amount)
+ chassis.use_power(energy_drain)
+
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm
new file mode 100644
index 00000000000..0cc2255b75f
--- /dev/null
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -0,0 +1,127 @@
+
+// Drill, Diamond drill, Mining scanner
+
+
+/obj/item/mecha_parts/mecha_equipment/drill
+ name = "exosuit drill"
+ desc = "Equipment for engineering and combat exosuits. This is the drill that'll pierce the heavens!"
+ icon_state = "mecha_drill"
+ equip_cooldown = 30
+ energy_drain = 10
+ force = 15
+
+/obj/item/mecha_parts/mecha_equipment/drill/action(atom/target)
+ if(!action_checks(target))
+ return
+ if(istype(target, /turf) && !istype(target, /turf/simulated))
+ return
+ if(isobj(target))
+ var/obj/target_obj = target
+ if(target_obj.unacidable)
+ return
+ target.visible_message("[chassis] starts to drill [target]. ", \
+ "[chassis] starts to drill [target]... ", \
+ "You hear drilling. ")
+
+ if(do_after_cooldown(target))
+ if(istype(target, /turf/simulated/wall/r_wall))
+ if(istype(src , /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill))
+ if(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
+ occupant_message("[target] is too durable to drill through. ")
+ else if(istype(target, /turf/simulated/mineral))
+ for(var/turf/simulated/mineral/M in range(chassis,1))
+ if(get_dir(chassis,M)&chassis.dir)
+ M.gets_drilled(chassis.occupant)
+ log_message("Drilled through [target]")
+ if(locate(/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) in chassis.equipment)
+ var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
+ if(ore_box)
+ for(var/obj/item/weapon/ore/ore in range(chassis,1))
+ if(get_dir(chassis,ore)&chassis.dir)
+ ore.Move(ore_box)
+ else if(istype(target, /turf/simulated/floor/plating/asteroid))
+ for(var/turf/simulated/floor/plating/asteroid/M in range(chassis,1))
+ if(get_dir(chassis,M)&chassis.dir)
+ M.gets_dug()
+ log_message("Drilled through [target]")
+ if(locate(/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) in chassis.equipment)
+ var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
+ if(ore_box)
+ for(var/obj/item/weapon/ore/ore in range(chassis,1))
+ if(get_dir(chassis,ore)&chassis.dir)
+ ore.Move(ore_box)
+ else
+ log_message("Drilled through [target]")
+ if(isliving(target))
+ if(istype(src , /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill))
+ drill_mob(target, chassis.occupant, 120)
+ else
+ drill_mob(target, chassis.occupant)
+ else
+ target.ex_act(2)
+
+
+/obj/item/mecha_parts/mecha_equipment/drill/can_attach(obj/mecha/M as obj)
+ if(..())
+ if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80)
+ target.visible_message("[chassis] drills [target] with [src]. ", \
+ "[chassis] drills [target] with [src]. ")
+ add_logs(user, target, "attacked", object="[name]", addition="(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/limb/affecting = H.get_organ("chest")
+ affecting.take_damage(drill_damage)
+ H.update_damage_overlays(0)
+ else
+ target.take_organ_damage(drill_damage)
+ if(target)
+ target.Paralyse(10)
+ target.updatehealth()
+
+
+
+/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill
+ name = "diamond-tipped exosuit drill"
+ desc = "Equipment for engineering and combat exosuits. This is an upgraded version of the drill that'll pierce the heavens!"
+ icon_state = "mecha_diamond_drill"
+ origin_tech = "materials=4;engineering=3"
+ equip_cooldown = 20
+ force = 15
+
+
+
+/obj/item/mecha_parts/mecha_equipment/mining_scanner
+ name = "exosuit mining scanner"
+ desc = "Equipment for engineering and combat exosuits. It will automatically check surrounding rock for useful minerals."
+ icon_state = "mecha_analyzer"
+ origin_tech = "materials=3;engineering=2"
+ equip_cooldown = 30
+ var/scanning = 0
+
+/obj/item/mecha_parts/mecha_equipment/mining_scanner/New()
+ SSobj.processing |= src
+
+/obj/item/mecha_parts/mecha_equipment/mining_scanner/process()
+ if(!loc)
+ SSobj.processing.Remove(src)
+ qdel(src)
+ if(scanning)
+ return
+ if(istype(loc,/obj/mecha/working))
+ var/obj/mecha/working/mecha = loc
+ if(!mecha.occupant)
+ return
+ var/list/occupant = list()
+ occupant |= mecha.occupant
+ scanning = 1
+ mineral_scan_pulse(occupant,get_turf(loc))
+ spawn(equip_cooldown)
+ scanning = 0
+
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
new file mode 100644
index 00000000000..56e6aa089d2
--- /dev/null
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -0,0 +1,518 @@
+
+// Teleporter, Wormhole generator, Gravitational catapult, Armor booster modules,
+// Repair droid, Tesla Energy relay, Generators
+
+////////////////////////////////////////////// TELEPORTER ///////////////////////////////////////////////
+
+/obj/item/mecha_parts/mecha_equipment/teleporter
+ name = "mounted teleporter"
+ desc = "An exosuit module that allows exosuits to teleport to any position in view."
+ icon_state = "mecha_teleport"
+ origin_tech = "bluespace=10"
+ equip_cooldown = 150
+ energy_drain = 1000
+ range = RANGED
+
+/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target)
+ if(!action_checks(target) || src.loc.z == ZLEVEL_CENTCOM) return
+ var/turf/T = get_turf(target)
+ if(T)
+ do_teleport(chassis, T, 4)
+ return 1
+
+
+
+////////////////////////////////////////////// WORMHOLE GENERATOR //////////////////////////////////////////
+
+/obj/item/mecha_parts/mecha_equipment/wormhole_generator
+ name = "mounted wormhole generator"
+ desc = "An exosuit module that allows generating of small quasi-stable wormholes."
+ icon_state = "mecha_wholegen"
+ origin_tech = "bluespace=3"
+ equip_cooldown = 50
+ energy_drain = 300
+ range = RANGED
+
+
+/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target)
+ if(!action_checks(target) || src.loc.z == ZLEVEL_CENTCOM) 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
+ 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.icon_state = "anom"
+ P.name = "wormhole"
+ var/turf/T = get_turf(target)
+ message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](? ) (FLW ) used a Wormhole Generator in ([T.x],[T.y],[T.z] - JMP )",0,1)
+ log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([T.x],[T.y],[T.z])")
+ src = null
+ spawn(rand(150,300))
+ qdel(P)
+ return 1
+
+
+/////////////////////////////////////// GRAVITATIONAL CATAPULT ///////////////////////////////////////////
+
+/obj/item/mecha_parts/mecha_equipment/gravcatapult
+ name = "mounted gravitational catapult"
+ desc = "An exosuit mounted Gravitational Catapult."
+ icon_state = "mecha_teleport"
+ origin_tech = "bluespace=2;magnets=3"
+ equip_cooldown = 10
+ energy_drain = 100
+ range = MELEE|RANGED
+ var/atom/movable/locked
+ var/mode = 1 //1 - gravsling 2 - gravpush
+
+
+/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target)
+ if(!action_checks(target))
+ return
+ switch(mode)
+ if(1)
+ 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())
+ else if(target!=locked)
+ if(locked in view(chassis))
+ locked.throw_at(target, 14, 1.5)
+ locked = null
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+ return 1
+ else
+ locked = null
+ occupant_message("Lock on [locked] disengaged.")
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+ if(2)
+ 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)
+ var/turf/T = get_turf(target)
+ log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Gravitational Catapult in ([T.x],[T.y],[T.z])")
+ return 1
+
+
+/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
+
+
+
+
+//////////////////////////// ARMOR BOOSTER MODULES //////////////////////////////////////////////////////////
+
+
+/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants.
+ name = "armor booster module (Close Combat Weaponry)"
+ desc = "Boosts exosuit armor against armed melee attacks. Requires energy to operate."
+ icon_state = "mecha_abooster_ccw"
+ origin_tech = "materials=3"
+ equip_cooldown = 10
+ energy_drain = 50
+ range = 0
+ var/deflect_coeff = 1.15
+ var/damage_coeff = 0.8
+
+/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/can_attach(obj/mecha/combat/M as obj)
+ if(..())
+ if(istype(M))
+ return 1
+
+/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/attack_react(mob/user as mob)
+ if(action_checks(user))
+ start_cooldown()
+ return 1
+
+
+
+/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster
+ name = "armor booster module (Ranged Weaponry)"
+ desc = "Boosts exosuit armor against ranged attacks. Completely blocks taser shots. Requires energy to operate."
+ icon_state = "mecha_abooster_proj"
+ origin_tech = "materials=4"
+ equip_cooldown = 10
+ energy_drain = 50
+ range = 0
+ var/deflect_coeff = 1.15
+ var/damage_coeff = 0.8
+
+/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/can_attach(obj/mecha/combat/M as obj)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/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/projectile_react()
+ if(action_checks(src))
+ start_cooldown()
+ return 1
+
+
+////////////////////////////////// REPAIR DROID //////////////////////////////////////////////////
+
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid
+ name = "exosuit repair droid"
+ desc = "An automated repair droid for exosuits. Scans for damage and repairs it. Can fix almost all types of external or internal damage."
+ icon_state = "repair_droid"
+ origin_tech = "magnets=3;programming=3"
+ energy_drain = 50
+ range = 0
+ var/health_boost = 1
+ var/icon/droid_overlay
+ var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH)
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy()
+ SSobj.processing.Remove(src)
+ if(chassis)
+ chassis.overlays -= droid_overlay
+ ..()
+
+/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
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
+ chassis.overlays -= droid_overlay
+ SSobj.processing.Remove(src)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info()
+ if(!chassis) return
+ return "* [src.name] - [equip_ready?"A":"Dea"]ctivate "
+
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list)
+ ..()
+ if(href_list["toggle_repairs"])
+ chassis.overlays -= droid_overlay
+ if(equip_ready)
+ SSobj.processing |= src
+ droid_overlay = new(src.icon, icon_state = "repair_droid_a")
+ log_message("Activated.")
+ set_ready_state(0)
+ else
+ SSobj.processing.Remove(src)
+ 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())
+
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/process()
+ if(!chassis)
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+ return
+ var/h_boost = health_boost
+ var/repaired = 0
+ if(chassis.internal_damage & MECHA_INT_SHORT_CIRCUIT)
+ h_boost *= -2
+ else if(chassis.internal_damage && prob(15))
+ for(var/int_dam_flag in repairable_damage)
+ if(chassis.internal_damage & int_dam_flag)
+ chassis.clearInternalDamage(int_dam_flag)
+ repaired = 1
+ break
+ if(health_boost<0 || chassis.health < initial(chassis.health))
+ chassis.health += min(health_boost, initial(chassis.health)-chassis.health)
+ repaired = 1
+ if(repaired)
+ if(!chassis.use_power(energy_drain))
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+ else //no repair needed, we turn off
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+
+
+
+
+
+/////////////////////////////////// TESLA ENERGY RELAY ////////////////////////////////////////////////
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
+ name = "exosuit energy relay"
+ desc = "An exosuit module that wirelessly drains energy from any available power channel in area. The performance index is quite low."
+ icon_state = "tesla"
+ origin_tech = "magnets=4;powerstorage=3"
+ energy_drain = 0
+ range = 0
+ var/coeff = 100
+ var/list/use_channels = list(EQUIP,ENVIRON,LIGHT)
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy()
+ SSobj.processing.Remove(src)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach()
+ SSobj.processing.Remove(src)
+ ..()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge()
+ if(equip_ready) //disabled
+ return
+ var/area/A = get_area(chassis)
+ var/pow_chan = get_power_channel(A)
+ if(pow_chan)
+ return 1000 //making magic
+
+
+/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.master && A.master.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(equip_ready) //inactive
+ SSobj.processing |= src
+ set_ready_state(0)
+ log_message("Activated.")
+ else
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+ log_message("Deactivated.")
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info()
+ if(!chassis) return
+ return "* [src.name] - [equip_ready?"A":"Dea"]ctivate "
+
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/process()
+ if(!chassis || chassis.internal_damage & MECHA_INT_SHORT_CIRCUIT)
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+ return
+ var/cur_charge = chassis.get_charge()
+ if(isnull(cur_charge) || !chassis.cell)
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+ occupant_message("No powercell detected.")
+ return
+ if(cur_charge < chassis.cell.maxcharge)
+ var/area/A = get_area(chassis)
+ if(A)
+ var/pow_chan
+ for(var/c in list(EQUIP,ENVIRON,LIGHT))
+ if(A.master.powered(c))
+ pow_chan = c
+ break
+ if(pow_chan)
+ var/delta = min(15, chassis.cell.maxcharge-cur_charge)
+ chassis.give_power(delta)
+ A.master.use_power(delta*coeff, pow_chan)
+
+
+
+
+/////////////////////////////////////////// GENERATOR /////////////////////////////////////////////
+
+
+/obj/item/mecha_parts/mecha_equipment/generator
+ name = "exosuit plasma converter"
+ desc = "An exosuit module that generates power using solid plasma as fuel. Pollutes the environment."
+ icon_state = "tesla"
+ origin_tech = "plasmatech=2;powerstorage=2;engineering=1"
+ range = MELEE
+ var/coeff = 100
+ var/obj/item/stack/sheet/fuel
+ var/max_fuel = 150000
+ var/fuel_per_cycle_idle = 25
+ var/fuel_per_cycle_active = 200
+ var/power_per_cycle = 20
+ reliability = 1000
+
+/obj/item/mecha_parts/mecha_equipment/generator/New()
+ ..()
+ generator_init()
+
+/obj/item/mecha_parts/mecha_equipment/generator/Destroy()
+ SSobj.processing.Remove(src)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/generator/proc/generator_init()
+ fuel = new /obj/item/stack/sheet/mineral/plasma(src)
+ fuel.amount = 0
+
+/obj/item/mecha_parts/mecha_equipment/generator/detach()
+ SSobj.processing.Remove(src)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/generator/Topic(href, href_list)
+ ..()
+ if(href_list["toggle"])
+ if(equip_ready) //inactive
+ set_ready_state(0)
+ SSobj.processing |= src
+ log_message("Activated.")
+ else
+ set_ready_state(1)
+ SSobj.processing.Remove(src)
+ log_message("Deactivated.")
+
+/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 \] - [equip_ready?"A":"Dea"]ctivate "
+
+/obj/item/mecha_parts/mecha_equipment/generator/action(target)
+ if(chassis)
+ var/result = load_fuel(target)
+ if(result)
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+
+/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P)
+ if(P.type == fuel.type && P.amount > 0)
+ 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)
+ fuel.amount += units
+ P.use(units)
+ occupant_message("[units] unit\s of [fuel] successfully loaded.")
+ return units
+ else
+ occupant_message("Unit is full.")
+ return 0
+ else
+ occupant_message("[fuel] traces in target minimal! [P] cannot be used as fuel. ")
+ return
+
+/obj/item/mecha_parts/mecha_equipment/generator/attackby(weapon,mob/user, params)
+ load_fuel(weapon)
+
+/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))
+ GM.toxins += 100
+ GM.temperature = 1500+T0C //should be enough to start a fire
+ T.visible_message("The [src] suddenly disgorges a cloud of heated plasma.")
+ qdel(src)
+ else
+ GM.toxins += 5
+ GM.temperature = istype(T) ? T.air.return_temperature() : T20C
+ T.visible_message("The [src] suddenly disgorges a cloud of plasma.")
+ T.assume_air(GM)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/generator/process()
+ if(!chassis)
+ SSobj.processing.Remove(src)
+ set_ready_state(1)
+ return
+ if(fuel.amount<=0)
+ SSobj.processing.Remove(src)
+ log_message("Deactivated - no fuel.")
+ set_ready_state(1)
+ return
+ if(anyprob(reliability))
+ set_ready_state(1) //inactive
+ critfail()
+ SSobj.processing.Remove(src)
+ return
+ var/cur_charge = chassis.get_charge()
+ if(isnull(cur_charge))
+ set_ready_state(1)
+ occupant_message("No powercell detected.")
+ log_message("Deactivated.")
+ SSobj.processing.Remove(src)
+ return
+ var/use_fuel = fuel_per_cycle_idle
+ if(cur_charge < chassis.cell.maxcharge)
+ use_fuel = fuel_per_cycle_active
+ chassis.give_power(power_per_cycle)
+ fuel.amount -= min(use_fuel/fuel.perunit,fuel.amount)
+ update_equip_info()
+ return 1
+
+
+/obj/item/mecha_parts/mecha_equipment/generator/nuclear
+ name = "exonuclear reactor"
+ desc = "An exosuit module that generates power using uranium as fuel. Pollutes the environment."
+ icon_state = "tesla"
+ origin_tech = "powerstorage=3;engineering=3"
+ max_fuel = 50000
+ fuel_per_cycle_idle = 10
+ fuel_per_cycle_active = 30
+ power_per_cycle = 50
+ var/rad_per_cycle = 0.3
+ reliability = 1000
+
+/obj/item/mecha_parts/mecha_equipment/generator/nuclear/generator_init()
+ fuel = new /obj/item/stack/sheet/mineral/uranium(src)
+ fuel.amount = 0
+
+/obj/item/mecha_parts/mecha_equipment/generator/nuclear/critfail()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/generator/nuclear/process()
+ if(..())
+ for(var/mob/living/carbon/M in view(chassis))
+ if(istype(M,/mob/living/carbon/human))
+ M.irradiate(rad_per_cycle*3)
+ else
+ M.irradiate(rad_per_cycle)
+
+
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
deleted file mode 100644
index 7b9a4867f03..00000000000
--- a/code/game/mecha/equipment/tools/tools.dm
+++ /dev/null
@@ -1,1245 +0,0 @@
-/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp
- name = "hydraulic clamp"
- desc = "Equipment for engineering exosuits. Lifts objects and loads them into cargo."
- icon_state = "mecha_clamp"
- equip_cooldown = 15
- energy_drain = 10
- var/dam_force = 20
- var/obj/mecha/working/ripley/cargo_holder
-
-/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
- if(..())
- if(istype(M))
- return 1
- return 0
-
-/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/detach(atom/moveto = null)
- ..()
- if(can_attach(chassis))
- cargo_holder = chassis
- else
- cargo_holder = null
-
-/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target)
- if(!action_checks(target))
- return
- if(!cargo_holder)
- return
- if(istype(target,/obj))
- var/obj/O = target
- if(!O.anchored)
- if(cargo_holder.cargo.len < cargo_holder.cargo_capacity)
- 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] successfully 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)
- else
- occupant_message("Not enough room in cargo compartment! ")
- else
- 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 == "harm")
- M.take_overall_damage(dam_force)
- if(!M)
- return
- M.adjustOxyLoss(round(dam_force/2))
- M.updatehealth()
- target.visible_message("[chassis] squeezes [target]. ", \
- "[chassis] squeezes [target]. ",\
- "You hear something crack. ")
- add_logs(chassis.occupant, M, "attacked", object="[name]", addition="(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])")
- 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 = "exosuit drill"
- desc = "Equipment for engineering and combat exosuits. This is the drill that'll pierce the heavens!"
- icon_state = "mecha_drill"
- equip_cooldown = 30
- energy_drain = 10
- force = 15
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target)
- if(!action_checks(target))
- return
- if(istype(target, /turf) && !istype(target, /turf/simulated))
- return
- if(isobj(target))
- var/obj/target_obj = target
- if(target_obj.unacidable)
- return
- set_ready_state(0)
- chassis.use_power(energy_drain)
- target.visible_message("[chassis] starts to drill [target]. ", \
- "[chassis] starts to drill [target]... ", \
- "You hear drilling. ")
- 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/r_wall))
- if(istype(src , /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill))
- if(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
- occupant_message("[target] is too durable to drill through. ")
- else if(istype(target, /turf/simulated/mineral))
- for(var/turf/simulated/mineral/M in range(chassis,1))
- if(get_dir(chassis,M)&chassis.dir)
- M.gets_drilled(chassis.occupant)
- 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.Move(ore_box)
- else if(istype(target, /turf/simulated/floor/plating/asteroid))
- for(var/turf/simulated/floor/plating/asteroid/M in range(chassis,1))
- if(get_dir(chassis,M)&chassis.dir)
- M.gets_dug()
- 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.Move(ore_box)
- else if(target.loc == C)
- log_message("Drilled through [target]")
- if(isliving(target))
- if(istype(src , /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill))
- drill_mob(target, chassis.occupant, 120)
- else
- drill_mob(target, chassis.occupant)
- else
- target.ex_act(2)
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill/can_attach(obj/mecha/M as obj)
- if(..())
- if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat))
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80)
- target.visible_message("[chassis] drills [target] with [src]. ", \
- "[chassis] drills [target] with [src]. ")
- add_logs(user, target, "attacked", object="[name]", addition="(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- var/obj/item/organ/limb/affecting = H.get_organ("chest")
- affecting.take_damage(drill_damage)
- H.update_damage_overlays(0)
- else
- target.take_organ_damage(drill_damage)
- if(target)
- target.Paralyse(10)
- target.updatehealth()
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
- name = "diamond-tipped exosuit drill"
- desc = "Equipment for engineering and combat exosuits. This is an upgraded version of the drill that'll pierce the heavens!"
- icon_state = "mecha_diamond_drill"
- origin_tech = "materials=4;engineering=3"
- equip_cooldown = 20
- force = 15
-
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/can_attach(obj/mecha/M as obj)
- if(..())
- if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat))
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner
- name = "exosuit mining scanner"
- desc = "Equipment for engineering and combat exosuits. It will automatically check surrounding rock for useful minerals."
- icon_state = "mecha_analyzer"
- origin_tech = "materials=3;engineering=2"
- equip_cooldown = 30
- var/scanning = 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/New()
- SSobj.processing |= src
-
-/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/process()
- if(!loc)
- SSobj.processing.Remove(src)
- qdel(src)
- if(scanning)
- return
- if(istype(loc,/obj/mecha/working))
- var/obj/mecha/working/mecha = loc
- if(!mecha.occupant)
- return
- var/list/occupant = list()
- occupant |= mecha.occupant
- scanning = 1
- mineral_scan_pulse(occupant,get_turf(loc))
- spawn(equip_cooldown)
- scanning = 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/extinguisher
- name = "exosuit extinguisher"
- desc = "Equipment for engineering exosuits. A rapid-firing high capacity fire extinguisher."
- icon_state = "mecha_exting"
- equip_cooldown = 5
- energy_drain = 0
- range = MELEE|RANGED
-
-/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/New()
- create_reagents(1000)
- reagents.add_reagent("water", 1000)
- ..()
- return
-
-/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
- o.reagents.trans_to(src, 1000)
- occupant_message("Extinguisher refilled. ")
- playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6)
- else
- if(src.reagents.total_volume > 0)
- 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)
- spawn(0)
- for(var/a=0, a<5, a++)
- var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(chassis))
- if(!W)
- return
- var/turf/my_target = pick(the_targets)
- var/datum/reagents/R = new/datum/reagents(5)
- W.reagents = R
- R.my_atom = W
- src.reagents.trans_to(W,1)
- for(var/b=0, b<4, b++)
- if(!W)
- return
- step_towards(W,my_target)
- if(!W)
- return
- var/turf/W_turf = get_turf(W)
- W.reagents.reaction(W_turf)
- for(var/atom/atm in W_turf)
- W.reagents.reaction(atm)
- if(W.loc == my_target)
- break
- sleep(2)
- 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/extinguisher/can_attach(obj/mecha/working/M as obj)
- if(..())
- if(istype(M))
- return 1
- return 0
-
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd
- name = "mounted RCD"
- desc = "An exosuit-mounted Rapid Construction Device."
- icon_state = "mecha_rcd"
- origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4"
- equip_cooldown = 10
- energy_drain = 250
- range = MELEE|RANGED
- var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
- var/disabled = 0 //malf
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/action(atom/target)
- if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve
- disabled = 1
- else
- disabled = 0
- if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock))
- target = get_turf(target)
- if(!action_checks(target) || disabled || get_dist(chassis, target)>3) return
- playsound(chassis, 'sound/machines/click.ogg', 50, 1)
- //meh
- switch(mode)
- if(0)
- if (istype(target, /turf/simulated/wall))
- var/turf/simulated/wall/W = target
- occupant_message("Deconstructing [W]...")
- set_ready_state(0)
- if(do_after_cooldown(W))
- if(disabled) return
- chassis.spark_system.start()
- W.ChangeTurf(/turf/simulated/floor/plating)
- playsound(W, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.use_power(energy_drain)
- else if (istype(target, /turf/simulated/floor))
- var/turf/simulated/floor/F = target
- occupant_message("Deconstructing [F]...")
- set_ready_state(0)
- if(do_after_cooldown(F))
- if(disabled) return
- chassis.spark_system.start()
- F.ChangeTurf(F.baseturf)
- playsound(F, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.use_power(energy_drain)
- else if (istype(target, /obj/machinery/door/airlock))
- occupant_message("Deconstructing [target]...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- if(disabled) return
- chassis.spark_system.start()
- qdel(target)
- playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.use_power(energy_drain)
- if(1)
- if(istype(target, /turf/space))
- var/turf/space/S = target
- occupant_message("Building Floor...")
- set_ready_state(0)
- if(do_after_cooldown(S))
- if(disabled) return
- S.ChangeTurf(/turf/simulated/floor/plating)
- playsound(S, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.spark_system.start()
- chassis.use_power(energy_drain*2)
- else if(istype(target, /turf/simulated/floor))
- var/turf/simulated/floor/F = target
- occupant_message("Building Wall...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- if(disabled) return
- F.ChangeTurf(/turf/simulated/wall)
- playsound(F, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.spark_system.start()
- chassis.use_power(energy_drain*2)
- if(2)
- if(istype(target, /turf/simulated/floor))
- occupant_message("Building Airlock...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- if(disabled) return
- chassis.spark_system.start()
- var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target)
- T.autoclose = 1
- playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
- playsound(target, 'sound/effects/sparks2.ogg', 50, 1)
- chassis.use_power(energy_drain*2)
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/Topic(href,href_list)
- ..()
- if(href_list["mode"])
- mode = text2num(href_list["mode"])
- switch(mode)
- if(0)
- occupant_message("Switched RCD to Deconstruct.")
- if(1)
- occupant_message("Switched RCD to Construct.")
- if(2)
- occupant_message("Switched RCD to Construct Airlock.")
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info()
- return "[..()] \[D |C |A \]"
-
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer
- name = "cable layer"
- desc = "Equipment for engineering exosuits. Lays cable along the exosuit's path."
- icon_state = "mecha_wire"
- var/datum/event/event
- var/turf/old_turf
- var/obj/structure/cable/last_piece
- var/obj/item/stack/cable_coil/cable
- var/max_cable = 1000
-
-/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/can_attach(obj/mecha/working/M)
- if(..())
- if(istype(M))
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/attach()
- ..()
- event = chassis.events.addEvent("onMove",src,"layCable")
- return
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/detach()
- chassis.events.clearEvent("onMove",event)
- return ..()
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/destroy()
- chassis.events.clearEvent("onMove",event)
- return ..()
-
-/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)
- if(istype(new_turf, /turf/simulated/floor))
- var/turf/simulated/floor/T = new_turf
- if(!istype(T, /turf/simulated/floor/plating))
- if(!T.broken && !T.burnt)
- new T.floor_tile(T)
- T.make_plating()
- return !new_turf.intact
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(var/turf/new_turf)
- if(equip_ready || !istype(new_turf) || !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.updateicon()
-
- 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.updateicon()
- PN = last_piece.powernet
-
- if(!PN)
- PN = new()
- powernets += PN
- NC.powernet = PN
- PN.cables += NC
- NC.mergeConnectedNetworks(NC.d2)
-
- //NC.mergeConnectedNetworksOnTurf()
- last_piece = NC
- return 1
-
-
-/obj/item/mecha_parts/mecha_equipment/teleporter
- name = "mounted teleporter"
- desc = "An exosuit module that allows exosuits to teleport to any position in view."
- icon_state = "mecha_teleport"
- origin_tech = "bluespace=10"
- equip_cooldown = 150
- energy_drain = 1000
- range = RANGED
-
-/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target)
- if(!action_checks(target) || src.loc.z == ZLEVEL_CENTCOM) 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 = "mounted wormhole generator"
- desc = "An exosuit module that allows generating of small quasi-stable wormholes."
- icon_state = "mecha_wholegen"
- origin_tech = "bluespace=3"
- equip_cooldown = 50
- energy_drain = 300
- range = RANGED
-
-
-/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target)
- if(!action_checks(target) || src.loc.z == ZLEVEL_CENTCOM) 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.icon_state = "anom"
- P.name = "wormhole"
- var/turf/T = get_turf(target)
- message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](? ) (FLW ) used a Wormhole Generator in ([T.x],[T.y],[T.z] - JMP )",0,1)
- log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([T.x],[T.y],[T.z])")
- do_after_cooldown()
- src = null
- spawn(rand(150,300))
- qdel(P)
- return
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult
- name = "mounted gravitational catapult"
- desc = "An exosuit mounted Gravitational Catapult."
- icon_state = "mecha_teleport"
- origin_tech = "bluespace=2;magnets=3"
- equip_cooldown = 10
- energy_drain = 100
- range = MELEE|RANGED
- var/atom/movable/locked
- var/mode = 1 //1 - gravsling 2 - gravpush
-
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target)
- 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)
- 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)
- var/turf/T = get_turf(target)
- log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Gravitational Catapult in ([T.x],[T.y],[T.z])")
- 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 = "armor booster module (Close Combat Weaponry)"
- desc = "Boosts exosuit armor against armed melee attacks. Requires energy to operate."
- icon_state = "mecha_abooster_ccw"
- origin_tech = "materials=3"
- equip_cooldown = 10
- energy_drain = 50
- range = 0
- var/deflect_coeff = 1.15
- var/damage_coeff = 0.8
-
-/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/can_attach(obj/mecha/M as obj)
- if(..())
- if(!istype(M, /obj/mecha/combat/honker))
- 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("[user] hits [chassis] with [W]. ")
- user.visible_message("[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 = "armor booster module (Ranged Weaponry)"
- desc = "Boosts exosuit armor against ranged attacks. Completely blocks taser shots. Requires energy to operate."
- icon_state = "mecha_abooster_proj"
- origin_tech = "materials=4"
- equip_cooldown = 10
- energy_drain = 50
- range = 0
- var/deflect_coeff = 1.15
- var/damage_coeff = 0.8
-
-/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/can_attach(obj/mecha/M as obj)
- if(..())
- if(!istype(M, /obj/mecha/combat/honker))
- 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.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.flag)
- 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.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 = "exosuit repair droid"
- desc = "An automated repair droid for exosuits. Scans for damage and repairs it. Can fix almost all types of external or internal damage."
- icon_state = "repair_droid"
- origin_tech = "magnets=3;programming=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)
-
-/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 = "exosuit energy relay"
- desc = "An exosuit module that wirelessly drains energy from any available power channel in area. The performance index is quite low."
- icon_state = "tesla"
- origin_tech = "magnets=4;powerstorage=3"
- 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)
-
-/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.master && A.master.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 "
-
-/*/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/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_charge3\] - [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/sheet/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, params)
- 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))
- GM.toxins += 100
- GM.temperature = 1500+T0C //should be enough to start a fire
- T.visible_message("The [src] suddenly disgorges a cloud of heated plasma.")
- destroy()
- else
- GM.toxins += 5
- GM.temperature = istype(T) ? T.air.return_temperature() : T20C
- T.visible_message("The [src] suddenly disgorges a cloud of plasma.")
- 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
- if(anyprob(EG.reliability))
- EG.critfail()
- stop()
- 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] successfully 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 == "harm")
- target.visible_message("[chassis] destroys [target] in an unholy fury. ", \
- "[chassis] destroys [target] in an unholy fury. ")
- if(chassis.occupant.a_intent == "disarm")
- target.visible_message("[chassis] rips [target]'s arms off. ", \
- "[chassis] rips [target]'s arms off. ")
- else
- step_away(M,chassis)
- target.visible_message("[chassis] tosses [target] like a piece of paper.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return 1
diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm
new file mode 100644
index 00000000000..515fe52c2a2
--- /dev/null
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -0,0 +1,424 @@
+
+//Hydraulic clamp, Kill clamp, Extinguisher, RCD, Cable layer.
+
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp
+ name = "hydraulic clamp"
+ desc = "Equipment for engineering exosuits. Lifts objects and loads them into cargo."
+ icon_state = "mecha_clamp"
+ equip_cooldown = 15
+ energy_drain = 10
+ var/dam_force = 20
+ var/obj/mecha/working/ripley/cargo_holder
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/attach(obj/mecha/M as obj)
+ ..()
+ cargo_holder = M
+ return
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/detach(atom/moveto = null)
+ ..()
+ cargo_holder = null
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/action(atom/target)
+ if(!action_checks(target))
+ return
+ if(!cargo_holder)
+ return
+ if(istype(target,/obj))
+ var/obj/O = target
+ if(!O.anchored)
+ if(cargo_holder.cargo.len < cargo_holder.cargo_capacity)
+ chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.")
+ O.anchored = 1
+ if(do_after_cooldown(target))
+ cargo_holder.cargo += O
+ O.loc = chassis
+ O.anchored = 0
+ occupant_message("[target] successfully loaded. ")
+ log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
+ else
+ O.anchored = initial(O.anchored)
+ else
+ occupant_message("Not enough room in cargo compartment! ")
+ else
+ occupant_message("[target] is firmly secured! ")
+
+ else if(istype(target,/mob/living))
+ var/mob/living/M = target
+ if(M.stat == DEAD) return
+ if(chassis.occupant.a_intent == "harm")
+ M.take_overall_damage(dam_force)
+ if(!M)
+ return
+ M.adjustOxyLoss(round(dam_force/2))
+ M.updatehealth()
+ target.visible_message("[chassis] squeezes [target]. ", \
+ "[chassis] squeezes [target]. ",\
+ "You hear something crack. ")
+ add_logs(chassis.occupant, M, "attacked", object="[name]", addition="(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])")
+ else
+ step_away(M,chassis)
+ occupant_message("You push [target] out of the way.")
+ chassis.visible_message("[chassis] pushes [target] out of the way.")
+ return 1
+
+
+
+//This is pretty much just for the death-ripley
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill
+ name = "\improper KILL CLAMP"
+ desc = "They won't know what clamped them!"
+ energy_drain = 0
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill/action(atom/target)
+ if(!action_checks(target)) return
+ if(!cargo_holder) return
+ if(istype(target,/obj))
+ var/obj/O = target
+ if(!O.anchored)
+ if(cargo_holder.cargo.len < cargo_holder.cargo_capacity)
+ chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.")
+ O.anchored = 1
+ if(do_after_cooldown(target))
+ cargo_holder.cargo += O
+ O.loc = chassis
+ O.anchored = 0
+ occupant_message("[target] successfully loaded. ")
+ log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
+ else
+ O.anchored = initial(O.anchored)
+ else
+ occupant_message("Not enough room in cargo compartment! ")
+ else
+ occupant_message("[target] is firmly secured! ")
+
+ else if(istype(target,/mob/living))
+ var/mob/living/M = target
+ if(M.stat == DEAD) return
+ if(chassis.occupant.a_intent == "harm")
+ target.visible_message("[chassis] destroys [target] in an unholy fury. ", \
+ "[chassis] destroys [target] in an unholy fury. ")
+ if(chassis.occupant.a_intent == "disarm")
+ target.visible_message("[chassis] rips [target]'s arms off. ", \
+ "[chassis] rips [target]'s arms off. ")
+ else
+ step_away(M,chassis)
+ target.visible_message("[chassis] tosses [target] like a piece of paper.")
+ return 1
+
+
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher
+ name = "exosuit extinguisher"
+ desc = "Equipment for engineering exosuits. A rapid-firing high capacity fire extinguisher."
+ icon_state = "mecha_exting"
+ equip_cooldown = 5
+ energy_drain = 0
+ range = MELEE|RANGED
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/New()
+ create_reagents(1000)
+ reagents.add_reagent("water", 1000)
+ ..()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch.
+ if(!action_checks(target) || get_dist(chassis, target)>3)
+ return
+
+ if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1)
+ var/obj/structure/reagent_dispensers/watertank/WT = target
+ WT.reagents.trans_to(src, 1000)
+ occupant_message("Extinguisher refilled. ")
+ playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6)
+ else
+ if(reagents.total_volume > 0)
+ 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)
+ spawn(0)
+ for(var/a=0, a<5, a++)
+ var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(chassis))
+ if(!W)
+ return
+ var/turf/my_target = pick(the_targets)
+ var/datum/reagents/R = new/datum/reagents(5)
+ W.reagents = R
+ R.my_atom = W
+ reagents.trans_to(W,1)
+ for(var/b=0, b<4, b++)
+ if(!W)
+ return
+ step_towards(W,my_target)
+ if(!W)
+ return
+ var/turf/W_turf = get_turf(W)
+ W.reagents.reaction(W_turf)
+ for(var/atom/atm in W_turf)
+ W.reagents.reaction(atm)
+ if(W.loc == my_target)
+ break
+ sleep(2)
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/get_equip_info()
+ return "[..()] \[[src.reagents.total_volume]\]"
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/on_reagent_change()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/can_attach(obj/mecha/working/M as obj)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+
+
+/obj/item/mecha_parts/mecha_equipment/rcd
+ name = "mounted RCD"
+ desc = "An exosuit-mounted Rapid Construction Device."
+ icon_state = "mecha_rcd"
+ origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4"
+ equip_cooldown = 10
+ energy_drain = 250
+ range = MELEE|RANGED
+ var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
+ var/disabled = 0 //malf
+
+/obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target)
+ if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve
+ disabled = 1
+ else
+ disabled = 0
+ if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock))
+ target = get_turf(target)
+ if(!action_checks(target) || disabled || get_dist(chassis, target)>3)
+ return
+ playsound(chassis, 'sound/machines/click.ogg', 50, 1)
+
+ switch(mode)
+ if(0)
+ if (istype(target, /turf/simulated/wall))
+ var/turf/simulated/wall/W = target
+ occupant_message("Deconstructing [W]...")
+ if(do_after_cooldown(W))
+ chassis.spark_system.start()
+ W.ChangeTurf(/turf/simulated/floor/plating)
+ playsound(W, 'sound/items/Deconstruct.ogg', 50, 1)
+ else if (istype(target, /turf/simulated/floor))
+ var/turf/simulated/floor/F = target
+ occupant_message("Deconstructing [F]...")
+ if(do_after_cooldown(target))
+ chassis.spark_system.start()
+ F.ChangeTurf(F.baseturf)
+ playsound(F, 'sound/items/Deconstruct.ogg', 50, 1)
+ else if (istype(target, /obj/machinery/door/airlock))
+ occupant_message("Deconstructing [target]...")
+ if(do_after_cooldown(target))
+ chassis.spark_system.start()
+ qdel(target)
+ playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(1)
+ if(istype(target, /turf/space))
+ var/turf/space/S = target
+ occupant_message("Building Floor...")
+ if(do_after_cooldown(S))
+ S.ChangeTurf(/turf/simulated/floor/plating)
+ playsound(S, 'sound/items/Deconstruct.ogg', 50, 1)
+ chassis.spark_system.start()
+ else if(istype(target, /turf/simulated/floor))
+ var/turf/simulated/floor/F = target
+ occupant_message("Building Wall...")
+ if(do_after_cooldown(F))
+ if(disabled) return
+ F.ChangeTurf(/turf/simulated/wall)
+ playsound(F, 'sound/items/Deconstruct.ogg', 50, 1)
+ chassis.spark_system.start()
+ if(2)
+ if(istype(target, /turf/simulated/floor))
+ occupant_message("Building Airlock...")
+ if(do_after_cooldown(target))
+ chassis.spark_system.start()
+ var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target)
+ T.autoclose = 1
+ playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(target, 'sound/effects/sparks2.ogg', 50, 1)
+
+
+
+/obj/item/mecha_parts/mecha_equipment/rcd/do_after_cooldown(var/atom/target)
+ . = ..()
+ if(disabled)
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/rcd/Topic(href,href_list)
+ ..()
+ if(href_list["mode"])
+ mode = text2num(href_list["mode"])
+ switch(mode)
+ if(0)
+ occupant_message("Switched RCD to Deconstruct.")
+ energy_drain = initial(energy_drain)
+ if(1)
+ occupant_message("Switched RCD to Construct.")
+ energy_drain = 2*initial(energy_drain)
+ if(2)
+ occupant_message("Switched RCD to Construct Airlock.")
+ energy_drain = 2*initial(energy_drain)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/rcd/get_equip_info()
+ return "[..()] \[D |C |A \]"
+
+
+
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer
+ name = "cable layer"
+ desc = "Equipment for engineering exosuits. Lays cable along the exosuit's path."
+ icon_state = "mecha_wire"
+ var/datum/event/event
+ var/turf/old_turf
+ var/obj/structure/cable/last_piece
+ var/obj/item/stack/cable_coil/cable
+ var/max_cable = 1000
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/New()
+ cable = new(src)
+ cable.amount = 0
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/can_attach(obj/mecha/working/M)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/attach()
+ ..()
+ event = chassis.events.addEvent("onMove",src,"layCable")
+ return
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/detach()
+ chassis.events.clearEvent("onMove",event)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/Destroy()
+ chassis.events.clearEvent("onMove",event)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/action(var/obj/item/stack/cable_coil/target)
+ if(!action_checks(target))
+ return
+ if(istype(target) && target.amount)
+ var/cur_amount = cable? cable.amount : 0
+ var/to_load = max(max_cable - cur_amount,0)
+ if(to_load)
+ to_load = min(target.amount, to_load)
+ if(!cable)
+ cable = new(src)
+ cable.amount = 0
+ cable.amount += to_load
+ target.use(to_load)
+ occupant_message("[to_load] meters of cable successfully loaded. ")
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+ else
+ occupant_message("Reel is full. ")
+ else
+ occupant_message("Unable to load [target] - no cable found. ")
+
+
+/obj/item/mecha_parts/mecha_equipment/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/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/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/cable_layer/proc/reset()
+ last_piece = null
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/proc/dismantleFloor(var/turf/new_turf)
+ if(istype(new_turf, /turf/simulated/floor))
+ var/turf/simulated/floor/T = new_turf
+ if(!istype(T, /turf/simulated/floor/plating))
+ if(!T.broken && !T.burnt)
+ new T.floor_tile(T)
+ T.make_plating()
+ return !new_turf.intact
+
+/obj/item/mecha_parts/mecha_equipment/cable_layer/proc/layCable(var/turf/new_turf)
+ if(equip_ready || !istype(new_turf) || !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.updateicon()
+
+ 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.updateicon()
+ PN = last_piece.powernet
+
+ if(!PN)
+ PN = new()
+ powernets += PN
+ NC.powernet = PN
+ PN.cables += NC
+ NC.mergeConnectedNetworks(NC.d2)
+
+ //NC.mergeConnectedNetworksOnTurf()
+ last_piece = NC
+ return 1
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 0414658025d..266a0061be6 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -20,7 +20,6 @@
/obj/item/mecha_parts/mecha_equipment/weapon/action(atom/target)
if(!action_checks(target))
return 0
- set_ready_state(0)
var/turf/curloc = get_turf(chassis)
var/turf/targloc = get_turf(target)
@@ -29,6 +28,10 @@
if (targloc == curloc)
return 0
+ set_ready_state(0)
+ chassis.can_move = 0
+ spawn(shot_delay*projectiles_per_shot)
+ chassis.can_move = 1
for(var/i=1 to get_shot_amount())
var/obj/item/projectile/A = new projectile(curloc)
A.firer = chassis.occupant
@@ -49,9 +52,9 @@
sleep(shot_delay)
chassis.log_message("Fired from [src.name], targeting [target].")
- do_after_cooldown()
return 1
+
//Base energy weapon type
/obj/item/mecha_parts/mecha_equipment/weapon/energy
name = "general energy weapon"
@@ -59,10 +62,11 @@
/obj/item/mecha_parts/mecha_equipment/weapon/energy/get_shot_amount()
return min(round(chassis.cell.charge / energy_drain), projectiles_per_shot)
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/action(atom/target)
- ..()
- chassis.use_power(energy_drain * get_shot_amount())
-
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/start_cooldown()
+ set_ready_state(0)
+ chassis.use_power(energy_drain*get_shot_amount())
+ sleep(equip_cooldown)
+ set_ready_state(1)
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
equip_cooldown = 8
@@ -112,9 +116,9 @@
projectile = /obj/item/projectile/plasma/adv/mech
fire_sound = 'sound/weapons/Laser.ogg'
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/mecha/M as obj)
- if(istype(M, /obj/mecha/working))
- if(M.equipment.len < M.max_equip)
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/mecha/working/M as obj)
+ if(..())
+ if(istype(M))
return 1
return 0
@@ -158,8 +162,8 @@
return 0
/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target)
- if(!action_checks(target)) return 0
- set_ready_state(0)
+ if(!action_checks(target))
+ return
playsound(chassis, 'sound/items/AirHorn.ogg', 100, 1)
chassis.occupant_message("HONK ")
for(var/mob/living/carbon/M in ohearers(6, chassis))
@@ -177,24 +181,12 @@
M.Paralyse(4)
else
M.Jitter(500)
- /* //else the mousetraps are useless
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(isobj(H.shoes))
- var/thingy = H.shoes
- H.unEquip(H.shoes)
- walk_away(thingy,chassis,15,2)
- spawn(20)
- if(thingy)
- walk(thingy,0)
- */
- chassis.use_power(energy_drain)
+
log_message("Honked from [src.name]. HONK!")
var/turf/T = get_turf(src)
message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](? ) (FLW ) used a Mecha Honker in ([T.x],[T.y],[T.z] - JMP )",0,1)
log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Mecha Honker in ([T.x],[T.y],[T.z])")
- do_after_cooldown()
- return
+ return 1
//Base ballistic weapon type
@@ -212,8 +204,6 @@
return 0
if(projectiles <= 0)
return 0
- if(!equip_ready)
- return 0
return 1
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info()
@@ -238,8 +228,9 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action(atom/target)
if(..())
- src.projectiles -= get_shot_amount()
+ projectiles -= get_shot_amount()
send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
+ return 1
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
@@ -284,7 +275,27 @@
deviation = 0.3
shot_delay = 2
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher
+ var/missile_speed = 2
+ var/missile_range = 30
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/action(target)
+ if(!action_checks(target))
+ return
+ var/obj/O = new projectile(chassis.loc)
+ playsound(chassis, fire_sound, 50, 1)
+ log_message("Launched a [O.name] from [name], targeting [target].")
+ projectiles--
+ proj_init(O)
+ spawn(0)
+ O.throw_at(target, missile_range, missile_speed, spin = 0)
+ return 1
+
+//used for projectile initilisation (priming flashbang) and additional logging
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/proc/proj_init(var/obj/O)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack
name = "\improper SRM-8 missile rack"
desc = "A weapon for combat exosuits. Shoots light explosive missiles."
icon_state = "mecha_missilerack"
@@ -293,24 +304,12 @@
projectiles = 8
projectile_energy_cost = 1000
equip_cooldown = 60
- var/missile_speed = 2
- var/missile_range = 30
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/action(target)
- if(!action_checks(target)) return
- set_ready_state(0)
- var/obj/item/missile/M = new projectile(chassis.loc)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack/proj_init(var/obj/item/missile/M)
M.primed = 1
- playsound(chassis, fire_sound, 50, 1)
- M.throw_at(target, missile_range, missile_speed)
- projectiles--
- log_message("Fired from [src.name], targeting [target].")
var/turf/T = get_turf(src)
message_admins("[key_name(chassis.occupant, chassis.occupant.client)](? ) fired a [src] in ([T.x],[T.y],[T.z] - JMP )",0,1)
log_game("[key_name(chassis.occupant)] fired a [src] ([T.x],[T.y],[T.z])")
- do_after_cooldown()
- return
-
/obj/item/missile
icon = 'icons/obj/grenade.dmi'
@@ -324,9 +323,8 @@
qdel(src)
else
..()
- return
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang
name = "\improper SGL-6 grenade launcher"
desc = "A weapon for combat exosuits. Launches primed flashbangs."
icon_state = "mecha_grenadelnchr"
@@ -338,24 +336,16 @@
equip_cooldown = 60
var/det_time = 20
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/action(target)
- if(!action_checks(target)) return
- set_ready_state(0)
- var/obj/item/weapon/grenade/flashbang/F = new projectile(chassis.loc)
- playsound(chassis, fire_sound, 50, 1)
- F.throw_at(target, missile_range, missile_speed)
- projectiles--
- log_message("Fired from [src.name], targeting [target].")
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/proj_init(var/obj/item/weapon/grenade/flashbang/F)
var/turf/T = get_turf(src)
- message_admins("[key_name(chassis.occupant, chassis.occupant.client)](? ) (FLW ) fired a [src] in ([T.x],[T.y],[T.z] - JMP )",0,1)
+ message_admins("[key_name(chassis.occupant, chassis.occupant.client)](? ) fired a [src] in ([T.x],[T.y],[T.z] - JMP )",0,1)
log_game("[key_name(chassis.occupant)] fired a [src] ([T.x],[T.y],[T.z])")
spawn(det_time)
if(F)
F.prime()
- do_after_cooldown()
- return
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang //Because I am a heartless bastard -Sieve //Heartless? for making the poor man's honkblast? - Kaze
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/clusterbang //Because I am a heartless bastard -Sieve //Heartless? for making the poor man's honkblast? - Kaze
name = "\improper SOB-3 grenade launcher"
desc = "A weapon for combat exosuits. Launches primed clusterbangs. You monster."
projectiles = 3
@@ -363,7 +353,7 @@
projectile_energy_cost = 1600 //getting off cheap seeing as this is 3 times the flashbangs held in the grenade launcher.
equip_cooldown = 90
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar
name = "banana mortar"
desc = "Equipment for clown exosuits. Launches banana peels."
icon_state = "mecha_bananamrtr"
@@ -374,25 +364,13 @@
projectile_energy_cost = 100
equip_cooldown = 20
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/can_attach(obj/mecha/combat/honker/M as obj)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/can_attach(obj/mecha/combat/honker/M as obj)
if(..())
if(istype(M))
return 1
return 0
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/action(target)
- if(!action_checks(target)) return
- set_ready_state(0)
- var/obj/item/weapon/grown/bananapeel/B = new projectile(chassis.loc,60)
- playsound(chassis, fire_sound, 60, 1)
- B.throw_at(target, missile_range, missile_speed)
- projectiles--
- log_message("Bananed from [src.name], targeting [target]. HONK!")
- do_after_cooldown()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar
name = "mousetrap mortar"
desc = "Equipment for clown exosuits. Launches armed mousetraps."
icon_state = "mecha_mousetrapmrtr"
@@ -403,20 +381,12 @@
projectile_energy_cost = 100
equip_cooldown = 10
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M as obj)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M as obj)
if(..())
if(istype(M))
return 1
return 0
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/action(target)
- if(!action_checks(target)) return
- set_ready_state(0)
- var/obj/item/device/assembly/mousetrap/armed/M = new projectile(chassis.loc)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/proj_init(var/obj/item/device/assembly/mousetrap/armed/M)
M.secured = 1
- playsound(chassis, fire_sound, 60, 1)
- M.throw_at(target, missile_range, missile_speed)
- projectiles--
- log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!")
- do_after_cooldown()
- return
+
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 48f34a6faaf..35512a1429f 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -57,10 +57,6 @@
var/list/operation_req_access = list()//required access level for mecha operation
var/list/internals_req_access = list(access_engine,access_robotics)//required access level to open cell compartment
- var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature
- var/datum/global_iterator/pr_give_air //moves air from tank to cabin
- var/datum/global_iterator/pr_internal_damage //processes internal damage
-
var/wreckage
var/list/equipment = new
@@ -74,6 +70,12 @@
var/melee_cooldown = 10
var/melee_can_hit = 1
+ var/datum/action/mecha/mech_eject/eject_action = new
+ var/datum/action/mecha/mech_toggle_internals/internals_action = new
+ var/datum/action/mecha/mech_cycle_equip/cycle_action = new
+ var/datum/action/mecha/mech_toggle_lights/lights_action = new
+ var/datum/action/mecha/mech_view_stats/stats_action = new
+
/obj/mecha/New()
..()
@@ -81,14 +83,11 @@
icon_state += "-open"
add_radio()
add_cabin()
- if(!add_airtank()) //we check this here in case mecha does not have an internal tank available by default - WIP
- removeVerb(/obj/mecha/verb/connect_to_port)
- removeVerb(/obj/mecha/verb/toggle_internal_tank)
+ add_airtank()
spark_system.set_up(2, 0, src)
spark_system.attach(src)
add_cell()
- add_iterators()
- removeVerb(/obj/mecha/verb/disconnect_from_port)
+ SSobj.processing |= src
log_message("[src.name] created.")
mechas_list += src //global mech list
return
@@ -114,7 +113,7 @@
E.reliability = round(rand(E.reliability/3,E.reliability))
else
E.detach(loc)
- E.destroy()
+ qdel(E)
if(cell)
WR.crowbar_salvage += cell
cell.forceMove(WR)
@@ -125,22 +124,16 @@
else
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
E.detach(loc)
- E.destroy()
+ qdel(E)
if(cell)
qdel(cell)
if(internal_tank)
qdel(internal_tank)
+ SSobj.processing.Remove(src)
equipment.Cut()
cell = null
internal_tank = null
-
- qdel(pr_int_temp_processor)
- qdel(pr_give_air)
- qdel(pr_internal_damage)
qdel(spark_system)
- pr_int_temp_processor = null
- pr_give_air = null
- pr_internal_damage = null
spark_system = null
mechas_list -= src //global mech list
@@ -150,12 +143,6 @@
////// Helpers /////////
////////////////////////
-/obj/mecha/proc/removeVerb(verb_path)
- verbs -= verb_path
-
-/obj/mecha/proc/addVerb(verb_path)
- verbs += verb_path
-
/obj/mecha/proc/add_airtank()
internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
return internal_tank
@@ -184,37 +171,16 @@
radio.icon_state = icon_state
radio.subspace_transmission = 1
-/obj/mecha/proc/add_iterators()
- pr_int_temp_processor = new /datum/global_iterator/mecha_preserve_temp(list(src))
- pr_give_air = new /datum/global_iterator/mecha_tank_give_air(list(src))
- pr_internal_damage = new /datum/global_iterator/mecha_internal_damage(list(src),0)
-
-/obj/mecha/proc/do_after(delay as num)
- sleep(delay)
- if(src)
- return 1
- return 0
-
-/obj/mecha/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5)
- var/delayfraction = delay/numticks
-
- var/turf/T = user.loc
-
- for(var/i = 0, i internal_tank.maximum_pressure && !(internal_damage & MECHA_INT_TANK_BREACH))
+ setInternalDamage(MECHA_INT_TANK_BREACH)
+ var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
+ if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents
+ int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15))
+ if(cabin_air && cabin_air.return_volume()>0)
+ cabin_air.temperature = min(6000+T0C, cabin_air.return_temperature()+rand(10,15))
+ if(cabin_air.return_temperature() > max_temperature/2)
+ take_damage(4/round(max_temperature/cabin_air.return_temperature(),0.1),"fire")
+
+ if(internal_damage & MECHA_INT_TEMP_CONTROL)
+ internal_temp_regulation = 0
+
+ if(internal_damage & MECHA_INT_TANK_BREACH) //remove some air from internal tank
+ if(internal_tank)
+ var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
+ var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.10)
+ if(loc)
+ loc.assume_air(leaked_gas)
+ else
+ del(leaked_gas)
+
+ if(internal_damage & MECHA_INT_SHORT_CIRCUIT)
+ if(get_charge())
+ spark_system.start()
+ cell.charge -= min(20,cell.charge)
+ cell.maxcharge -= min(20,cell.maxcharge)
+
+ if(internal_temp_regulation)
+ if(cabin_air && cabin_air.return_volume() > 0)
+ var/delta = cabin_air.temperature - T20C
+ cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1)))
+
+ if(internal_tank)
+ var/datum/gas_mixture/tank_air = internal_tank.return_air()
+
+ var/release_pressure = internal_tank_valve
+ var/cabin_pressure = cabin_air.return_pressure()
+ var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2)
+ var/transfer_moles = 0
+ if(pressure_delta > 0) //cabin pressure lower than release pressure
+ if(tank_air.return_temperature() > 0)
+ transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
+ var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
+ cabin_air.merge(removed)
+ else if(pressure_delta < 0) //cabin pressure higher than release pressure
+ var/datum/gas_mixture/t_air = return_air()
+ pressure_delta = cabin_pressure - release_pressure
+ if(t_air)
+ pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta)
+ if(pressure_delta > 0) //if location pressure is lower than cabin pressure
+ transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
+ var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles)
+ if(t_air)
+ t_air.merge(removed)
+ else //just delete the cabin gas, we're in space or some shit
+ del(removed)
+
+ if(occupant)
+ if(cell)
+ var/cellcharge = cell.charge/cell.maxcharge
+ switch(cellcharge)
+ if(0.75 to INFINITY)
+ occupant.clear_alert("charge")
+ if(0.5 to 0.75)
+ occupant.throw_alert("charge","lowcell",1)
+ if(0.25 to 0.5)
+ occupant.throw_alert("charge","lowcell",2)
+ if(0.01 to 0.25)
+ occupant.throw_alert("charge","lowcell",3)
+ else
+ occupant.throw_alert("charge","emptycell")
+
+ var/integrity = health/initial(health)*100
+ switch(integrity)
+ if(30 to 45)
+ occupant.throw_alert("mech damage", "low_mech_integrity", 1)
+ if(15 to 35)
+ occupant.throw_alert("mech damage", "low_mech_integrity", 2)
+ if(-INFINITY to 15)
+ occupant.throw_alert("mech damage", "low_mech_integrity", 3)
+ else
+ occupant.clear_alert("mech damage")
+
+ if(occupant.loc != src) //something went wrong
+ occupant.clear_alert("charge")
+ occupant.clear_alert("mech damage")
+ RemoveActions(occupant, human_occupant=1)
+ occupant = null
+
+ if(lights)
+ var/lights_energy_drain = 2
+ use_power(lights_energy_drain)
+
+
+
+
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
return
@@ -247,32 +321,11 @@
////////////////////////////
///// Action processing ////
////////////////////////////
-/*
-/atom/DblClick(object,location,control,params)
- var/mob/M = src.mob
- if(M && M.in_contents_of(/obj/mecha))
- if(mech_click == world.time) return
- mech_click = world.time
-
- if(!istype(object, /atom)) return
- if(istype(object, /obj/screen))
- var/obj/screen/using = object
- if(using.screen_loc == ui_acti || using.screen_loc == ui_iarrowleft || using.screen_loc == ui_iarrowright)//ignore all HUD objects save 'intent' and its arrows
- return ..()
- else
- return
- var/obj/mecha/Mech = M.loc
- spawn() //this helps prevent clickspam fest.
- if (Mech)
- Mech.click_action(object,M)
-// else
-// return ..()
-*/
/obj/mecha/proc/click_action(atom/target,mob/user)
- if(!src.occupant || src.occupant != user ) return
- if(user.stat || !user.canmove)
+ if(!occupant || occupant != user ) return
+ if(user.incapacitated())
return
if(state)
occupant_message("Maintenance protocols in effect. ")
@@ -284,49 +337,28 @@
var/dir_to_target = get_dir(src,target)
if(dir_to_target && !(dir_to_target & src.dir))//wrong direction
return
- if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
+ if(internal_damage & MECHA_INT_CONTROL_LOST)
target = safepick(view(3,target))
if(!target)
return
if(!target.Adjacent(src))
if(selected && selected.is_ranged())
- selected.action(target)
+ if(selected.action(target))
+ selected.start_cooldown()
else if(selected && selected.is_melee())
- selected.action(target)
+ if(selected.action(target))
+ selected.start_cooldown()
else
- if(internal_damage&MECHA_INT_CONTROL_LOST)
+ if(internal_damage & MECHA_INT_CONTROL_LOST)
target = safepick(oview(1,src))
if(!melee_can_hit || !istype(target, /atom))
return
target.mech_melee_attack(src)
melee_can_hit = 0
- if(do_after(melee_cooldown))
+ spawn(melee_cooldown)
melee_can_hit = 1
return
-/obj/mecha/proc/mech_toxin_damage(mob/living/target)
- playsound(src, 'sound/effects/spray2.ogg', 50, 1)
- if(target.reagents)
- if(target.reagents.get_reagent_amount("cryptobiolin") + force < force*2)
- target.reagents.add_reagent("cryptobiolin", force/2)
- if(target.reagents.get_reagent_amount("toxin") + force < force*2)
- target.reagents.add_reagent("toxin", force/2.5)
-
-
-/atom/proc/mech_melee_attack(obj/mecha/M)
- return
-
-/obj/mecha/mech_melee_attack(obj/mecha/M)
- if(M.damtype =="brute")
- playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
- else if(M.damtype == "fire")
- playsound(src, 'sound/items/Welder.ogg', 50, 1)
- else
- return
- visible_message("[M.name] has hit [src]. ")
- take_damage(M.force, damtype)
- add_logs(M.occupant, src, "attacked", object=M, addition="(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
- return
/obj/mecha/proc/range_action(atom/target)
return
@@ -364,9 +396,6 @@
return domove(direction)
/obj/mecha/proc/domove(direction)
- return call((proc_res["dyndomove"]||src), "dyndomove")(direction)
-
-/obj/mecha/proc/dyndomove(direction)
if(!can_move)
return 0
if(!Process_Spacemove(direction))
@@ -374,15 +403,16 @@
if(!has_charge(step_energy_drain))
return 0
var/move_result = 0
- if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
+ if(internal_damage & MECHA_INT_CONTROL_LOST)
move_result = mechsteprand()
else if(src.dir!=direction)
move_result = mechturn(direction)
else
move_result = mechstep(direction)
if(move_result)
+ use_power(step_energy_drain)
can_move = 0
- if(do_after(step_in))
+ spawn(step_in)
can_move = 1
return 1
return 0
@@ -410,15 +440,15 @@
if(istype(obstacle, /obj))
var/obj/O = obstacle
if(istype(O, /obj/effect/portal)) //derpfix
- src.anchored = 0
+ anchored = 0
O.Crossed(src)
src.anchored = 1
else if(!O.anchored)
- step(obstacle,src.dir)
+ step(obstacle, dir)
else //I have no idea why I disabled this
obstacle.Bumped(src)
else if(istype(obstacle, /mob))
- step(obstacle,src.dir)
+ step(obstacle, dir)
else
obstacle.Bumped(src)
return
@@ -430,7 +460,7 @@
/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null)
if(!islist(possible_int_damage) || isemptylist(possible_int_damage)) return
if(prob(20))
- if(ignore_threshold || src.health*100/initial(src.health)Life support system reactivated. ")
+ if(MECHA_INT_FIRE)
+ occupant_message("Internal fire extinquished. ")
+ if(MECHA_INT_TANK_BREACH)
+ occupant_message("Damaged internal tank has been sealed. ")
internal_damage &= ~int_dam_flag
- switch(int_dam_flag)
- if(MECHA_INT_TEMP_CONTROL)
- if(pr_int_temp_processor)
- occupant_message("Life support system reactivated. ")
- pr_int_temp_processor.start()
- if(MECHA_INT_FIRE)
- occupant_message("Internal fire extinquished. ")
- if(MECHA_INT_TANK_BREACH)
- occupant_message("Damaged internal tank has been sealed. ")
- return
-////////////////////////////////////////
-//////// Health related procs ////////
-////////////////////////////////////////
-
-/obj/mecha/proc/take_damage(amount, type="brute")
- if(amount)
- var/damage = absorbDamage(amount,type)
- health -= damage
- update_health()
- occupant_message("Taking damage! ")
- log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1)
-
-/obj/mecha/proc/absorbDamage(damage,damage_type)
- return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type)
-
-/obj/mecha/proc/dynabsorbdamage(damage,damage_type)
- return damage*(listgetindex(damage_absorption,damage_type) || 1)
-
-
-/obj/mecha/proc/update_health()
- if(src.health > 0)
- src.spark_system.start()
- else
- qdel(src)
-
-/obj/mecha/attack_hulk(mob/living/carbon/human/user)
- if(!prob(src.deflect_chance))
- ..(user, 1)
- take_damage(15)
- check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- user.visible_message("[user] hits [src.name], doing some damage. ", "You hit [src.name] with all your might. The metal creaks and bends. ")
- occupant_message("[user] hits [src.name], doing some damage. ")
- return 1
- return 0
-
-/obj/mecha/attack_hand(mob/living/user as mob)
- user.changeNext_move(CLICK_CD_MELEE) // Ugh. Ideally we shouldn't be setting cooldowns outside of click code.
- user.do_attack_animation(src)
- src.log_message("Attack by hand/paw. Attacker - [user].",1)
- user.visible_message("[user] hits [src.name]. Nothing happens ","You hit [src.name] with no visible effect. ")
- src.log_append_to_last("Armor saved.")
- return
-
-/obj/mecha/attack_paw(mob/user as mob)
- return src.attack_hand(user)
-
-
-/obj/mecha/attack_alien(mob/living/user as mob)
- src.log_message("Attack by alien. Attacker - [user].",1)
- user.changeNext_move(CLICK_CD_MELEE) //Now stompy alien killer mechs are actually scary to aliens!
- user.do_attack_animation(src)
- if(!prob(src.deflect_chance))
- src.take_damage(15)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
- visible_message("The [user] slashes at [src.name]'s armor! ")
- else
- src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
- user << "\green Your claws had no effect!"
- visible_message("The [user] rebounds off [src.name]'s armor! ")
- return
-
-
-/obj/mecha/attack_animal(mob/living/simple_animal/user as mob)
- src.log_message("Attack by simple animal. Attacker - [user].",1)
- user.changeNext_move(CLICK_CD_MELEE)
- if(user.melee_damage_upper == 0)
- user.emote("[user.friendly] [src]")
- else
- user.do_attack_animation(src)
- if(!prob(src.deflect_chance))
- var/damage = rand(user.melee_damage_lower, user.melee_damage_upper)
- src.take_damage(damage)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- visible_message("[user] [user.attacktext] [src]! ")
- add_logs(user, src, "attacked", admin=0)
- else
- src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
- visible_message("The [user] rebounds off [src.name]'s armor! ")
- add_logs(user, src, "attacked", admin=0)
- return
-
-/obj/mecha/attack_tk()
- return
-
-/obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper
- src.log_message("Hit by [A].",1)
- call((proc_res["dynhitby"]||src), "dynhitby")(A)
- return
-
-/obj/mecha/proc/dynhitby(atom/movable/A)
- if(istype(A, /obj/item/mecha_parts/mecha_tracking))
- A.forceMove(src)
- src.visible_message("The [A] fastens firmly to [src].")
- return
- if(prob(src.deflect_chance) || istype(A, /mob))
- src.visible_message("[A] bounces off the [src.name] armor")
- src.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)
- src.visible_message("[src.name] is hit by [A]. ")
- src.take_damage(O.throwforce)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- return
-
-
-/obj/mecha/bullet_act(var/obj/item/projectile/Proj) //wrapper
- src.log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1)
- call((proc_res["dynbulletdamage"]||src), "dynbulletdamage")(Proj) //calls equipment
- ..()
- return
-
-/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj)
- if(prob(src.deflect_chance))
- src.visible_message("The [src.name] armor deflects the projectile")
- src.log_append_to_last("Armor saved.")
- return
- var/ignore_threshold
- if(Proj.flag == "taser")
- use_power(200)
- return
- if(istype(Proj, /obj/item/projectile/beam/pulse))
- ignore_threshold = 1
- if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
- src.take_damage(Proj.damage,Proj.flag)
- src.visible_message("[src.name] is hit by [Proj]. ")
- src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
- Proj.on_hit(src)
- return
-
-/obj/mecha/ex_act(severity, target)
- src.log_message("Affected by explosion of severity: [severity].",1)
- if(prob(src.deflect_chance))
- severity++
- src.log_append_to_last("Armor saved, changing severity to [severity].")
- switch(severity)
- if(1.0)
- qdel(src)
- if(2.0)
- if (prob(30))
- qdel(src)
- else
- src.take_damage(initial(src.health)/2)
- src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
- if(3.0)
- if (prob(5))
- qdel(src)
- else
- src.take_damage(initial(src.health)/5)
- src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
- return
-
-/obj/mecha/blob_act()
- take_damage(30, "brute")
- return
-
-/obj/mecha/emp_act(severity)
- if(get_charge())
- use_power((cell.charge/2)/severity)
- take_damage(50 / severity,"energy")
- src.log_message("EMP detected",1)
- check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
- return
-
-/obj/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- if(exposed_temperature>src.max_temperature)
- src.log_message("Exposed to dangerous temperature.",1)
- src.take_damage(5,"fire")
- src.check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL))
- return
-
-/obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/living/user as mob)
- user.changeNext_move(CLICK_CD_MELEE) // Ugh. Ideally we shouldn't be setting cooldowns outside of click code.
- user.do_attack_animation(src)
- src.log_message("Attacked by [W]. Attacker - [user]")
- if(prob(src.deflect_chance))
- user << "The [W] bounces off [src.name] armor. "
- src.log_append_to_last("Armor saved.")
- return 0
- else
- user.visible_message("[user] hits [src] with [W]. ", "You hit [src] with [W]. ")
- src.take_damage(W.force,W.damtype)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- return 1
-
-//////////////////////
-////// AttackBy //////
-//////////////////////
-
-/obj/mecha/attackby(obj/item/W as obj, mob/user as mob, params)
-
- if(istype(W, /obj/item/device/mmi))
- if(mmi_move_inside(W,user))
- user << "[src]-[W] interface initialized successfuly"
- else
- user << "[src]-[W] interface initialization failed."
- return
-
- if(istype(W, /obj/item/mecha_parts/mecha_equipment))
- var/obj/item/mecha_parts/mecha_equipment/E = W
- spawn()
- if(E.can_attach(src))
- if(!user.drop_item())
- return
- E.attach(src)
- user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]. ")
- else
- user << "You were unable to attach [W] to [src]! "
- return
- if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
- if(add_req_access || maint_access)
- if(internals_access_allowed(user))
- var/obj/item/weapon/card/id/id_card
- if(istype(W, /obj/item/weapon/card/id))
- id_card = W
- else
- var/obj/item/device/pda/pda = W
- id_card = pda.id
- output_maintenance_dialog(id_card, user)
- return
- else
- user << "Invalid ID: Access denied. "
- else
- user << "Maintenance protocols disabled by operator. "
- else if(istype(W, /obj/item/weapon/wrench))
- if(state==1)
- state = 2
- user << "You undo the securing bolts. "
- else if(state==2)
- state = 1
- user << "You tighten the securing bolts. "
- return
- else if(istype(W, /obj/item/weapon/crowbar))
- if(state==2)
- state = 3
- user << "You open the hatch to the power unit. "
- else if(state==3)
- state=2
- user << "You close the hatch to the power unit. "
- return
- else if(istype(W, /obj/item/stack/cable_coil))
- if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
- var/obj/item/stack/cable_coil/CC = W
- if(CC.use(2))
- clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
- user << "You replace the fused wires. "
- else
- user << "You need two lengths of cable to fix this mech! "
- return
- else if(istype(W, /obj/item/weapon/screwdriver))
- if(hasInternalDamage(MECHA_INT_TEMP_CONTROL))
- clearInternalDamage(MECHA_INT_TEMP_CONTROL)
- user << "You repair the damaged temperature controller. "
- else if(state==3 && src.cell)
- src.cell.forceMove(src.loc)
- src.cell = null
- state = 4
- user << "You unscrew and pry out the powercell. "
- src.log_message("Powercell removed")
- else if(state==4 && src.cell)
- state=3
- user << "You screw the cell in place. "
- return
-
- else if(istype(W, /obj/item/weapon/stock_parts/cell))
- if(state==4)
- if(!src.cell)
- if(!user.drop_item())
- return
- var/obj/item/weapon/stock_parts/cell/C = W
- user << "You install the powercell. "
- C.forceMove(src)
- C.use(C.charge * 0.8)
- src.cell = C
- src.log_message("Powercell installed")
- else
- user << "There's already a powercell installed. "
- return
-
- else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm")
- user.changeNext_move(CLICK_CD_MELEE)
- var/obj/item/weapon/weldingtool/WT = W
- if(src.healthYou repair the damaged gas tank."
- else
- user.visible_message("[user] repairs some damage to [src.name]. ")
- src.health += min(10, initial(src.health)-src.health)
- else
- user << "The welder must be on for this task! "
- return 1
- else
- user << "The [src.name] is at full integrity! "
- return 1
-
- else if(istype(W, /obj/item/mecha_parts/mecha_tracking))
- if(!user.unEquip(W))
- user << "\the [W] is stuck to your hand, you cannot put it in \the [src]! "
- return
- W.forceMove(src)
- user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]. ")
- return
-
- else if(!(W.flags&NOBLUDGEON))
- call((proc_res["dynattackby"]||src), "dynattackby")(W,user)
- return
-
/////////////////////////////////////
//////////// AI piloting ////////////
/////////////////////////////////////
@@ -861,7 +568,7 @@
occupant = AI
icon_state = initial(icon_state)
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
- if(!hasInternalDamage())
+ if(!internal_damage)
occupant << sound('sound/mecha/nominal.ogg',volume=50)
AI.cancel_camera()
AI.controlled_mech = src
@@ -871,7 +578,7 @@
AI << "[interaction == AI_MECH_HACK ? "Takeover of [name] complete! You are now permanently loaded onto the onboard computer. Do not attempt to leave the station sector! " \
: "You have been uploaded to a mech's onboard computer."]"
AI << "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions. "
-
+ GrantActions(AI)
/////////////////////////////////////
//////// Atmospheric stuff ////////
@@ -929,81 +636,6 @@
/obj/mecha/portableConnectorReturnAir()
return internal_tank.return_air()
-/////////////////////////
-//////// Verbs ////////
-/////////////////////////
-
-
-/obj/mecha/verb/connect_to_port()
- set name = "Connect to port"
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(!can_use(usr))
- return
-
- var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc
- if(possible_port)
- if(connect(possible_port))
- src.occupant_message("[name] connects to the port. ")
- src.verbs += /obj/mecha/verb/disconnect_from_port
- src.verbs -= /obj/mecha/verb/connect_to_port
- return
- else
- src.occupant_message("[name] failed to connect to the port. ")
- return
- else
- src.occupant_message("Nothing happens")
-
-
-/obj/mecha/verb/disconnect_from_port()
- set name = "Disconnect from port"
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(!can_use(usr))
- return
-
- if(disconnect())
- src.occupant_message("[name] disconnects from the port. ")
- src.verbs -= /obj/mecha/verb/disconnect_from_port
- src.verbs += /obj/mecha/verb/connect_to_port
- else
- src.occupant_message("[name] is not connected to the port at the moment. ")
-
-/obj/mecha/verb/toggle_lights()
- set name = "Toggle Lights"
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(!can_use(usr))
- return
-
- lights = !lights
- if(lights) AddLuminosity(lights_power)
- else AddLuminosity(-lights_power)
- src.occupant_message("Toggled lights [lights?"on":"off"].")
- log_message("Toggled lights [lights?"on":"off"].")
- return
-
-
-/obj/mecha/verb/toggle_internal_tank()
- set name = "Toggle internal airtank usage."
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(!can_use(usr))
- return
-
- use_internal_tank = !use_internal_tank
- src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
- src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
- return
-
/obj/mecha/MouseDrop_T(mob/M as mob, mob/user as mob)
if (!user.canUseTopic(src) || (user != M))
@@ -1034,13 +666,13 @@
visible_message("[user] starts to climb into [src.name].")
- if(enter_after(40,user))
- if(src.health <= 0)
+ if(do_after(user, 40, target = src))
+ if(health <= 0)
user << "You cannot get in the [src.name], it has been destroyed! "
- else if(!src.occupant)
- moved_inside(user)
- else if(src.occupant!=user)
+ else if(occupant)
user << "[src.occupant] was faster! Try better next time, loser. "
+ else
+ moved_inside(user)
else
user << "You stop entering the exosuit! "
return
@@ -1048,25 +680,18 @@
/obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob)
if(H && H.client && H in range(1))
H.reset_view(src)
- /*
- H.client.perspective = EYE_PERSPECTIVE
- H.client.eye = src
- */
H.stop_pulling()
H.forceMove(src)
- if(H.hud_used)
- last_user_hud = H.hud_used.hud_shown
- H.hud_used.show_hud(HUD_STYLE_REDUCED)
-
- src.occupant = H
- src.add_fingerprint(H)
- src.forceMove(src.loc)
- src.log_append_to_last("[H] moved in as pilot.")
- src.icon_state = initial(icon_state)
+ occupant = H
+ add_fingerprint(H)
+ GrantActions(H, human_occupant=1)
+ forceMove(loc)
+ log_append_to_last("[H] moved in as pilot.")
+ icon_state = initial(icon_state)
dir = dir_in
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
- if(!hasInternalDamage())
- src.occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ if(!internal_damage)
+ occupant << sound('sound/mecha/nominal.ogg',volume=50)
return 1
else
return 0
@@ -1089,7 +714,7 @@
visible_message("[user] starts to insert an MMI into [src.name]. ")
- if(enter_after(40,user))
+ if(do_after(user, 40, target = src))
if(!occupant)
return mmi_moved_inside(mmi_as_oc,user)
else
@@ -1111,122 +736,65 @@
return
var/mob/brainmob = mmi_as_oc.brainmob
brainmob.reset_view(src)
- /*
- brainmob.client.eye = src
- brainmob.client.perspective = EYE_PERSPECTIVE
- */
occupant = brainmob
brainmob.loc = src //should allow relaymove
brainmob.canmove = 1
mmi_as_oc.loc = src
mmi_as_oc.mecha = src
- src.verbs -= /obj/mecha/verb/eject
- src.icon_state = initial(icon_state)
+ icon_state = initial(icon_state)
dir = dir_in
- src.log_message("[mmi_as_oc] moved in as pilot.")
- if(!hasInternalDamage())
- src.occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ log_message("[mmi_as_oc] moved in as pilot.")
+ if(!internal_damage)
+ occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ GrantActions(brainmob)
return 1
else
return 0
-/obj/mecha/verb/view_stats()
- set name = "View Stats"
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(!can_use(usr))
- return
- //pr_update_stats.start()
- src.occupant << browse(src.get_stats_html(), "window=exosuit")
- return
-
-/*
-/obj/mecha/verb/force_eject()
- set category = "Object"
- set name = "Force Eject"
- set src in view(5)
- src.go_out()
- return
-*/
-
-/obj/mecha/verb/eject()
- set name = "Eject"
- set category = "Exosuit Interface"
- set src = usr.loc
- set popup_menu = 0
-
- if(!can_use(usr))
- return
-
- src.go_out()
- add_fingerprint(usr)
- return
-
/obj/mecha/container_resist()
go_out()
-/obj/mecha/proc/go_out(var/forced)
- if(!src.occupant) return
+/obj/mecha/Exited(var/atom/movable/M, var/atom/newloc)
+ if(occupant && occupant == M) // The occupant exited the mech without calling go_out()
+ go_out(1, newloc)
+
+/obj/mecha/proc/go_out(var/forced, var/atom/newloc = loc)
+ if(!occupant) return
var/atom/movable/mob_container
+ occupant.clear_alert("charge")
+ occupant.clear_alert("mech damage")
if(ishuman(occupant))
- mob_container = src.occupant
- if(occupant.hud_used && last_user_hud)
- occupant.hud_used.show_hud(HUD_STYLE_STANDARD)
+ mob_container = occupant
+ RemoveActions(occupant, human_occupant=1)
else if(istype(occupant, /mob/living/carbon/brain))
var/mob/living/carbon/brain/brain = occupant
+ RemoveActions(brain)
mob_container = brain.container
else if(isAI(occupant) && forced) //This should only happen if there are multiple AIs in a round, and at least one is Malf.
+ RemoveActions(occupant)
occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
occupant = null
return
else
return
- if(mob_container.forceMove(src.loc))//ejecting mob container
- /*
- if(ishuman(occupant) && (return_pressure() > HAZARD_HIGH_PRESSURE))
- use_internal_tank = 0
- var/datum/gas_mixture/environment = get_turf_air()
- if(environment)
- var/env_pressure = environment.return_pressure()
- var/pressure_delta = (cabin.return_pressure() - env_pressure)
- //Can not have a pressure delta that would cause environment pressure > tank pressure
-
- var/transfer_moles = 0
- if(pressure_delta > 0)
- transfer_moles = pressure_delta*environment.volume/(cabin.return_temperature() * R_IDEAL_GAS_EQUATION)
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = cabin.air_contents.remove(transfer_moles)
- loc.assume_air(removed)
-
- occupant.SetStunned(5)
- occupant.SetWeakened(5)
- occupant << "You were blown out of the mech!"
- */
- src.log_message("[mob_container] moved out.")
- occupant.reset_view()
- /*
- if(src.occupant.client)
- src.occupant.client.eye = src.occupant.client.mob
- src.occupant.client.perspective = MOB_PERSPECTIVE
- */
- src.occupant << browse(null, "window=exosuit")
+ var/mob/living/L = occupant
+ occupant = null //we need it null when forceMove calls Exited().
+ if(mob_container.forceMove(newloc))//ejecting mob container
+ log_message("[mob_container] moved out.")
+ L.reset_view()
+ L << browse(null, "window=exosuit")
if(istype(mob_container, /obj/item/device/mmi))
var/obj/item/device/mmi/mmi = mob_container
if(mmi.brainmob)
- occupant.loc = mmi
+ L.loc = mmi
mmi.mecha = null
mmi.update_icon()
- src.occupant.canmove = 0
- src.verbs += /obj/mecha/verb/eject
- src.occupant = null
- src.icon_state = initial(icon_state)+"-open"
- src.dir = dir_in
+ L.canmove = 0
+ icon_state = initial(icon_state)+"-open"
+ dir = dir_in
return
/////////////////////////
@@ -1244,211 +812,6 @@
return allowed(M)
-////////////////////////////////////
-///// Rendering stats window ///////
-////////////////////////////////////
-
-/obj/mecha/proc/get_stats_html()
- var/output = {"
- [src.name] data
-
-
-
-
-
- [src.get_stats_part()]
-
-
- [src.get_equipment_list()]
-
-
-
- [src.get_commands()]
-
-
-
- "}
- return output
-
-
-/obj/mecha/proc/report_internal_damage()
- var/output = null
- var/list/dam_reports = list(
- "[MECHA_INT_FIRE]" = "INTERNAL FIRE ",
- "[MECHA_INT_TEMP_CONTROL]" = "LIFE SUPPORT SYSTEM MALFUNCTION ",
- "[MECHA_INT_TANK_BREACH]" = "GAS TANK BREACH ",
- "[MECHA_INT_CONTROL_LOST]" = "COORDINATION SYSTEM CALIBRATION FAILURE - Recalibrate ",
- "[MECHA_INT_SHORT_CIRCUIT]" = "SHORT CIRCUIT "
- )
- for(var/tflag in dam_reports)
- var/intdamflag = text2num(tflag)
- if(hasInternalDamage(intdamflag))
- output += dam_reports[tflag]
- output += " "
- if(return_pressure() > WARNING_HIGH_PRESSURE)
- output += "DANGEROUSLY HIGH CABIN PRESSURE "
- return output
-
-
-/obj/mecha/proc/get_stats_part()
- var/integrity = health/initial(health)*100
- var/cell_charge = get_charge()
- var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None"
- var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown"
- var/cabin_pressure = round(return_pressure(),0.01)
- var/output = {"[report_internal_damage()]
- [integrity<30?"DAMAGE LEVEL CRITICAL ":null]
- Integrity: [integrity]%
- Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
- Air source: [use_internal_tank?"Internal Airtank":"Environment"]
- Airtank pressure: [tank_pressure]kPa
- Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
- Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure] ": cabin_pressure]kPa
- Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
- Lights: [lights?"on":"off"]
- [src.dna?"DNA-locked: [src.dna] \[Reset \] ":null]
- "}
- return output
-
-/obj/mecha/proc/get_commands()
- var/output = {"
-
-
-
-
- [(/obj/mecha/verb/eject in src.verbs)?"Eject ":null]
- "}
- return output
-
-/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu
- var/output
- if(equipment.len)
- output += {"
-
-
"}
- for(var/obj/item/mecha_parts/mecha_equipment/W in equipment)
- output += "[W.name]
Detach "
- output += "
Available equipment slots: [max_equip-equipment.len]"
- output += "
"
- return output
-
-/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html
- if(!equipment.len)
- return
- var/output = "Equipment: "
- for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
- output += "
[MT.get_equip_info()]
"
- output += "
"
- return output
-
-
-/obj/mecha/proc/get_log_html()
- var/output = "[src.name] Log "
- for(var/list/entry in log)
- output += {"[entry["time"]] [time2text(entry["date"],"MMM DD")] [entry["year"]]
- [entry["message"]]
- "}
- output += ""
- return output
-
-
-/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user)
- if(!id_card || !user) return
- var/output = {"
-
-
-
- Following keycodes are present in this system: "}
- for(var/a in operation_req_access)
- output += "[get_access_desc(a)] - Delete "
- output += "Following keycodes were detected on portable device: "
- for(var/a in id_card.access)
- if(a in operation_req_access) continue
- var/a_name = get_access_desc(a)
- if(!a_name) continue //there's some strange access without a name
- output += "[a_name] - Add "
- output += "Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.) "
- output += ""
- user << browse(output, "window=exosuit_add_access")
- onclose(user, "exosuit_add_access")
- return
-
-/obj/mecha/proc/output_maintenance_dialog(obj/item/weapon/card/id/id_card,mob/user)
- if(!id_card || !user) return
- var/output = {"
-
-
-
-
- [add_req_access?"Edit operation keycodes ":null]
- [maint_access?"Initiate maintenance protocol ":null]
- [(state>0) ?"Set Cabin Air Pressure ":null]
-
- "}
- user << browse(output, "window=exosuit_maint_console")
- onclose(user, "exosuit_maint_console")
- return
-
////////////////////////////////
/////// Messages and Log ///////
@@ -1473,172 +836,6 @@
var/year = time2text(world.realtime,"YYYY")
var/year_integer = text2num(year) // = 2013???
-/////////////////
-///// Topic /////
-/////////////////
-
-/obj/mecha/Topic(href, href_list)
- ..()
- if(href_list["update_content"])
- if(usr != src.occupant) return
- send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part())
- return
- if(href_list["close"])
- return
- if(usr.stat > 0)
- return
- var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
- if(href_list["select_equip"])
- if(usr != src.occupant) return
- var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip")
- if(equip)
- src.selected = equip
- src.occupant_message("You switch to [equip]")
- src.visible_message("[src] raises [equip]")
- send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list())
- return
- if(href_list["eject"])
- if(usr != src.occupant) return
- src.eject()
- return
- if(href_list["toggle_lights"])
- if(usr != src.occupant) return
- src.toggle_lights()
- return
- if(href_list["toggle_airtank"])
- if(usr != src.occupant) return
- src.toggle_internal_tank()
- return
- if(href_list["rmictoggle"])
- if(usr != src.occupant) return
- radio.broadcasting = !radio.broadcasting
- send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged"))
- return
- if(href_list["rspktoggle"])
- if(usr != src.occupant) return
- radio.listening = !radio.listening
- send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged"))
- return
- if(href_list["rfreq"])
- if(usr != src.occupant) return
- var/new_frequency = (radio.frequency + filter.getNum("rfreq"))
- if (!radio.freerange || (radio.frequency < 1200 || radio.frequency > 1600))
- new_frequency = sanitize_frequency(new_frequency)
- radio.set_frequency(new_frequency)
- send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]")
- return
- if(href_list["port_disconnect"])
- if(usr != src.occupant) return
- src.disconnect_from_port()
- return
- if (href_list["port_connect"])
- if(usr != src.occupant) return
- src.connect_to_port()
- return
- if (href_list["view_log"])
- if(usr != src.occupant) return
- src.occupant << browse(src.get_log_html(), "window=exosuit_log")
- onclose(occupant, "exosuit_log")
- return
- if (href_list["change_name"])
- if(usr != src.occupant) return
- var/newname = stripped_input(occupant,"Choose new exosuit name","Rename exosuit","", MAX_NAME_LEN)
- if(newname && trim(newname))
- name = newname
- else
- alert(occupant, "nope.avi")
- return
- if (href_list["toggle_id_upload"])
- if(usr != src.occupant) return
- add_req_access = !add_req_access
- send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel")
- return
- if(href_list["toggle_maint_access"])
- if(usr != src.occupant) return
- if(state)
- occupant_message("Maintenance protocols in effect ")
- return
- maint_access = !maint_access
- send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols")
- return
- if(href_list["req_access"] && add_req_access)
- if(!in_range(src, usr)) return
- output_access_dialog(filter.getObj("id_card"),filter.getMob("user"))
- return
- if(href_list["maint_access"] && maint_access)
- if(!in_range(src, usr)) return
- var/mob/user = filter.getMob("user")
- if(user)
- if(state==0)
- state = 1
- user << "The securing bolts are now exposed."
- else if(state==1)
- state = 0
- user << "The securing bolts are now hidden."
- output_maintenance_dialog(filter.getObj("id_card"),user)
- return
- if(href_list["set_internal_tank_valve"] && state >=1)
- if(!in_range(src, usr)) return
- var/mob/user = filter.getMob("user")
- if(user)
- var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num
- if(new_pressure)
- internal_tank_valve = new_pressure
- user << "The internal pressure valve has been set to [internal_tank_valve]kPa."
- if(href_list["add_req_access"] && add_req_access && filter.getObj("id_card"))
- if(!in_range(src, usr)) return
- operation_req_access += filter.getNum("add_req_access")
- output_access_dialog(filter.getObj("id_card"),filter.getMob("user"))
- return
- if(href_list["del_req_access"] && add_req_access && filter.getObj("id_card"))
- if(!in_range(src, usr)) return
- operation_req_access -= filter.getNum("del_req_access")
- output_access_dialog(filter.getObj("id_card"),filter.getMob("user"))
- return
- if(href_list["finish_req_access"])
- if(!in_range(src, usr)) return
- add_req_access = 0
- var/mob/user = filter.getMob("user")
- user << browse(null,"window=exosuit_add_access")
- return
- if(href_list["dna_lock"])
- if(usr != src.occupant)
- return
- if(src.occupant && !iscarbon(src.occupant))
- src.occupant << " You do not have any DNA! "
- return
- src.dna = src.occupant.dna.unique_enzymes
- src.occupant_message("You feel a prick as the needle takes your DNA sample.")
- return
- if(href_list["reset_dna"])
- if(usr != src.occupant) return
- src.dna = null
- if(href_list["repair_int_control_lost"])
- if(usr != src.occupant) return
- src.occupant_message("Recalibrating coordination system...")
- src.log_message("Recalibration of coordination system started.")
- var/T = src.loc
- if(do_after(100))
- if(T == src.loc)
- src.clearInternalDamage(MECHA_INT_CONTROL_LOST)
- src.occupant_message("Recalibration successful. ")
- src.log_message("Recalibration of coordination system finished with 0 errors.")
- else
- src.occupant_message("Recalibration failed! ")
- src.log_message("Recalibration of coordination system failed with 1 error.",1)
-
- //debug
- /*
- if(href_list["debug"])
- if(href_list["set_i_dam"])
- setInternalDamage(filter.getNum("set_i_dam"))
- if(href_list["clear_i_dam"])
- clearInternalDamage(filter.getNum("clear_i_dam"))
- return
- */
-
- return
-
///////////////////////
///// Power stuff /////
///////////////////////
@@ -1647,16 +844,14 @@ var/year_integer = text2num(year) // = 2013???
return (get_charge()>=amount)
/obj/mecha/proc/get_charge()
- return call((proc_res["dyngetcharge"]||src), "dyngetcharge")()
-
-/obj/mecha/proc/dyngetcharge()//returns null if no powercell, else returns cell.charge
- if(!src.cell) return
- return max(0, src.cell.charge)
+ for(var/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/R in equipment)
+ var/relay_charge = R.get_charge()
+ if(relay_charge)
+ return relay_charge
+ if(cell)
+ return max(0, cell.charge)
/obj/mecha/proc/use_power(amount)
- return call((proc_res["dynusepower"]||src), "dynusepower")(amount)
-
-/obj/mecha/proc/dynusepower(amount)
if(get_charge())
cell.use(amount)
return 1
@@ -1672,123 +867,121 @@ var/year_integer = text2num(year) // = 2013???
return 0
-//////////////////////////////////////////
-//////// Mecha global iterators ////////
-//////////////////////////////////////////
+//////////////////////////////////////// Action Buttons ///////////////////////////////////////////////
+
+/obj/mecha/proc/GrantActions(var/mob/living/user, var/human_occupant = 0)
+ if(human_occupant)
+ eject_action.chassis = src
+ eject_action.Grant(user)
+
+ internals_action.chassis = src
+ internals_action.Grant(user)
+
+ cycle_action.chassis = src
+ cycle_action.Grant(user)
+
+ lights_action.chassis = src
+ lights_action.Grant(user)
+
+ stats_action.chassis = src
+ stats_action.Grant(user)
-/datum/global_iterator/mecha_preserve_temp //normalizing cabin air temperature to 20 degrees celsium
- delay = 20
+/obj/mecha/proc/RemoveActions(var/mob/living/user, var/human_occupant = 0)
+ if(human_occupant)
+ eject_action.Remove(user)
+ internals_action.Remove(user)
+ cycle_action.Remove(user)
+ lights_action.Remove(user)
+ stats_action.Remove(user)
- process(var/obj/mecha/mecha)
- if(mecha.cabin_air && mecha.cabin_air.return_volume() > 0)
- var/delta = mecha.cabin_air.temperature - T20C
- mecha.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1)))
+
+/datum/action/mecha
+ check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUNNED | AB_CHECK_ALIVE
+ action_type = AB_INNATE
+ var/obj/mecha/chassis
+
+
+/datum/action/mecha/mech_eject
+ name = "Eject From Mech"
+ button_icon_state = "mech_eject"
+
+/datum/action/mecha/mech_eject/Activate()
+ if(!owner || !iscarbon(owner))
return
-
-/datum/global_iterator/mecha_tank_give_air
- delay = 15
-
- process(var/obj/mecha/mecha)
- if(mecha.internal_tank)
- var/datum/gas_mixture/tank_air = mecha.internal_tank.return_air()
- var/datum/gas_mixture/cabin_air = mecha.cabin_air
-
- var/release_pressure = mecha.internal_tank_valve
- var/cabin_pressure = cabin_air.return_pressure()
- var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2)
- var/transfer_moles = 0
- if(pressure_delta > 0) //cabin pressure lower than release pressure
- if(tank_air.return_temperature() > 0)
- transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
- var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
- cabin_air.merge(removed)
- else if(pressure_delta < 0) //cabin pressure higher than release pressure
- var/datum/gas_mixture/t_air = mecha.return_air()
- pressure_delta = cabin_pressure - release_pressure
- if(t_air)
- pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta)
- if(pressure_delta > 0) //if location pressure is lower than cabin pressure
- transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
- var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles)
- if(t_air)
- t_air.merge(removed)
- else //just delete the cabin gas, we're in space or some shit
- del(removed)
- else
- return stop()
+ if(!chassis || chassis.occupant != owner)
return
+ chassis.go_out()
-/datum/global_iterator/mecha_internal_damage // processing internal damage
+/datum/action/mecha/mech_toggle_internals
+ name = "Toggle Internal Airtank Usage"
+ button_icon_state = "mech_toggle_internals"
- process(var/obj/mecha/mecha)
- if(!mecha.hasInternalDamage())
- return stop()
- if(mecha.hasInternalDamage(MECHA_INT_FIRE))
- if(!mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL) && prob(5))
- mecha.clearInternalDamage(MECHA_INT_FIRE)
- if(mecha.internal_tank)
- if(mecha.internal_tank.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)))
- mecha.setInternalDamage(MECHA_INT_TANK_BREACH)
- var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air()
- if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents
- int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15))
- if(mecha.cabin_air && mecha.cabin_air.return_volume()>0)
- mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.return_temperature()+rand(10,15))
- if(mecha.cabin_air.return_temperature()>mecha.max_temperature/2)
- mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.return_temperature(),0.1),"fire")
- if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum
- mecha.pr_int_temp_processor.stop()
- if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank
- if(mecha.internal_tank)
- var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air()
- var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.10)
- if(mecha.loc && hascall(mecha.loc,"assume_air"))
- mecha.loc.assume_air(leaked_gas)
- else
- del(leaked_gas)
- if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
- if(mecha.get_charge())
- mecha.spark_system.start()
- mecha.cell.charge -= min(20,mecha.cell.charge)
- mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge)
+/datum/action/mecha/mech_toggle_internals/Activate()
+ if(!owner || !chassis || chassis.occupant != owner)
return
+ chassis.use_internal_tank = !chassis.use_internal_tank
+ if(chassis.use_internal_tank)
+ button_icon_state = "mech_toggle_internals_on"
+ else
+ button_icon_state = "mech_toggle_internals"
+ chassis.occupant_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
+ chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
-/////////////
+/datum/action/mecha/mech_cycle_equip
+ name = "Cycle Equipment"
+ button_icon_state = "mech_cycle_equip"
-//debug
-/*
-/obj/mecha/verb/test_int_damage()
- set name = "Test internal damage"
- set category = "Exosuit Interface"
- set src in view(0)
- if(!occupant) return
- if(usr!=occupant)
+/datum/action/mecha/mech_cycle_equip/Activate()
+ if(!owner || !chassis || chassis.occupant != owner)
return
- var/output = {"
-
-
-
- Set:
- MECHA_INT_FIRE
- MECHA_INT_TEMP_CONTROL
- MECHA_INT_SHORT_CIRCUIT
- MECHA_INT_TANK_BREACH
- MECHA_INT_CONTROL_LOST
-
- Clear:
- MECHA_INT_FIRE
- MECHA_INT_TEMP_CONTROL
- MECHA_INT_SHORT_CIRCUIT
- MECHA_INT_TANK_BREACH
- MECHA_INT_CONTROL_LOST
-
- "}
+ if(chassis.equipment.len == 0)
+ chassis.occupant_message("No equipment available.")
+ return
+ if(!chassis.selected)
+ chassis.selected = chassis.equipment[1]
+ chassis.occupant_message("You select [chassis.selected]")
+ send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list())
+ return
+ var/number = 0
+ for(var/A in chassis.equipment)
+ number++
+ if(A == chassis.selected)
+ if(chassis.equipment.len == number)
+ chassis.selected = null
+ chassis.occupant_message("You switch to no equipment")
+ else
+ chassis.selected = chassis.equipment[number+1]
+ chassis.occupant_message("You switch to [chassis.selected]")
+ send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list())
+ return
- occupant << browse(output, "window=ex_debug")
- //src.health = initial(src.health)/2.2
- //src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- return
-*/
+
+/datum/action/mecha/mech_toggle_lights
+ name = "Toggle Lights"
+ button_icon_state = "mech_toggle_lights"
+
+/datum/action/mecha/mech_toggle_lights/Activate()
+ if(!owner || !chassis || chassis.occupant != owner)
+ return
+ chassis.lights = !chassis.lights
+ if(chassis.lights)
+ chassis.AddLuminosity(chassis.lights_power)
+ button_icon_state = "mech_toggle_lights_on"
+ else
+ chassis.AddLuminosity(-chassis.lights_power)
+ button_icon_state = "mech_toggle_lights"
+ chassis.occupant_message("Toggled lights [chassis.lights?"on":"off"].")
+ chassis.log_message("Toggled lights [chassis.lights?"on":"off"].")
+
+
+/datum/action/mecha/mech_view_stats
+ name = "View Stats"
+ button_icon_state = "mech_view_stats"
+
+/datum/action/mecha/mech_view_stats/Activate()
+ if(!owner || !chassis || chassis.occupant != owner)
+ return
+ chassis.occupant << browse(chassis.get_stats_html(), "window=exosuit")
diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm
new file mode 100644
index 00000000000..3b61b31887f
--- /dev/null
+++ b/code/game/mecha/mecha_defense.dm
@@ -0,0 +1,345 @@
+
+/obj/mecha/proc/take_damage(amount, type="brute")
+ if(amount)
+ var/damage = absorbDamage(amount,type)
+ health -= damage
+ update_health()
+ occupant_message("Taking damage! ")
+ log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1)
+
+/obj/mecha/proc/absorbDamage(damage,damage_type)
+ var/coeff = 1
+ if(damage_absorption[damage_type])
+ coeff = damage_absorption[damage_type]
+ return damage*coeff
+
+
+/obj/mecha/proc/update_health()
+ if(src.health > 0)
+ src.spark_system.start()
+ else
+ qdel(src)
+
+/obj/mecha/attack_hulk(mob/living/carbon/human/user)
+ if(!prob(src.deflect_chance))
+ ..(user, 1)
+ take_damage(15)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ user.visible_message("[user] hits [src.name], doing some damage. ", "You hit [src.name] with all your might. The metal creaks and bends. ")
+ occupant_message("[user] hits [src.name], doing some damage. ")
+ return 1
+ return 0
+
+/obj/mecha/attack_hand(mob/living/user as mob)
+ user.changeNext_move(CLICK_CD_MELEE) // Ugh. Ideally we shouldn't be setting cooldowns outside of click code.
+ user.do_attack_animation(src)
+ src.log_message("Attack by hand/paw. Attacker - [user].",1)
+ user.visible_message("[user] hits [src.name]. Nothing happens ","You hit [src.name] with no visible effect. ")
+ src.log_append_to_last("Armor saved.")
+ return
+
+/obj/mecha/attack_paw(mob/user as mob)
+ return src.attack_hand(user)
+
+
+/obj/mecha/attack_alien(mob/living/user as mob)
+ src.log_message("Attack by alien. Attacker - [user].",1)
+ user.changeNext_move(CLICK_CD_MELEE) //Now stompy alien killer mechs are actually scary to aliens!
+ user.do_attack_animation(src)
+ if(!prob(src.deflect_chance))
+ take_damage(15)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ visible_message("The [user] slashes at [src.name]'s armor! ")
+ else
+ src.log_append_to_last("Armor saved.")
+ playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ user << "\green Your claws had no effect!"
+ visible_message("The [user] rebounds off [src.name]'s armor! ")
+ return
+
+
+/obj/mecha/attack_animal(mob/living/simple_animal/user as mob)
+ src.log_message("Attack by simple animal. Attacker - [user].",1)
+ user.changeNext_move(CLICK_CD_MELEE)
+ if(user.melee_damage_upper == 0)
+ user.emote("[user.friendly] [src]")
+ else
+ user.do_attack_animation(src)
+ if(!prob(src.deflect_chance))
+ var/damage = rand(user.melee_damage_lower, user.melee_damage_upper)
+ take_damage(damage)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ visible_message("[user] [user.attacktext] [src]! ")
+ add_logs(user, src, "attacked", admin=0)
+ else
+ src.log_append_to_last("Armor saved.")
+ playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ visible_message("The [user] rebounds off [src.name]'s armor! ")
+ add_logs(user, src, "attacked", admin=0)
+ return
+
+/obj/mecha/attack_tk()
+ return
+
+/obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper
+ log_message("Hit by [A].",1)
+ var/deflection = deflect_chance
+ var/dam_coeff = 1
+ var/counter_tracking = 0
+ for(var/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/B in equipment)
+ if(B.projectile_react())
+ deflection *= B.deflect_coeff
+ dam_coeff *= B.damage_coeff
+ counter_tracking = 1
+ break
+ if(istype(A, /obj/item/mecha_parts/mecha_tracking))
+ if(!counter_tracking)
+ A.forceMove(src)
+ visible_message("The [A] fastens firmly to [src].")
+ return
+ else
+ deflection = 100 //will bounce off
+ if(prob(deflection) || istype(A, /mob))
+ visible_message("[A] bounces off the [src.name] armor")
+ 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)
+ visible_message("[src.name] is hit by [A]. ")
+ take_damage(O.throwforce*dam_coeff)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ return
+
+
+/obj/mecha/bullet_act(var/obj/item/projectile/Proj) //wrapper
+ log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1)
+ var/deflection = deflect_chance
+ var/dam_coeff = 1
+ for(var/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/B in equipment)
+ if(B.projectile_react())
+ deflection *= B.deflect_coeff
+ dam_coeff *= B.damage_coeff
+ break
+ if(prob(deflection))
+ visible_message("The [src.name] armor deflects the projectile")
+ log_append_to_last("Armor saved.")
+ return
+ var/ignore_threshold
+ if(Proj.flag == "taser")
+ use_power(200)
+ return
+ if(istype(Proj, /obj/item/projectile/beam/pulse))
+ ignore_threshold = 1
+ if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ take_damage(Proj.damage*dam_coeff,Proj.flag)
+ visible_message("[src.name] is hit by [Proj]. ")
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
+ Proj.on_hit(src)
+
+/obj/mecha/ex_act(severity, target)
+ src.log_message("Affected by explosion of severity: [severity].",1)
+ if(prob(src.deflect_chance))
+ severity++
+ log_append_to_last("Armor saved, changing severity to [severity].")
+ switch(severity)
+ if(1.0)
+ qdel(src)
+ if(2.0)
+ if (prob(30))
+ qdel(src)
+ else
+ take_damage(initial(src.health)/2)
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
+ if(3.0)
+ if (prob(5))
+ qdel(src)
+ else
+ take_damage(initial(src.health)/5)
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
+ return
+
+/obj/mecha/blob_act()
+ take_damage(30, "brute")
+ return
+
+/obj/mecha/emp_act(severity)
+ if(get_charge())
+ use_power((cell.charge/2)/severity)
+ take_damage(50 / severity,"energy")
+ src.log_message("EMP detected",1)
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
+ return
+
+/obj/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature>src.max_temperature)
+ log_message("Exposed to dangerous temperature.",1)
+ take_damage(5,"fire")
+ check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL))
+ return
+
+
+/obj/mecha/attackby(obj/item/W as obj, mob/user as mob, params)
+
+ if(istype(W, /obj/item/device/mmi))
+ if(mmi_move_inside(W,user))
+ user << "[src]-[W] interface initialized successfuly"
+ else
+ user << "[src]-[W] interface initialization failed."
+ return
+
+ if(istype(W, /obj/item/mecha_parts/mecha_equipment))
+ var/obj/item/mecha_parts/mecha_equipment/E = W
+ spawn()
+ if(E.can_attach(src))
+ if(!user.drop_item())
+ return
+ E.attach(src)
+ user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]. ")
+ else
+ user << "You were unable to attach [W] to [src]! "
+ return
+ if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
+ if(add_req_access || maint_access)
+ if(internals_access_allowed(user))
+ var/obj/item/weapon/card/id/id_card
+ if(istype(W, /obj/item/weapon/card/id))
+ id_card = W
+ else
+ var/obj/item/device/pda/pda = W
+ id_card = pda.id
+ output_maintenance_dialog(id_card, user)
+ return
+ else
+ user << "Invalid ID: Access denied. "
+ else
+ user << "Maintenance protocols disabled by operator. "
+ else if(istype(W, /obj/item/weapon/wrench))
+ if(state==1)
+ state = 2
+ user << "You undo the securing bolts. "
+ else if(state==2)
+ state = 1
+ user << "You tighten the securing bolts. "
+ return
+ else if(istype(W, /obj/item/weapon/crowbar))
+ if(state==2)
+ state = 3
+ user << "You open the hatch to the power unit. "
+ else if(state==3)
+ state=2
+ user << "You close the hatch to the power unit. "
+ return
+ else if(istype(W, /obj/item/stack/cable_coil))
+ if(state == 3 && (internal_damage & MECHA_INT_SHORT_CIRCUIT))
+ var/obj/item/stack/cable_coil/CC = W
+ if(CC.use(2))
+ clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
+ user << "You replace the fused wires. "
+ else
+ user << "You need two lengths of cable to fix this mech! "
+ return
+ else if(istype(W, /obj/item/weapon/screwdriver))
+ if(internal_damage & MECHA_INT_TEMP_CONTROL)
+ clearInternalDamage(MECHA_INT_TEMP_CONTROL)
+ user << "You repair the damaged temperature controller. "
+ else if(state==3 && src.cell)
+ src.cell.forceMove(src.loc)
+ src.cell = null
+ state = 4
+ user << "You unscrew and pry out the powercell. "
+ src.log_message("Powercell removed")
+ else if(state==4 && src.cell)
+ state=3
+ user << "You screw the cell in place. "
+ return
+
+ else if(istype(W, /obj/item/weapon/stock_parts/cell))
+ if(state==4)
+ if(!src.cell)
+ if(!user.drop_item())
+ return
+ var/obj/item/weapon/stock_parts/cell/C = W
+ user << "You install the powercell. "
+ C.forceMove(src)
+ C.use(C.charge * 0.8)
+ src.cell = C
+ src.log_message("Powercell installed")
+ else
+ user << "There's already a powercell installed. "
+ return
+
+ else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm")
+ user.changeNext_move(CLICK_CD_MELEE)
+ var/obj/item/weapon/weldingtool/WT = W
+ if(src.healthYou repair the damaged gas tank. "
+ else
+ user.visible_message("[user] repairs some damage to [src.name]. ")
+ src.health += min(10, initial(src.health)-src.health)
+ else
+ user << "The welder must be on for this task! "
+ return 1
+ else
+ user << "The [src.name] is at full integrity! "
+ return 1
+
+ else if(istype(W, /obj/item/mecha_parts/mecha_tracking))
+ if(!user.unEquip(W))
+ user << "\the [W] is stuck to your hand, you cannot put it in \the [src]! "
+ return
+ W.forceMove(src)
+ user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]. ")
+ return
+
+ else if(!(W.flags&NOBLUDGEON))
+ user.changeNext_move(CLICK_CD_MELEE) // Ugh. Ideally we shouldn't be setting cooldowns outside of click code.
+ user.do_attack_animation(src)
+ log_message("Attacked by [W]. Attacker - [user]")
+ var/deflection = deflect_chance
+ var/dam_coeff = 1
+ for(var/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/B in equipment)
+ if(B.attack_react(user))
+ deflection *= B.deflect_coeff
+ dam_coeff *= B.damage_coeff
+ break
+ if(prob(deflection))
+ user << "The [W] bounces off [src.name] armor. "
+ src.log_append_to_last("Armor saved.")
+ return 0
+ else
+ user.visible_message("[user] hits [src] with [W]. ", "You hit [src] with [W]. ")
+ take_damage(round(W.force*dam_coeff),W.damtype)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ return 1
+
+
+/obj/mecha/proc/mech_toxin_damage(mob/living/target)
+ playsound(src, 'sound/effects/spray2.ogg', 50, 1)
+ if(target.reagents)
+ if(target.reagents.get_reagent_amount("cryptobiolin") + force < force*2)
+ target.reagents.add_reagent("cryptobiolin", force/2)
+ if(target.reagents.get_reagent_amount("toxin") + force < force*2)
+ target.reagents.add_reagent("toxin", force/2.5)
+
+
+/atom/proc/mech_melee_attack(obj/mecha/M)
+ return
+
+/obj/mecha/mech_melee_attack(obj/mecha/M)
+ if(M.damtype =="brute")
+ playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
+ else if(M.damtype == "fire")
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
+ else
+ return
+ visible_message("[M.name] has hit [src]. ")
+ take_damage(M.force, damtype)
+ add_logs(M.occupant, src, "attacked", object=M, addition="(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
+ return
\ No newline at end of file
diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm
index 0e6d689b85f..ec04357cf2c 100644
--- a/code/game/mecha/mecha_parts.dm
+++ b/code/game/mecha/mecha_parts.dm
@@ -175,27 +175,7 @@
/obj/item/mecha_parts/chassis/firefighter/New()
..()
construct = new /datum/construction/mecha/firefighter_chassis(src)
-/*
-/obj/item/mecha_parts/part/firefighter_torso
- name="Ripley-on-Fire Torso"
- icon_state = "ripley_harness"
-/obj/item/mecha_parts/part/firefighter_left_arm
- name="Ripley-on-Fire Left Arm"
- icon_state = "ripley_l_arm"
-
-/obj/item/mecha_parts/part/firefighter_right_arm
- name="Ripley-on-Fire Right Arm"
- icon_state = "ripley_r_arm"
-
-/obj/item/mecha_parts/part/firefighter_left_leg
- name="Ripley-on-Fire Left Leg"
- icon_state = "ripley_l_leg"
-
-/obj/item/mecha_parts/part/firefighter_right_leg
- name="Ripley-on-Fire Right Leg"
- icon_state = "ripley_r_leg"
-*/
////////// HONK
@@ -334,13 +314,6 @@
icon_state = "odysseus_r_leg"
origin_tech = "programming=2;materials=2;engineering=2"
-/*/obj/item/mecha_parts/part/odysseus_armor
- name="Odysseus Carapace"
- icon_state = "odysseus_armor"
- origin_tech = "materials=3;engineering=3"
- construction_time = 200
- construction_cost = list("metal"=15000)*/
-
///////// Circuitboards
diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm
new file mode 100644
index 00000000000..25ba30fde4a
--- /dev/null
+++ b/code/game/mecha/mecha_topic.dm
@@ -0,0 +1,321 @@
+
+////////////////////////////////////
+///// Rendering stats window ///////
+////////////////////////////////////
+
+/obj/mecha/proc/get_stats_html()
+ var/output = {"
+ [src.name] data
+
+
+
+
+
+ [src.get_stats_part()]
+
+
+ [src.get_equipment_list()]
+
+
+
+ [src.get_commands()]
+
+
+
+ "}
+ return output
+
+
+/obj/mecha/proc/report_internal_damage()
+ var/output = null
+ var/list/dam_reports = list(
+ "[MECHA_INT_FIRE]" = "INTERNAL FIRE ",
+ "[MECHA_INT_TEMP_CONTROL]" = "LIFE SUPPORT SYSTEM MALFUNCTION ",
+ "[MECHA_INT_TANK_BREACH]" = "GAS TANK BREACH ",
+ "[MECHA_INT_CONTROL_LOST]" = "COORDINATION SYSTEM CALIBRATION FAILURE - Recalibrate ",
+ "[MECHA_INT_SHORT_CIRCUIT]" = "SHORT CIRCUIT "
+ )
+ for(var/tflag in dam_reports)
+ var/intdamflag = text2num(tflag)
+ if(internal_damage & intdamflag)
+ output += dam_reports[tflag]
+ output += " "
+ if(return_pressure() > WARNING_HIGH_PRESSURE)
+ output += "DANGEROUSLY HIGH CABIN PRESSURE "
+ return output
+
+
+/obj/mecha/proc/get_stats_part()
+ var/integrity = health/initial(health)*100
+ var/cell_charge = get_charge()
+ var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None"
+ var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown"
+ var/cabin_pressure = round(return_pressure(),0.01)
+ var/output = {"[report_internal_damage()]
+ [integrity<30?"DAMAGE LEVEL CRITICAL ":null]
+ Integrity: [integrity]%
+ Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
+ Air source: [use_internal_tank?"Internal Airtank":"Environment"]
+ Airtank pressure: [tank_pressure]kPa
+ Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
+ Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure] ": cabin_pressure]kPa
+ Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
+ [src.dna?"DNA-locked: [src.dna] \[Reset \] ":null]
+ "}
+ return output
+
+/obj/mecha/proc/get_commands()
+ var/output = {"
+
+
+ "}
+ return output
+
+/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu
+ var/output
+ if(equipment.len)
+ output += {"
+
+
"}
+ for(var/obj/item/mecha_parts/mecha_equipment/W in equipment)
+ output += "[W.name]
Detach "
+ output += "
Available equipment slots: [max_equip-equipment.len]"
+ output += "
"
+ return output
+
+/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html
+ if(!equipment.len)
+ return
+ var/output = "Equipment: "
+ for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
+ output += "
[MT.get_equip_info()]
"
+ output += "
"
+ return output
+
+
+/obj/mecha/proc/get_log_html()
+ var/output = "[src.name] Log "
+ for(var/list/entry in log)
+ output += {"[entry["time"]] [time2text(entry["date"],"MMM DD")] [entry["year"]]
+ [entry["message"]]
+ "}
+ output += ""
+ return output
+
+
+/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user)
+ if(!id_card || !user) return
+ var/output = {"
+
+
+
+ Following keycodes are present in this system: "}
+ for(var/a in operation_req_access)
+ output += "[get_access_desc(a)] - Delete "
+ output += "Following keycodes were detected on portable device: "
+ for(var/a in id_card.access)
+ if(a in operation_req_access) continue
+ var/a_name = get_access_desc(a)
+ if(!a_name) continue //there's some strange access without a name
+ output += "[a_name] - Add "
+ output += "Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.) "
+ output += ""
+ user << browse(output, "window=exosuit_add_access")
+ onclose(user, "exosuit_add_access")
+ return
+
+/obj/mecha/proc/output_maintenance_dialog(obj/item/weapon/card/id/id_card,mob/user)
+ if(!id_card || !user) return
+ var/output = {"
+
+
+
+
+ [add_req_access?"Edit operation keycodes ":null]
+ [maint_access?"Initiate maintenance protocol ":null]
+ [(state>0) ?"Set Cabin Air Pressure ":null]
+
+ "}
+ user << browse(output, "window=exosuit_maint_console")
+ onclose(user, "exosuit_maint_console")
+ return
+
+
+
+/////////////////
+///// Topic /////
+/////////////////
+
+/obj/mecha/Topic(href, href_list)
+ ..()
+ if(href_list["close"])
+ return
+
+ if(usr.incapacitated())
+ return
+
+ var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
+
+ if(in_range(src, usr))
+
+ if(href_list["req_access"] && add_req_access)
+ output_access_dialog(filter.getObj("id_card"),filter.getMob("user"))
+
+ if(href_list["maint_access"] && maint_access)
+ var/mob/user = filter.getMob("user")
+ if(user)
+ if(state==0)
+ state = 1
+ user << "The securing bolts are now exposed."
+ else if(state==1)
+ state = 0
+ user << "The securing bolts are now hidden."
+ output_maintenance_dialog(filter.getObj("id_card"),user)
+
+ if(href_list["set_internal_tank_valve"] && state >=1)
+ var/mob/user = filter.getMob("user")
+ if(user)
+ var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num
+ if(new_pressure)
+ internal_tank_valve = new_pressure
+ user << "The internal pressure valve has been set to [internal_tank_valve]kPa."
+
+ if(href_list["add_req_access"] && add_req_access && filter.getObj("id_card"))
+ operation_req_access += filter.getNum("add_req_access")
+ output_access_dialog(filter.getObj("id_card"),filter.getMob("user"))
+
+ if(href_list["del_req_access"] && add_req_access && filter.getObj("id_card"))
+ operation_req_access -= filter.getNum("del_req_access")
+ output_access_dialog(filter.getObj("id_card"),filter.getMob("user"))
+
+ if(href_list["finish_req_access"])
+ add_req_access = 0
+ var/mob/user = filter.getMob("user")
+ user << browse(null,"window=exosuit_add_access")
+
+ if(usr != occupant)
+ return
+
+ if(href_list["update_content"])
+ send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part())
+
+ if(href_list["select_equip"])
+ var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip")
+ if(equip)
+ src.selected = equip
+ src.occupant_message("You switch to [equip]")
+ src.visible_message("[src] raises [equip]")
+ send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list())
+
+ if(href_list["rmictoggle"])
+ radio.broadcasting = !radio.broadcasting
+ send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged"))
+
+ if(href_list["rspktoggle"])
+ radio.listening = !radio.listening
+ send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged"))
+
+ if(href_list["rfreq"])
+ var/new_frequency = (radio.frequency + filter.getNum("rfreq"))
+ if (!radio.freerange || (radio.frequency < 1200 || radio.frequency > 1600))
+ new_frequency = sanitize_frequency(new_frequency)
+ radio.set_frequency(new_frequency)
+ send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]")
+
+ if (href_list["view_log"])
+ src.occupant << browse(src.get_log_html(), "window=exosuit_log")
+ onclose(occupant, "exosuit_log")
+
+ if (href_list["change_name"])
+ var/newname = stripped_input(occupant,"Choose new exosuit name","Rename exosuit","", MAX_NAME_LEN)
+ if(newname && trim(newname))
+ name = newname
+ else
+ alert(occupant, "nope.avi")
+
+ if (href_list["toggle_id_upload"])
+ add_req_access = !add_req_access
+ send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel")
+
+ if(href_list["toggle_maint_access"])
+ if(state)
+ occupant_message("Maintenance protocols in effect ")
+ return
+ maint_access = !maint_access
+ send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols")
+
+ if(href_list["dna_lock"])
+ if(occupant && !iscarbon(occupant))
+ occupant << " You do not have any DNA! "
+ return
+ dna = src.occupant.dna.unique_enzymes
+ occupant_message("You feel a prick as the needle takes your DNA sample.")
+
+ if(href_list["reset_dna"])
+ dna = null
+
+ if(href_list["repair_int_control_lost"])
+ occupant_message("Recalibrating coordination system...")
+ log_message("Recalibration of coordination system started.")
+ var/T = loc
+ spawn(100)
+ if(T == loc)
+ clearInternalDamage(MECHA_INT_CONTROL_LOST)
+ occupant_message("Recalibration successful. ")
+ log_message("Recalibration of coordination system finished with 0 errors.")
+ else
+ occupant_message("Recalibration failed! ")
+ log_message("Recalibration of coordination system failed with 1 error.",1)
+
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 78fcf6d541a..a83a4a8c422 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -13,15 +13,9 @@
var/list/cargo = new
var/cargo_capacity = 15
-/*
-/obj/mecha/working/ripley/New()
- ..()
- return
-*/
-
/obj/mecha/working/ripley/Move()
. = ..()
- if(. && (locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in equipment))
+ if(. && (locate(/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) in equipment))
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in cargo
if(ore_box)
for(var/obj/item/weapon/ore/ore in get_turf(src))
@@ -29,10 +23,11 @@
update_pressure()
/obj/mecha/working/ripley/Destroy()
- while(src.damage_absorption.["brute"] < 0.6)
- new /obj/item/asteroid/goliath_hide(src.loc)
- src.damage_absorption.["brute"] = src.damage_absorption.["brute"] + 0.1 //If a goliath-plated ripley gets killed, all the plates drop
- for(var/atom/movable/A in src.cargo)
+ var/hides = round((initial(damage_absorption["brute"]) - damage_absorption["brute"])*10)
+ for(var/i=0, i < hides, i++)
+ new /obj/item/asteroid/goliath_hide(loc) //If a goliath-plated ripley gets killed, all the plates drop
+ damage_absorption["brute"] = initial(damage_absorption["brute"])
+ for(var/atom/movable/A in cargo)
A.loc = loc
step_rand(A)
cargo.Cut()
@@ -40,30 +35,25 @@
/obj/mecha/working/ripley/go_out()
..()
- if (src.damage_absorption["brute"] < 0.6 && src.damage_absorption["brute"] > 0.3)
- src.overlays = null
- src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-open")
- else if (src.damage_absorption.["brute"] == 0.3)
- src.overlays = null
- src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full-open")
+ update_icon()
/obj/mecha/working/ripley/moved_inside(var/mob/living/carbon/human/H as mob)
..()
- if (src.damage_absorption["brute"] < 0.6 && src.damage_absorption["brute"] > 0.3)
- src.overlays = null
- src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g")
- else if (src.damage_absorption["brute"] == 0.3)
- src.overlays = null
- src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full")
+ update_icon()
/obj/mecha/working/ripley/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob)
..()
- if (src.damage_absorption["brute"] < 0.6 && src.damage_absorption["brute"] > 0.3)
- src.overlays = null
- src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g")
- else if (src.damage_absorption["brute"] == 0.3)
- src.overlays = null
- src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full")
+ update_icon()
+
+/obj/mecha/working/ripley/update_icon()
+ ..()
+ if (damage_absorption["brute"] < 0.6 && damage_absorption["brute"] > 0.3)
+ overlays = null
+ overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-open")
+ else if (damage_absorption.["brute"] == 0.3)
+ overlays = null
+ overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full-open")
+
/obj/mecha/working/ripley/firefighter
desc = "Autonomous Power Loader Unit. This model is refitted with additional thermal protection."
@@ -76,6 +66,7 @@
max_equip = 5 // More armor, less tools
wreckage = /obj/structure/mecha_wreckage/ripley/firefighter
+
/obj/mecha/working/ripley/deathripley
desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE"
name = "\improper DEATH-RIPLEY"
@@ -88,7 +79,7 @@
/obj/mecha/working/ripley/deathripley/New()
..()
- 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/hydraulic_clamp/kill
ME.attach(src)
return
@@ -100,10 +91,10 @@
..()
//Attach drill
if(prob(25)) //Possible diamond drill... Feeling lucky?
- var/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
+ var/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill
D.attach(src)
else
- var/obj/item/mecha_parts/mecha_equipment/tool/drill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill
+ var/obj/item/mecha_parts/mecha_equipment/drill/D = new /obj/item/mecha_parts/mecha_equipment/drill
D.attach(src)
//Add possible plasma cutter
@@ -115,12 +106,12 @@
cargo.Add(new /obj/structure/ore_box(src))
//Attach hydraulic clamp
- var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp
+ var/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp
HC.attach(src)
for(var/obj/item/mecha_parts/mecha_tracking/B in src.contents)//Deletes the beacon so it can't be found easily
qdel(B)
- var/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/scanner = new /obj/item/mecha_parts/mecha_equipment/tool/mining_scanner
+ var/obj/item/mecha_parts/mecha_equipment/mining_scanner/scanner = new /obj/item/mecha_parts/mecha_equipment/mining_scanner
scanner.attach(src)
/obj/mecha/working/ripley/Exit(atom/movable/O)
@@ -159,9 +150,9 @@
if(pressure < 20)
step_in = 3
- for(var/obj/item/mecha_parts/mecha_equipment/tool/drill/drill in equipment)
+ for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)/2
else
step_in = 5
- for(var/obj/item/mecha_parts/mecha_equipment/tool/drill/drill in equipment)
+ for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index b71cb447ff7..3879f0071e4 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -430,7 +430,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
/obj/item/singularity_pull(S, current_size)
spawn(0) //this is needed or multiple items will be thrown sequentially and not simultaneously
if(current_size >= STAGE_FOUR)
- throw_at(S,14,3)
+ throw_at(S,14,3, spin=0)
else ..()
/obj/item/acid_act(var/acidpwr, var/acid_volume)
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 6ef0a3fa4f8..26dc5d73cb7 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -243,7 +243,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/proc/can_use(mob/user)
if(user && ismob(user))
- if(user.stat || user.restrained() || user.paralysis || user.stunned || user.weakened)
+ if(user.incapacitated())
return 0
if(loc == user)
return 1
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 9dc2e9482ba..92004a21780 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -398,7 +398,7 @@ var/list/TYPES_SHORTCUTS = list(
/obj/item/weapon/reagent_containers = "REAGENT_CONTAINERS",
/obj/machinery/atmospherics = "ATMOS",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
- /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK",
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack = "MECHA_MISSILE_RACK",
/obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP",
)
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 2f3218f4e27..11bca2a452b 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -487,7 +487,7 @@ var/global/list/rockTurfEdgeCache
return
/* else if(istype(AM,/obj/mecha))
var/obj/mecha/M = AM
- if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill))
+ if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/drill))
src.attackby(M.selected,M)
return*/
//Aparantly mechs are just TOO COOL to call Bump(), so fuck em (for now)
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index d7c223124b6..7779f227a18 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -72,7 +72,10 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
else
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand")
spawn(6)
- var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc)
+ var/location = get_turf(affected_mob)
+ if(!location)
+ location = affected_mob.loc
+ var/mob/living/carbon/alien/larva/new_xeno = new(location)
new_xeno.key = C.key
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
if(gib_on_success)
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index cf6548b0e05..840f19ef3bb 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -10,10 +10,12 @@
src.reset_view(null)
src.unset_machine()
- src.updatehealth()
+ updatehealth()
update_gravity(mob_has_gravity())
+ update_action_buttons()
+
if (src.malfhack)
if (src.malfhack.aidisabled)
src << "ERROR: APC access disabled, hack attempt canceled. "
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 90c60fc5769..44e06e7d5c2 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -26,7 +26,7 @@
var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing
var/last_warning
var/consumedSupermatter = 0 //If the singularity has eaten a supermatter shard and can go to stage six
- allow_spin = 0
+
/obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0)
//CARN: admin-alert for chuckle-fuckery.
admin_investigate_setup()
diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm
index 95d25e4592b..a93cf7e7b52 100644
--- a/code/modules/research/designs/mecha_designs.dm
+++ b/code/modules/research/designs/mecha_designs.dm
@@ -227,7 +227,7 @@
id = "mech_grenade_launcher"
build_type = MECHFAB
req_tech = list("combat" = 3)
- build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang
+ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang
materials = list(MAT_METAL=22000,MAT_GOLD=6000,MAT_SILVER=8000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -238,7 +238,7 @@
id = "mech_missile_rack"
build_type = MECHFAB
req_tech = list("combat" = 6, "materials" = 6)
- build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack
+ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack
materials = list(MAT_METAL=22000,MAT_GOLD=6000,MAT_SILVER=8000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -249,7 +249,7 @@
id = "clusterbang_launcher"
build_type = MECHFAB
req_tech = list("combat"= 5, "materials" = 5, "syndicate" = 3)
- build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang
+ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/clusterbang
materials = list(MAT_METAL=20000,MAT_GOLD=10000,MAT_URANIUM=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -282,7 +282,7 @@
id = "mech_rcd"
build_type = MECHFAB
req_tech = list("materials" = 4, "bluespace" = 3, "magnets" = 4, "powerstorage"=4, "engineering" = 4)
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/rcd
+ build_path = /obj/item/mecha_parts/mecha_equipment/rcd
materials = list(MAT_METAL=30000,MAT_GOLD=20000,MAT_PLASMA=25000,MAT_SILVER=20000)
construction_time = 1200
category = list("Exosuit Equipment")
@@ -348,7 +348,7 @@
id = "mech_diamond_drill"
build_type = MECHFAB
req_tech = list("materials" = 4, "engineering" = 3)
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
+ build_path = /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill
materials = list(MAT_METAL=10000,MAT_DIAMOND=6500)
construction_time = 100
category = list("Exosuit Equipment")
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index ce602a5e800..c3a14613b65 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -490,7 +490,7 @@
name = "Exosuit Engineering Equipment (Hydraulic Clamp)"
id = "mech_hydraulic_clamp"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp
+ build_path = /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp
materials = list(MAT_METAL=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -499,7 +499,7 @@
name = "Exosuit Engineering Equipment (Drill)"
id = "mech_drill"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill
+ build_path = /obj/item/mecha_parts/mecha_equipment/drill
materials = list(MAT_METAL=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -508,7 +508,7 @@
name = "Exosuit Engineering Equipement (Mining Scanner)"
id = "mech_mscanner"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/mining_scanner
+ build_path = /obj/item/mecha_parts/mecha_equipment/mining_scanner
materials = list(MAT_METAL=5000,MAT_GLASS=2500)
construction_time = 50
category = list("Exosuit Equipment")
@@ -517,7 +517,7 @@
name = "Exosuit Engineering Equipment (Extinguisher)"
id = "mech_extinguisher"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/extinguisher
+ build_path = /obj/item/mecha_parts/mecha_equipment/extinguisher
materials = list(MAT_METAL=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -526,7 +526,7 @@
name = "Exosuit Engineering Equipment (Cable Layer)"
id = "mech_cable_layer"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/cable_layer
+ build_path = /obj/item/mecha_parts/mecha_equipment/cable_layer
materials = list(MAT_METAL=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -535,7 +535,7 @@
name = "Exosuit Medical Equipment (Mounted Sleeper)"
id = "mech_sleeper"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/sleeper
+ build_path = /obj/item/mecha_parts/mecha_equipment/sleeper
materials = list(MAT_METAL=5000,MAT_GLASS=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -544,7 +544,7 @@
name = "Exosuit Medical Equipment (Syringe Gun)"
id = "mech_syringe_gun"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
+ build_path = /obj/item/mecha_parts/mecha_equipment/syringe_gun
materials = list(MAT_METAL=3000,MAT_GLASS=2000)
construction_time = 200
category = list("Exosuit Equipment")
@@ -580,7 +580,7 @@
name = "H.O.N.K Mousetrap Mortar"
id = "mech_mousetrap_mortar"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar
+ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar
materials = list(MAT_METAL=20000,MAT_BANANIUM=5000)
construction_time = 300
category = list("Exosuit Equipment")
@@ -589,7 +589,7 @@
name = "H.O.N.K Banana Mortar"
id = "mech_banana_mortar"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar
+ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar
materials = list(MAT_METAL=20000,MAT_BANANIUM=5000)
construction_time = 300
category = list("Exosuit Equipment")
diff --git a/data/mode.txt b/data/mode.txt
index cf1ffd5c991..ef18df98db4 100644
--- a/data/mode.txt
+++ b/data/mode.txt
@@ -1 +1 @@
-extended
\ No newline at end of file
+extended
diff --git a/html/changelogs/phil235-MechRefactoring.yml b/html/changelogs/phil235-MechRefactoring.yml
new file mode 100644
index 00000000000..c8e188f6fc5
--- /dev/null
+++ b/html/changelogs/phil235-MechRefactoring.yml
@@ -0,0 +1,4 @@
+author: phil235
+delete-after: True
+changes:
+ - rscadd: "Mechs no longer use object verbs and the exosuit interface tab. They now use action buttons. Mechs now have a cycle equipment action button to change weapon faster than by using the view stats window. Mechs get two special alerts when their battery or health is low. Mechs now properly consume energy when moving and having their lights on. Using a mech tool that takes time to act now shows a progress bar (e.g. mech drill)."
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
index 4ced7caebed..0636ebac478 100644
Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index 0ed43592376..1b707cda5e0 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index f1be4b290bc..cabc33c6f09 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -215,7 +215,6 @@
#include "code\datums\helper_datums\construction_datum.dm"
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
-#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\icon_snapshot.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
@@ -501,7 +500,9 @@
#include "code\game\mecha\mecha.dm"
#include "code\game\mecha\mecha_construction_paths.dm"
#include "code\game\mecha\mecha_control_console.dm"
+#include "code\game\mecha\mecha_defense.dm"
#include "code\game\mecha\mecha_parts.dm"
+#include "code\game\mecha\mecha_topic.dm"
#include "code\game\mecha\mecha_wreckage.dm"
#include "code\game\mecha\combat\combat.dm"
#include "code\game\mecha\combat\durand.dm"
@@ -512,7 +513,9 @@
#include "code\game\mecha\combat\reticence.dm"
#include "code\game\mecha\equipment\mecha_equipment.dm"
#include "code\game\mecha\equipment\tools\medical_tools.dm"
-#include "code\game\mecha\equipment\tools\tools.dm"
+#include "code\game\mecha\equipment\tools\mining_tools.dm"
+#include "code\game\mecha\equipment\tools\other_tools.dm"
+#include "code\game\mecha\equipment\tools\work_tools.dm"
#include "code\game\mecha\equipment\weapons\weapons.dm"
#include "code\game\mecha\medical\medical.dm"
#include "code\game\mecha\medical\odysseus.dm"