diff --git a/_maps/map_files/RandomZLevels/spacebattle.dmm b/_maps/map_files/RandomZLevels/spacebattle.dmm
index f398c6134e5..3f824e041db 100644
--- a/_maps/map_files/RandomZLevels/spacebattle.dmm
+++ b/_maps/map_files/RandomZLevels/spacebattle.dmm
@@ -190,8 +190,8 @@
"dH" = (/obj/item/stack/rods,/turf/simulated/floor/plasteel,/area/awaymission/spacebattle/cruiser)
"dI" = (/obj/mecha/medical/odysseus,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"dJ" = (/obj/mecha/working/ripley/firefighter,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
-"dK" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
-"dL" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/tool/drill,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
+"dK" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
+"dL" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/drill,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"dM" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"dN" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"dO" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor/plasteel{icon_state = "bar"},/area/awaymission/spacebattle/cruiser)
@@ -209,7 +209,7 @@
"ea" = (/obj/machinery/gateway{dir = 9},/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"eb" = (/obj/machinery/gateway{dir = 1},/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"ec" = (/obj/machinery/gateway{dir = 5},/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
-"ed" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
+"ed" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/syringe_gun,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"ee" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/repair_droid,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser)
"ef" = (/mob/living/simple_animal/hostile/syndicate/melee,/turf/simulated/floor/plasteel{icon_state = "bar"},/area/awaymission/spacebattle/cruiser)
"eg" = (/obj/structure/closet/l3closet/security,/turf/simulated/floor/plasteel{icon_state = "red"; dir = 4},/area/awaymission/spacebattle/cruiser)
diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm
index 1938244976c..c8213e50a6f 100644
--- a/_maps/map_files/cyberiad/z2.dmm
+++ b/_maps/map_files/cyberiad/z2.dmm
@@ -1127,7 +1127,7 @@
"Eb" = (/obj/structure/rack,/obj/item/clothing/shoes/magboots/syndie{pixel_x = -3; pixel_y = 3},/obj/item/clothing/shoes/magboots/advance,/obj/item/clothing/shoes/magboots{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Ec" = (/obj/structure/rack,/obj/item/clothing/shoes/green{pixel_x = -3; pixel_y = 3},/obj/item/clothing/shoes/centcom,/obj/item/clothing/shoes/syndigaloshes{pixel_x = 3; pixel_y = -3},/obj/item/clothing/shoes/rainbow{pixel_x = -3; pixel_y = 3},/obj/item/clothing/shoes/combat/swat,/obj/item/clothing/shoes/combat{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Ed" = (/obj/structure/rack,/obj/item/clothing/suit/pirate_black{pixel_x = -3; pixel_y = 3},/obj/item/clothing/suit/blacktrenchcoat,/obj/item/clothing/suit/jacket{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
-"Ee" = (/obj/item/mecha_parts/mecha_equipment/tool/cable_layer,/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill,/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,/obj/item/mecha_parts/mecha_equipment/tool/rcd,/obj/item/mecha_parts/mecha_equipment/tool/extinguisher,/obj/structure/closet/crate,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
+"Ee" = (/obj/item/mecha_parts/mecha_equipment/cable_layer,/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill,/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp,/obj/item/mecha_parts/mecha_equipment/rcd,/obj/item/mecha_parts/mecha_equipment/extinguisher,/obj/structure/closet/crate,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Ef" = (/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 4; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5 (EAST)"},/area/admin)
"Eg" = (/obj/structure/rack,/obj/item/clothing/under/syndicate{pixel_x = -3; pixel_y = 3},/obj/item/clothing/under/syndicate/combat,/obj/item/clothing/under/acj{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Eh" = (/obj/structure/mirror{pixel_y = -30},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
diff --git a/code/datums/helper_datums/events.dm b/code/datums/helper_datums/events.dm
index bb5e76deef3..fa0dccd2a15 100644
--- a/code/datums/helper_datums/events.dm
+++ b/code/datums/helper_datums/events.dm
@@ -6,62 +6,63 @@
/datum/events
var/list/events
- New()
- ..()
- events = new
+/datum/events/New()
+ ..()
+ events = new
- proc/addEventType(event_type as text)
- if(!(event_type in events) || !islist(events[event_type]))
- events[event_type] = list()
- return 1
- return
-
-
- // Arguments: event_type as text, proc_holder as datum, proc_name as text
- // Returns: New event, null on error.
- proc/addEvent(event_type as text, proc_holder, proc_name as text)
- if(!event_type || !proc_holder || !proc_name)
- return
- addEventType(event_type)
- var/list/event = events[event_type]
- var/datum/events_event/E = new /datum/events_event(proc_holder,proc_name)
- event += E
- return E
-
- // Arguments: event_type as text, any number of additional arguments to pass to event handler
- // Returns: null
- proc/fireEvent()
-// to_chat(world, "Events in [args[1]] called")
- var/list/event = listgetindex(events,args[1])
- if(istype(event))
- spawn(-1)
- for(var/datum/events_event/E in event)
- if(!E.Fire(arglist(args.Copy(2))))
- clearEvent(args[1],E)
- return
-
- // Arguments: event_type as text, E as /datum/events_event
- // Returns: 1 if event cleared, null on error
- proc/clearEvent(event_type as text, datum/events_event/E)
- if(!event_type || !E)
- return
- var/list/event = listgetindex(events,event_type)
- event -= E
+/datum/events/proc/addEventType(event_type as text)
+ if(!(event_type in events) || !islist(events[event_type]))
+ events[event_type] = list()
return 1
+ return
-/datum/events_event
+// Arguments: event_type as text, proc_holder as datum, proc_name as text
+// Returns: New event, null on error.
+/datum/events/proc/addEvent(event_type as text, proc_holder, proc_name as text)
+ if(!event_type || !proc_holder || !proc_name)
+ return
+ addEventType(event_type)
+ var/list/event = events[event_type]
+ var/datum/event/E = new /datum/event(proc_holder,proc_name)
+ event += E
+ return E
+
+// Arguments: event_type as text, any number of additional arguments to pass to event handler
+// Returns: null
+/datum/events/proc/fireEvent()
+ //world << "Events in [args[1]] called"
+ var/list/event = listgetindex(events,args[1])
+ if(istype(event))
+ spawn(0)
+ for(var/datum/event/E in event)
+ if(!E.Fire(arglist(args.Copy(2))))
+ clearEvent(args[1],E)
+ return
+
+// Arguments: event_type as text, E as /datum/event
+// Returns: 1 if event cleared, null on error
+
+/datum/events/proc/clearEvent(event_type as text, datum/event/E)
+ if(!event_type || !E)
+ return
+ var/list/event = listgetindex(events,event_type)
+ event -= E
+ return 1
+
+
+/datum/event
var/listener
var/proc_name
- New(tlistener,tprocname)
- listener = tlistener
- proc_name = tprocname
- return ..()
+/datum/event/New(tlistener,tprocname)
+ listener = tlistener
+ proc_name = tprocname
+ return ..()
- proc/Fire()
-// to_chat(world, "Event fired")
- if(listener)
- call(listener,proc_name)(arglist(args))
- return 1
- return
\ No newline at end of file
+/datum/event/proc/Fire()
+ //world << "Event fired"
+ if(listener)
+ call(listener,proc_name)(arglist(args))
+ return 1
+ return
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index a903e4ea8ed..0dd6c109170 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -345,3 +345,22 @@
if(buckled_mob == mover)
return 1
return ..()
+
+/atom/movable/proc/get_spacemove_backup()
+ var/atom/movable/dense_object_backup
+ for(var/A in orange(1, get_turf(src)))
+ if(isarea(A))
+ continue
+ else if(isturf(A))
+ var/turf/turf = A
+ if(!turf.density)
+ continue
+ return turf
+ else
+ var/atom/movable/AM = A
+ if(!AM.CanPass(src) || AM.density)
+ if(AM.anchored)
+ return AM
+ dense_object_backup = AM
+ break
+ . = dense_object_backup
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 29dd5b7c9c1..3f21e952a36 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1001,7 +1001,7 @@ About the new airlock wires panel:
to_chat(user, "The hatch is coated with a product that prevents the shaped charge from sticking!")
return
- if(istype(C, /obj/item/mecha_parts/mecha_equipment/tool/rcd) || istype(C, /obj/item/weapon/rcd))
+ if(istype(C, /obj/item/mecha_parts/mecha_equipment/rcd) || istype(C, /obj/item/weapon/rcd))
to_chat(user, "The hatch is made of an advanced compound that cannot be deconstructed using an RCD.")
return
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index d9b26404cad..99db971b420 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -3,8 +3,6 @@
var/maxsize = 2
internal_damage_threshold = 50
maint_access = 0
- //add_req_access = 0
- //operation_req_access = list(access_hos)
damage_absorption = list("brute"=0.7,"fire"=1,"bullet"=0.7,"laser"=0.85,"energy"=1,"bomb"=0.8)
var/am = "d3c2fbcadca903a41161ccc9df9cf948"
@@ -26,21 +24,13 @@
/obj/mecha/combat/go_out()
- if(src.occupant && src.occupant.client)
- src.occupant.client.mouse_pointer_icon = initial(src.occupant.client.mouse_pointer_icon)
+ if(occupant && occupant.client)
+ occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon)
..()
- return
/obj/mecha/combat/Topic(href,href_list)
..()
- var/datum/topic_input/filter = new (href,href_list)
+ var/datum/topic_input/filter = new(href, href_list)
if(filter.get("close"))
am = null
- return
- /*
- if(filter.get("saminput"))
- if(md5(filter.get("saminput")) == am)
- occupant_message("From the lies of the Antipath, Circuit preserve us.")
- am = null
- return
- */
\ No newline at end of file
+ return
\ No newline at end of file
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index cfe94888123..57614a8e426 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -22,17 +22,15 @@
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack
ME.attach(src)
- return
/obj/mecha/combat/durand/relaymove(mob/user,direction)
if(defence)
if(world.time - last_message > 20)
- src.occupant_message("Unable to move while in defence mode")
+ occupant_message("Unable to move while in defence mode")
last_message = world.time
return 0
. = ..()
- return
/obj/mecha/combat/durand/verb/defence_mode()
@@ -40,17 +38,16 @@
set name = "Toggle defence mode"
set src = usr.loc
set popup_menu = 0
- if(usr!=src.occupant)
+ if(usr != occupant)
return
defence = !defence
if(defence)
deflect_chance = defence_deflect
- src.occupant_message("You enable [src] defence mode.")
+ occupant_message("You enable [src] defence mode.")
else
deflect_chance = initial(deflect_chance)
- src.occupant_message("You disable [src] defence mode.")
- src.log_message("Toggled defence mode.")
- return
+ occupant_message("You disable [src] defence mode.")
+ log_message("Toggled defence mode.")
/obj/mecha/combat/durand/get_stats_part()
@@ -72,8 +69,7 @@
/obj/mecha/combat/durand/Topic(href, href_list)
..()
if(href_list["toggle_defence_mode"])
- src.defence_mode()
- return
+ defence_mode()
/obj/mecha/combat/durand/old
desc = "A retired, third-generation combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms."
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index 09caf2fcaf0..faa2329f5e4 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -24,7 +24,6 @@
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang
ME.attach(src)
- return
/obj/mecha/combat/gygax/dark
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
@@ -51,7 +50,6 @@
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
ME.attach(src)
- return
/obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/stock_parts/cell/C=null)
if(C)
@@ -68,31 +66,30 @@
set name = "Toggle leg actuators overload"
set src = usr.loc
set popup_menu = 0
- if(usr!=src.occupant)
+ if(usr != occupant)
return
if(overload)
overload = 0
step_in = initial(step_in)
step_energy_drain = initial(step_energy_drain)
- src.occupant_message("You disable leg actuators overload.")
+ occupant_message("You disable leg actuators overload.")
else
overload = 1
step_in = min(1, round(step_in/2))
step_energy_drain = step_energy_drain*overload_coeff
- src.occupant_message("You enable leg actuators overload.")
- src.log_message("Toggled leg actuators overload.")
- return
+ occupant_message("You enable leg actuators overload.")
+ log_message("Toggled leg actuators overload.")
-/obj/mecha/combat/gygax/dyndomove(direction)
- if(!..()) return
+/obj/mecha/combat/gygax/domove(direction)
+ if(!..())
+ return
if(overload)
health--
- if(health < initial(health) - initial(health)/3)
+ if(health < initial(health) - initial(health) / 3)
overload = 0
step_in = initial(step_in)
step_energy_drain = initial(step_energy_drain)
- src.occupant_message("Leg actuators damage threshold exceded. Disabling overload.")
- return
+ occupant_message("Leg actuators damage threshold exceded. Disabling overload.")
/obj/mecha/combat/gygax/get_stats_part()
@@ -114,5 +111,4 @@
/obj/mecha/combat/gygax/Topic(href, href_list)
..()
if(href_list["toggle_leg_overload"])
- src.overload()
- return
\ No newline at end of file
+ overload()
\ No newline at end of file
diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm
index 4bfd5f9a161..1053b3e9856 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -24,7 +24,6 @@
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar
ME.attach(src)
- return
/obj/mecha/combat/honker/get_stats_part()
var/integrity = health/initial(health)*100
@@ -45,13 +44,13 @@
HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
HONK temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
Lights: [lights?"on":"off"]
- [src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null]
+ [dna?"DNA-locked:
[dna] \[Reset\]
":null]
"}
return output
/obj/mecha/combat/honker/get_stats_html()
var/output = {"
-
[src.name] data
+ [name] data
-
-
- Health statistics
-
- [get_occupant_dam()]
-
- Reagents in bloodstream
-
- [get_occupant_reagents()]
-
-
- [get_available_reagents()]
-
-
- "}
-
- proc/get_occupant_dam()
- var/t1
- switch(occupant.stat)
- if(0)
- t1 = "Conscious"
- if(1)
- t1 = "Unconscious"
- if(2)
- t1 = "*dead*"
- else
- t1 = "Unknown"
- return {"Health: [occupant.health]% ([t1])
- Core Temperature: [src.occupant.bodytemperature-T0C]°C ([src.occupant.bodytemperature*1.8-459.67]°F)
- Brute Damage: [occupant.getBruteLoss()]%
- Respiratory Damage: [occupant.getOxyLoss()]%
- Toxin Content: [occupant.getToxLoss()]%
- Burn Severity: [occupant.getFireLoss()]%
- "}
-
- proc/get_occupant_reagents()
- if(occupant.reagents)
- for(var/datum/reagent/R in occupant.reagents.reagent_list)
- if(R.volume > 0)
- . += "[R]: [round(R.volume,0.01)]
"
- return . || "None"
-
- proc/get_available_reagents()
- var/output
- var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun) in chassis
- if(SG && SG.reagents && islist(SG.reagents.reagent_list))
- for(var/datum/reagent/R in SG.reagents.reagent_list)
- if(R.volume > 0)
- output += "Inject [R.name]
"
- return output
-
-
- proc/inject_reagent(var/datum/reagent/R,var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG)
- if(!R || !occupant || !SG || !(SG in chassis.equipment))
- return 0
- var/to_inject = min(R.volume, inject_amount)
- if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2)
- occupant_message("Injecting [occupant] with [to_inject] units of [R.name].")
- log_message("Injecting [occupant] with [to_inject] units of [R.name].")
- SG.reagents.trans_id_to(occupant,R.id,to_inject)
- update_equip_info()
- return
-
- container_resist(var/mob/living/L)
- go_out()
-
- update_equip_info()
- if(..())
- send_byjax(chassis.occupant,"msleeper.browser","lossinfo",get_occupant_dam())
- send_byjax(chassis.occupant,"msleeper.browser","reagents",get_occupant_reagents())
- send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents())
- return 1
- return
-
-/datum/global_iterator/mech_sleeper
-
- process(var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S)
- if(!S.chassis)
- S.set_ready_state(1)
- return stop()
- if(!S.chassis.has_charge(S.energy_drain))
- S.set_ready_state(1)
- S.log_message("Deactivated.")
- S.occupant_message("[src] deactivated - no power.")
- return stop()
- var/mob/living/carbon/M = S.occupant
- if(!M)
- return
- if(M.health > 0)
- M.adjustOxyLoss(-1)
- M.updatehealth()
- M.AdjustStunned(-4)
- M.AdjustWeakened(-4)
- M.AdjustStunned(-4)
- 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
-
-
-/obj/item/mecha_parts/mecha_equipment/tool/cable_layer
- name = "Cable Layer"
- 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
-
- New()
- cable = new(src)
- cable.amount = 0
- ..()
-
- can_attach(obj/mecha/working/M)
- if(..())
- if(istype(M))
- return 1
- return 0
-
- attach()
- ..()
- event = chassis.events.addEvent("onMove",src,"layCable")
- return
-
- detach()
- chassis.events.clearEvent("onMove",event)
- return ..()
-
- Destroy()
- chassis.events.clearEvent("onMove",event)
- return ..()
-
- 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
-
- 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
-
- 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
-
- 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
-
- 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)
+ target.forceMove(src)
+ patient = target
+ processing_objects.Add(src)
update_equip_info()
+ occupant_message("[target] successfully loaded into [src]. Life support functions engaged.")
+ chassis.visible_message("[chassis] loads [target] into [src].")
+ log_message("[target] loaded. Life support functions engaged.")
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target)
+ if(target.buckled)
+ occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled]!")
+ return
+ if(target.has_buckled_mobs())
+ occupant_message("[target] will not fit into the sleeper because of the creatures attached to it!")
+ return
+ if(patient)
+ occupant_message("The sleeper is already occupied!")
+ return
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/go_out()
+ if(!patient)
+ return
+ patient.forceMove(get_turf(src))
+ occupant_message("[patient] ejected. Life support functions disabled.")
+ log_message("[patient] ejected. Life support functions disabled.")
+ processing_objects.Remove(src)
+ patient = null
+ update_equip_info()
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/detach()
+ if(patient)
+ occupant_message("Unable to detach [src] - equipment occupied!")
+ return
+ processing_objects.Remove(src)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/get_equip_info()
+ var/output = ..()
+ if(output)
+ var/temp = ""
+ if(patient)
+ temp = "
\[Occupant: [patient] ([patient.stat > 1 ? "*DECEASED*" : "Health: [patient.health]%"])\]
View stats|Eject"
+ return "[output] [temp]"
+ return
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/Topic(href,href_list)
+ ..()
+ var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
+ if(filter.get("eject"))
+ go_out()
+ if(filter.get("view_stats"))
+ chassis.occupant << browse(get_patient_stats(),"window=msleeper")
+ onclose(chassis.occupant, "msleeper")
+ return
+ if(filter.get("inject"))
+ inject_reagent(filter.getType("inject",/datum/reagent),filter.getObj("source"))
+ return
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_stats()
+ if(!patient)
+ return
+ return {"
+
+ [patient] statistics
+
+
+
+
+ Health statistics
+
+ [get_patient_dam()]
+
+ Reagents in bloodstream
+
+ [get_patient_reagents()]
+
+
+ [get_available_reagents()]
+
+
+ "}
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_dam()
+ var/t1
+ switch(patient.stat)
+ if(0)
+ t1 = "Conscious"
+ if(1)
+ t1 = "Unconscious"
+ if(2)
+ t1 = "*dead*"
+ else
+ t1 = "Unknown"
+ 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/medical/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/medical/sleeper/proc/get_available_reagents()
+ var/output
+ var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun) in chassis
+ if(SG && SG.reagents && islist(SG.reagents.reagent_list))
+ for(var/datum/reagent/R in SG.reagents.reagent_list)
+ if(R.volume > 0)
+ output += "Inject [R.name]
"
+ return output
+
+
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/inject_reagent(datum/reagent/R,obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG)
+ if(!R || !patient || !SG || !(SG in chassis.equipment))
+ return 0
+ var/to_inject = min(R.volume, inject_amount)
+ 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", "[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/medical/sleeper/update_equip_info()
+ if(..())
+ if(patient)
+ 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
- proc/reset()
- last_piece = null
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/container_resist()
+ go_out()
- 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/medical/sleeper/process()
+ if(..())
+ return
+ if(!chassis.has_charge(energy_drain))
+ set_ready_state(1)
+ log_message("Deactivated.")
+ occupant_message("[src] deactivated - no power.")
+ processing_objects.Remove(src)
+ return
+ var/mob/living/carbon/M = patient
+ if(!M)
+ return
+ if(M.health > 0)
+ M.adjustOxyLoss(-1)
+ M.updatehealth()
+ M.AdjustStunned(-4)
+ M.AdjustWeakened(-4)
+ M.AdjustStunned(-4)
+ if(M.reagents.get_reagent_amount("epinephrine") < 5)
+ M.reagents.add_reagent("epinephrine", 5)
+ chassis.use_power(energy_drain)
+ update_equip_info()
- 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()
- PN.add_cable(NC)
- NC.mergeConnectedNetworks(NC.d2)
-
- //NC.mergeConnectedNetworksOnTurf()
- last_piece = NC
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
- name = "Syringe Gun"
- desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)"
+/obj/item/mecha_parts/mecha_equipment/medical/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'
icon_state = "syringegun"
- item_state = "syringegun"
- lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/guns_righthand.dmi'
+ flags = NOREACT
var/list/syringes
var/list/known_reagents
var/list/processed_reagents
@@ -397,273 +252,271 @@
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"
+ origin_tech = "materials=3;biotech=4;magnets=4"
- 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/medical/syringe_gun/New()
+ ..()
+ create_reagents(max_volume)
+ syringes = new
+ known_reagents = list("epinephrine"="Epinephrine","charcoal"="Charcoal")
+ processed_reagents = new
- detach()
- synth.stop()
- return ..()
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/detach()
+ processing_objects.Remove(src)
+ return ..()
- critfail()
- ..()
- flags &= ~NOREACT
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/critfail()
+ ..()
+ flags &= ~NOREACT
+
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/can_attach(obj/mecha/medical/M)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/medical/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/medical/syringe_gun/action(atom/movable/target)
+ if(!action_checks(target))
return
-
- can_attach(obj/mecha/medical/M)
- if(..())
- if(istype(M))
- return 1
- return 0
-
- 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"
+ if(istype(target,/obj/item/weapon/reagent_containers/syringe))
+ return load_syringe(target)
+ if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes
+ for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents)
+ load_syringe(S)
return
-
- action(atom/movable/target)
- if(!action_checks(target))
- return
- if(istype(target,/obj/item/weapon/reagent_containers/syringe))
- return load_syringe(target)
- if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes
- for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents)
- load_syringe(S)
- return
- if(mode)
- return analyze_reagents(target)
- if(!syringes.len)
- occupant_message("No syringes loaded.")
- return
- if(reagents.total_volume<=0)
- occupant_message("No available reagents to load syringe with.")
- return
- set_ready_state(0)
- chassis.use_power(energy_drain)
- var/turf/trg = get_turf(target)
- var/obj/item/weapon/reagent_containers/syringe/S = syringes[1]
- S.forceMove(get_turf(chassis))
- reagents.trans_to(S, min(S.volume, reagents.total_volume))
- syringes -= S
- S.icon = 'icons/obj/chemical.dmi'
- S.icon_state = "syringeproj"
- playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
- log_message("Launched [S] from [src], targeting [target].")
- spawn(-1)
- src = null //if src is deleted, still process the syringe
- for(var/i=0, i<6, i++)
- if(!S)
- break
- if(step_towards(S,trg))
- var/list/mobs = new
- for(var/mob/living/carbon/M in S.loc)
- mobs += M
- var/mob/living/carbon/M = safepick(mobs)
- if(M)
- S.icon_state = initial(S.icon_state)
- S.icon = initial(S.icon)
- S.reagents.reaction(M, INGEST)
- S.reagents.trans_to(M, S.reagents.total_volume)
+ if(mode)
+ return analyze_reagents(target)
+ if(!syringes.len)
+ occupant_message("No syringes loaded.")
+ return
+ if(reagents.total_volume<=0)
+ occupant_message("No available reagents to load syringe with.")
+ return
+ var/turf/trg = get_turf(target)
+ var/obj/item/weapon/reagent_containers/syringe/mechsyringe = syringes[1]
+ mechsyringe.forceMove(get_turf(chassis))
+ reagents.trans_to(mechsyringe, min(mechsyringe.volume, reagents.total_volume))
+ syringes -= mechsyringe
+ mechsyringe.icon = 'icons/obj/chemical.dmi'
+ mechsyringe.icon_state = "syringeproj"
+ playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
+ log_message("Launched [mechsyringe] from [src], targeting [target].")
+ var/mob/originaloccupant = chassis.occupant
+ spawn(0)
+ src = null //if src is deleted, still process the syringe
+ for(var/i=0, i<6, i++)
+ if(!mechsyringe)
+ break
+ if(step_towards(mechsyringe,trg))
+ var/list/mobs = new
+ for(var/mob/living/carbon/M in mechsyringe.loc)
+ mobs += M
+ var/mob/living/carbon/M = safepick(mobs)
+ if(M)
+ var/R
+ mechsyringe.visible_message(" [M] was hit by the syringe!")
+ if(M.can_inject(null, 1))
+ if(mechsyringe.reagents)
+ for(var/datum/reagent/A in mechsyringe.reagents.reagent_list)
+ R += A.id + " ("
+ R += num2text(A.volume) + "),"
+ mechsyringe.icon_state = initial(mechsyringe.icon_state)
+ mechsyringe.icon = initial(mechsyringe.icon)
+ mechsyringe.reagents.reaction(M, INGEST)
+ mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume)
M.take_organ_damage(2)
- S.visible_message(" [M] was hit by the syringe!")
- break
- else if(S.loc == trg)
- S.icon_state = initial(S.icon_state)
- S.icon = initial(S.icon)
- S.update_icon()
- break
- else
- S.icon_state = initial(S.icon_state)
- S.icon = initial(S.icon)
- S.update_icon()
+ add_logs(originaloccupant, M, "shot", "syringegun")
break
- sleep(1)
- do_after_cooldown()
- return 1
-
-
- Topic(href,href_list)
- ..()
- var/datum/topic_input/filter = new (href,href_list)
- if(filter.get("toggle_mode"))
- mode = !mode
- update_equip_info()
- return
- if(filter.get("select_reagents"))
- processed_reagents.len = 0
- var/m = 0
- var/message
- for(var/i=1 to known_reagents.len)
- if(m>=synth_speed)
+ else if(mechsyringe.loc == trg)
+ mechsyringe.icon_state = initial(mechsyringe.icon_state)
+ mechsyringe.icon = initial(mechsyringe.icon)
+ mechsyringe.update_icon()
break
- var/reagent = filter.get("reagent_[i]")
- if(reagent && (reagent in known_reagents))
- message = "[m ? ", " : null][known_reagents[reagent]]"
- processed_reagents += reagent
- m++
- if(processed_reagents.len)
- message += " added to production"
- synth.start()
- occupant_message(message)
- occupant_message("Reagent processing started.")
- log_message("Reagent processing started.")
- return
- if(filter.get("show_reagents"))
- chassis.occupant << browse(get_reagents_page(),"window=msyringegun")
- if(filter.get("purge_reagent"))
- var/reagent = filter.get("purge_reagent")
- if(reagent)
- reagents.del_reagent(reagent)
- return
- if(filter.get("purge_all"))
- reagents.clear_reagents()
- return
- return
-
- proc/get_reagents_page()
- var/output = {"
-
- Reagent Synthesizer
-
-
-
-
- Current reagents:
-
- [get_current_reagents()]
-
- Reagents production:
-
- [get_reagents_form()]
-
-
-
- "}
- return output
-
- proc/get_reagents_form()
- var/r_list = get_reagents_list()
- var/inputs
- if(r_list)
- inputs += ""
- inputs += ""
- inputs += ""
- var/output = {"
- [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null]
- "}
- return output
-
- 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
-
- proc/get_current_reagents()
- var/output
- for(var/datum/reagent/R in reagents.reagent_list)
- if(R.volume > 0)
- output += "[R]: [round(R.volume,0.001)] - Purge Reagent
"
- if(output)
- output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All"
- return output || "None"
-
- proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S)
- if(syringes.len= 2)
- occupant_message("The syringe is too far away.")
- return 0
- for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows)
- if(!(D.CanPass(S,src.loc)))
- occupant_message("Unable to load syringe.")
- return 0
- for(var/obj/machinery/door/D in S.loc)//Checks for doors
- if(!(D.CanPass(S,src.loc)))
- occupant_message("Unable to load syringe.")
- return 0
- S.reagents.trans_to(src, S.reagents.total_volume)
- S.forceMove(src)
- syringes += S
- occupant_message("Syringe loaded.")
- update_equip_info()
- return 1
- occupant_message("The [src] syringe chamber is full.")
- return 0
-
- proc/analyze_reagents(atom/A)
- if(get_dist(src,A) >= 4)
- occupant_message("The object is too far away.")
- return 0
- if(!A.reagents || istype(A,/mob))
- occupant_message("No reagent info gained from [A].")
- return 0
- occupant_message("Analyzing reagents...")
- for(var/datum/reagent/R in A.reagents.reagent_list)
- if(R.reagent_state == 2 && add_known_reagent(R.id,R.name))
- occupant_message("Reagent analyzed, identified as [R.name] and added to database.")
- send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form())
- occupant_message("Analyzis complete.")
- return 1
-
- proc/add_known_reagent(r_id,r_name)
- set_ready_state(0)
- do_after_cooldown()
- if(!(r_id in known_reagents))
- known_reagents += r_id
- known_reagents[r_id] = r_name
- return 1
- return 0
+ else
+ mechsyringe.icon_state = initial(mechsyringe.icon_state)
+ mechsyringe.icon = initial(mechsyringe.icon)
+ mechsyringe.update_icon()
+ break
+ sleep(1)
+ return 1
- 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
-
- on_reagent_change()
- ..()
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Topic(href,href_list)
+ ..()
+ var/datum/topic_input/filter = new (href,href_list)
+ if(filter.get("toggle_mode"))
+ mode = !mode
update_equip_info()
return
+ if(filter.get("select_reagents"))
+ processed_reagents.len = 0
+ var/m = 0
+ var/message
+ for(var/i=1 to known_reagents.len)
+ if(m>=synth_speed)
+ break
+ var/reagent = filter.get("reagent_[i]")
+ if(reagent && (reagent in known_reagents))
+ message = "[m ? ", " : null][known_reagents[reagent]]"
+ processed_reagents += reagent
+ m++
+ if(processed_reagents.len)
+ message += " added to production"
+ processing_objects.Add(src)
+ occupant_message(message)
+ occupant_message("Reagent processing started.")
+ log_message("Reagent processing started.")
+ return
+ if(filter.get("show_reagents"))
+ chassis.occupant << browse(get_reagents_page(),"window=msyringegun")
+ if(filter.get("purge_reagent"))
+ var/reagent = filter.get("purge_reagent")
+ if(reagent)
+ reagents.del_reagent(reagent)
+ return
+ if(filter.get("purge_all"))
+ reagents.clear_reagents()
+ return
+ return
-/datum/global_iterator/mech_synth
- delay = 100
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_page()
+ var/output = {"
+
+ Reagent Synthesizer
+
+
+
+
+ Current reagents:
+
+ [get_current_reagents()]
+
+ Reagents production:
+
+ [get_reagents_form()]
+
+
+
+ "}
+ return output
- 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)
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_form()
+ var/r_list = get_reagents_list()
+ var/inputs
+ if(r_list)
+ inputs += ""
+ inputs += ""
+ inputs += ""
+ var/output = {"
+ [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null]
+ "}
+ return output
+
+/obj/item/mecha_parts/mecha_equipment/medical/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/medical/syringe_gun/proc/get_current_reagents()
+ var/output
+ for(var/datum/reagent/R in reagents.reagent_list)
+ if(R.volume > 0)
+ output += "[R]: [round(R.volume,0.001)] - Purge Reagent
"
+ if(output)
+ output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All"
+ return output || "None"
+
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S)
+ if(syringes.len= 2)
+ occupant_message("The syringe is too far away.")
+ return 0
+ for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows)
+ if(!(D.CanPass(S,src.loc)))
+ occupant_message("Unable to load syringe.")
+ return 0
+ for(var/obj/machinery/door/D in S.loc)//Checks for doors
+ if(!(D.CanPass(S,src.loc)))
+ occupant_message("Unable to load syringe.")
+ return 0
+ S.reagents.trans_to(src, S.reagents.total_volume)
+ S.forceMove(src)
+ syringes += S
+ occupant_message("Syringe loaded.")
+ update_equip_info()
return 1
+ occupant_message("The [src] syringe chamber is full.")
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/analyze_reagents(atom/A)
+ if(get_dist(src,A) >= 4)
+ occupant_message("The object is too far away.")
+ return 0
+ if(!A.reagents || istype(A,/mob))
+ occupant_message("No reagent info gained from [A].")
+ return 0
+ occupant_message("Analyzing reagents...")
+ for(var/datum/reagent/R in A.reagents.reagent_list)
+ if(R.reagent_state == 2 && add_known_reagent(R.id,R.name))
+ occupant_message("Reagent analyzed, identified as [R.name] and added to database.")
+ send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form())
+ occupant_message("Analyzis complete.")
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/medical/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/medical/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/medical/syringe_gun/on_reagent_change()
+ ..()
+ update_equip_info()
+ return
+
+
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/process()
+ if(..())
+ 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.")
+ processing_objects.Remove(src)
+ return
+ 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..4f7211282c9
--- /dev/null
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -0,0 +1,136 @@
+// 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/space))
+ 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]...",
+ blind_message = "You hear drilling.")
+ if(do_after_cooldown(target))
+ if(isturf(target))
+ var/turf/T = target
+ T.drill_act(src)
+ 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)
+
+/turf/proc/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+ return
+
+/turf/simulated/floor/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+ ex_act(1)
+
+/turf/simulated/wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+ ex_act(2)
+
+/turf/simulated/wall/r_wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+ if(istype(drill, /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill))
+ if(drill.do_after_cooldown(src))//To slow down how fast mechs can drill through the station
+ drill.log_message("Drilled through [src]")
+ ex_act(3)
+ else
+ drill.occupant_message("[src] is too durable to drill through.")
+
+/turf/simulated/mineral/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+ for(var/turf/simulated/mineral/M in range(drill.chassis, 1))
+ if(get_dir(drill.chassis, M) & drill.chassis.dir)
+ M.gets_drilled()
+ drill.log_message("Drilled through [src]")
+ drill.move_ores()
+
+/turf/simulated/floor/plating/airless/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+ if(istype(drill, /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill))
+ for(var/turf/simulated/floor/plating/airless/asteroid/M in range(1, src))
+ M.gets_drilled()
+ else
+ for(var/turf/simulated/floor/plating/airless/asteroid/M in range(1, drill.chassis))
+ if(get_dir(drill.chassis, M) & drill.chassis.dir)
+ M.gets_drilled()
+ drill.log_message("Drilled through [src]")
+ drill.move_ores()
+
+/obj/item/mecha_parts/mecha_equipment/drill/proc/move_ores()
+ 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(1, chassis))
+ if(get_dir(chassis, ore) & chassis.dir)
+ ore.Move(ore_box)
+
+/obj/item/mecha_parts/mecha_equipment/drill/can_attach(obj/mecha/M)
+ 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", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
+ if(target.stat == DEAD && target.butcher_results)
+ target.harvest(chassis) // Butcher the mob with our drill.
+ 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=4"
+ 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"
+ selectable = 0
+ equip_cooldown = 30
+ var/scanning = 0
+
+/obj/item/mecha_parts/mecha_equipment/mining_scanner/New()
+ processing_objects.Add(src)
+
+/obj/item/mecha_parts/mecha_equipment/mining_scanner/process()
+ if(!loc)
+ processing_objects.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..e57ee9ba8a2
--- /dev/null
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -0,0 +1,494 @@
+// 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) || !is_teleport_allowed(loc.z))
+ 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) || !is_teleport_allowed(loc.z))
+ return
+ var/list/theareas = get_areas_in_range(100, chassis)
+ 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), target_turf)
+ P.icon = 'icons/obj/objects.dmi'
+ P.failchance = 0
+ P.icon_state = "anom"
+ P.name = "wormhole"
+ message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](?) (FLW) used a Wormhole Generator in ([loc.x],[loc.y],[loc.z] - JMP)",0,1)
+ log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([loc.x],[loc.y],[loc.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]",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]",get_equip_info())
+ return 1
+ else
+ locked = null
+ occupant_message("Lock on [locked] disengaged.")
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info())
+ if(2)
+ var/list/atoms = list()
+ if(isturf(target))
+ atoms = range(3, target)
+ else
+ atoms = orange(3, target)
+ 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]",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
+ selectable = 0
+
+/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
+ selectable = 0
+
+/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 = "Repair Droid"
+ desc = "Automated repair droid. Scans exosuit 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 = 1
+ var/icon/droid_overlay
+ var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH)
+ selectable = 0
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy()
+ processing_objects.Remove(src)
+ if(chassis)
+ chassis.overlays -= droid_overlay
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M)
+ ..()
+ droid_overlay = new(icon, icon_state = "repair_droid")
+ M.overlays += droid_overlay
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
+ chassis.overlays -= droid_overlay
+ processing_objects.Remove(src)
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info()
+ if(!chassis) return
+ return "* [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)
+ processing_objects.Add(src)
+ droid_overlay = new(icon, icon_state = "repair_droid_a")
+ log_message("Activated.")
+ set_ready_state(0)
+ else
+ processing_objects.Remove(src)
+ droid_overlay = new(icon, icon_state = "repair_droid")
+ log_message("Deactivated.")
+ set_ready_state(1)
+ chassis.overlays += droid_overlay
+ send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info())
+
+
+/obj/item/mecha_parts/mecha_equipment/repair_droid/process()
+ if(!chassis)
+ processing_objects.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))
+ processing_objects.Remove(src)
+ set_ready_state(1)
+ else //no repair needed, we turn off
+ processing_objects.Remove(src)
+ set_ready_state(1)
+ chassis.overlays -= droid_overlay
+ droid_overlay = new(icon, icon_state = "repair_droid")
+ chassis.overlays += droid_overlay
+
+/////////////////////////////////// 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=4;engineering=4"
+ energy_drain = 0
+ range = 0
+ var/coeff = 100
+ var/list/use_channels = list(EQUIP,ENVIRON,LIGHT)
+ selectable = 0
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach()
+ processing_objects.Remove(src)
+ ..()
+
+/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.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
+ processing_objects.Add(src)
+ set_ready_state(0)
+ log_message("Activated.")
+ else
+ processing_objects.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 "* [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)
+ processing_objects.Remove(src)
+ set_ready_state(1)
+ return
+ var/cur_charge = chassis.get_charge()
+ if(isnull(cur_charge) || !chassis.cell)
+ processing_objects.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.powered(c))
+ pow_chan = c
+ break
+ if(pow_chan)
+ var/delta = min(20, chassis.cell.maxcharge-cur_charge)
+ chassis.give_power(delta)
+ A.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=2"
+ range = MELEE
+ var/coeff = 100
+ var/fuel_type = MAT_PLASMA
+ var/max_fuel = 150000
+ var/fuel_name = "plasma" // Our fuel name as a string
+ var/fuel_amount = 0
+ var/fuel_per_cycle_idle = 10
+ var/fuel_per_cycle_active = 100
+ var/power_per_cycle = 30
+
+/obj/item/mecha_parts/mecha_equipment/generator/New()
+ ..()
+ generator_init()
+
+/obj/item/mecha_parts/mecha_equipment/generator/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/generator/proc/generator_init()
+ fuel_amount = 0
+
+/obj/item/mecha_parts/mecha_equipment/generator/detach()
+ processing_objects.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)
+ processing_objects.Add(src)
+ log_message("Activated.")
+ else
+ set_ready_state(1)
+ processing_objects.Remove(src)
+ log_message("Deactivated.")
+
+/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
+ var/output = ..()
+ if(output)
+ return "[output] \[[fuel_name]: [round(fuel_amount,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]",get_equip_info())
+
+/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/I)
+ if(istype(I) && (fuel_type in I.materials))
+ if(istype(I, /obj/item/stack/sheet))
+ var/obj/item/stack/sheet/P = I
+ var/to_load = max(max_fuel - P.amount*P.perunit,0)
+ if(to_load)
+ var/units = min(max(round(to_load / P.perunit),1),P.amount)
+ if(units)
+ var/added_fuel = units * P.perunit
+ fuel_amount += added_fuel
+ P.use(units)
+ occupant_message("[units] unit\s of [fuel_name] successfully loaded.")
+ return added_fuel
+ else
+ occupant_message("Unit is full.")
+ return 0
+ else // Some other object containing our fuel's type, so we just eat it (ores mainly)
+ var/to_load = max(min(I.materials[fuel_type], max_fuel - fuel_amount),0)
+ if(to_load == 0)
+ return 0
+ fuel_amount += to_load
+ qdel(I)
+ return to_load
+
+ else if(istype(I, /obj/structure/ore_box))
+ var/fuel_added = 0
+ for(var/baz in I.contents)
+ var/obj/item/O = baz
+ if(fuel_type in O.materials)
+ fuel_added = load_fuel(O)
+ break
+ return fuel_added
+
+ else
+ occupant_message("[fuel_name] traces in target minimal! [I] 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(!istype(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("[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("[src] suddenly disgorges a cloud of plasma.")
+ T.assume_air(GM)
+
+/obj/item/mecha_parts/mecha_equipment/generator/process()
+ if(!chassis)
+ processing_objects.Remove(src)
+ set_ready_state(1)
+ return
+ if(fuel_amount<=0)
+ processing_objects.Remove(src)
+ log_message("Deactivated - no fuel.")
+ set_ready_state(1)
+ return
+ var/cur_charge = chassis.get_charge()
+ if(isnull(cur_charge))
+ set_ready_state(1)
+ occupant_message("No powercell detected.")
+ log_message("Deactivated.")
+ processing_objects.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_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=4;engineering=4"
+ fuel_name = "uranium" // Our fuel name as a string
+ fuel_type = MAT_URANIUM
+ max_fuel = 50000
+ fuel_per_cycle_idle = 10
+ fuel_per_cycle_active = 30
+ power_per_cycle = 50
+ var/rad_per_cycle = 0.3
+
+/obj/item/mecha_parts/mecha_equipment/generator/nuclear/generator_init()
+ 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))
+ M.apply_effect((rad_per_cycle * 3),IRRADIATE,0)
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
deleted file mode 100644
index d945e1cbb7f..00000000000
--- a/code/game/mecha/equipment/tools/tools.dm
+++ /dev/null
@@ -1,1147 +0,0 @@
-/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp
- name = "Hydraulic Clamp"
- icon_state = "mecha_clamp"
- equip_cooldown = 15
- energy_drain = 10
- var/dam_force = 20
- var/obj/mecha/working/ripley/cargo_holder
-
- can_attach(obj/mecha/working/ripley/M as obj)
- if(..())
- if(istype(M))
- return 1
- return 0
-
- attach(obj/mecha/M as obj)
- ..()
- cargo_holder = M
- return
-
- action(atom/target)
- if(!action_checks(target)) return
- if(!cargo_holder) return
- if(istype(target, /obj/structure/stool)) return
-
- if(istype(target,/obj))
- var/obj/O = target
- if(!O.anchored)
- if(cargo_holder.cargo.len < cargo_holder.cargo_capacity)
- occupant_message("You lift [target] and start to load it into cargo compartment.")
- chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- O.anchored = 1
- var/T = chassis.loc
- if(do_after_cooldown(target))
- if(T == chassis.loc && src == chassis.selected)
- cargo_holder.cargo += O
- O.loc = chassis
- O.anchored = 0
- occupant_message("[target] succesfully loaded.")
- log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
- else
- occupant_message("You must hold still while handling objects.")
- O.anchored = initial(O.anchored)
- 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 == I_HARM)
- M.take_overall_damage(dam_force)
- M.adjustOxyLoss(round(dam_force/2))
- M.updatehealth()
- occupant_message("\red You squeeze [target] with [src.name]. Something cracks.")
- chassis.visible_message("\red [chassis] squeezes [target].")
- else
- step_away(M,chassis)
- occupant_message("You push [target] out of the way.")
- chassis.visible_message("[chassis] pushes [target] out of the way.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/drill
- name = "Drill"
- desc = "This is the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)"
- icon_state = "mecha_drill"
- equip_cooldown = 30
- energy_drain = 10
- force = 15
-
- action(atom/target)
- if(!action_checks(target)) return
- if(isobj(target))
- var/obj/target_obj = target
- if(!target_obj.vars.Find("unacidable") || target_obj.unacidable) return
- set_ready_state(0)
- chassis.use_power(energy_drain)
- chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.")
- occupant_message("You start to drill [target]")
- var/T = chassis.loc
- var/C = target.loc //why are these backwards? we may never know -Pete
- if(do_after_cooldown(target))
- if(T == chassis.loc && src == chassis.selected)
- if(istype(target, /turf/simulated/wall/r_wall))
- 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()
- 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/airless/asteroid))
- for(var/turf/simulated/floor/plating/airless/asteroid/M in range(chassis,1))
- if(get_dir(chassis,M)&chassis.dir)
- M.gets_drilled()
- 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)
- if(istype(target, /mob/living))
- var/mob/living/M = target
- M.attack_log +="\[[time_stamp()]\] Mech Drilled by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]"
- chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Drilled [M.name] ([M.ckey]) with [src.name]"
- log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech drilled [M.name] ([M.ckey]) with [src.name]" )
- if(!iscarbon(chassis.occupant))
- M.LAssailant = null
- else
- M.LAssailant = chassis.occupant
- log_message("Drilled through [target]")
- target.ex_act(2)
- return 1
-
- 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/diamonddrill
- name = "Diamond Drill"
- desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)"
- icon_state = "mecha_diamond_drill"
- origin_tech = "materials=4;engineering=3"
- equip_cooldown = 20
- force = 15
-
- action(atom/target)
- if(!action_checks(target)) return
- if(isobj(target))
- var/obj/target_obj = target
- if(target_obj.unacidable) return
- set_ready_state(0)
- chassis.use_power(energy_drain)
- chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.")
- occupant_message("You start to drill [target]")
- var/T = chassis.loc
- var/C = target.loc //why are these backwards? we may never know -Pete
- if(do_after_cooldown(target))
- if(T == chassis.loc && src == chassis.selected)
- if(istype(target, /turf/simulated/wall/r_wall))
- 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 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()
- 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/airless/asteroid))
- for(var/turf/simulated/floor/plating/airless/asteroid/M in range(target,1))
- M.gets_drilled()
- 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(target,1))
- ore.Move(ore_box)
- else if(target.loc == C)
- if(istype(target, /mob/living))
- var/mob/living/M = target
- M.attack_log +="\[[time_stamp()]\] Mech Drilled by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]"
- chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Drilled [M.name] ([M.ckey]) with [src.name]"
- log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech drilled [M.name] ([M.ckey]) with [src.name]" )
- if(!iscarbon(chassis.occupant))
- M.LAssailant = null
- else
- M.LAssailant = chassis.occupant
- log_message("Drilled through [target]")
- target.ex_act(2)
- return 1
-
- 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/extinguisher
- name = "Extinguisher"
- desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)"
- icon_state = "mecha_exting"
- equip_cooldown = 5
- energy_drain = 0
- range = MELEE|RANGED
-
- New()
- reagents = new/datum/reagents(1000)
- reagents.my_atom = src
- reagents.add_reagent("water", 1000)
- ..()
- return
-
- 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("\blue 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 = new /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
-
- get_equip_info()
- return "[..()] \[[src.reagents.total_volume]\]"
-
- on_reagent_change()
- return
-
- 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. (Can be attached to: Any exosuit)"
- 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/canRwall = 0
-
- New()
- rcd_list += src
- ..()
-
- Destroy()
- rcd_list -= src
- return ..()
-
- action(atom/target)
- if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve
- return
- if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock))
- target = get_turf(target)
- if(!action_checks(target) || 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))
- if(istype(target, /turf/simulated/wall/r_wall) && !canRwall)
- return 0
- occupant_message("Deconstructing [target]...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- chassis.spark_system.start()
- target:ChangeTurf(/turf/simulated/floor/plating)
- playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.use_power(energy_drain)
- else if(istype(target, /turf/simulated/floor))
- occupant_message("Deconstructing [target]...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- chassis.spark_system.start()
- target:ChangeTurf(/turf/space)
- playsound(target, '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))
- 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))
- occupant_message("Building Floor...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- target:ChangeTurf(/turf/simulated/floor/plating)
- playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
- chassis.spark_system.start()
- chassis.use_power(energy_drain*2)
- else if(istype(target, /turf/simulated/floor))
- occupant_message("Building Wall...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- target:ChangeTurf(/turf/simulated/wall)
- playsound(target, '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))
- 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
-
-
- 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
-
- get_equip_info()
- return "[..()] \[D|C|A\]"
-
-
-
-
-/obj/item/mecha_parts/mecha_equipment/teleporter
- name = "Teleporter"
- desc = "An exosuit module that allows exosuits to teleport to any position in view."
- icon_state = "mecha_teleport"
- origin_tech = "bluespace=10"
- equip_cooldown = 150
- energy_drain = 1000
- range = RANGED
-
- action(atom/target)
- if(!action_checks(target) || !is_teleport_allowed(src.loc.z)) return
- var/turf/T = get_turf(target)
- if(T)
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_teleport(chassis, T, 4)
- do_after_cooldown()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/wormhole_generator
- name = "Wormhole Generator"
- desc = "An exosuit module that allows generating of small quasi-stable wormholes."
- icon_state = "mecha_wholegen"
- origin_tech = "bluespace=3"
- equip_cooldown = 50
- energy_drain = 300
- range = RANGED
-
-
- action(atom/target)
- if(!action_checks(target) || !is_teleport_allowed(src.loc.z)) 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), target_turf)
- P.icon = 'icons/obj/objects.dmi'
- P.failchance = 0
- P.icon_state = "anom"
- P.name = "wormhole"
- message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](?) (FLW) used a Wormhole Generator in ([loc.x],[loc.y],[loc.z] - JMP)",0,1)
- log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([loc.x],[loc.y],[loc.z])")
- do_after_cooldown()
- src = null
- spawn(rand(150,300))
- qdel(P)
- return
-
-/obj/item/mecha_parts/mecha_equipment/gravcatapult
- name = "Gravitational Catapult"
- desc = "An exosuit mounted Gravitational Catapult."
- icon_state = "mecha_teleport"
- origin_tech = "bluespace=2;magnets=3"
- equip_cooldown = 10
- energy_drain = 100
- range = MELEE|RANGED
- var/atom/movable/locked
- var/mode = 1 //1 - gravsling 2 - gravpush
-
-
- 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, chassis)
- locked = null
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- else
- locked = null
- occupant_message("Lock on [locked] disengaged.")
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- if(2)
- if(!action_checks(target)) return
- var/list/atoms = list()
- if(isturf(target))
- atoms = range(target,3)
- else
- atoms = orange(target,3)
- for(var/atom/movable/A in atoms)
- if(A.anchored) continue
- spawn(0)
- var/iter = 5-get_dist(A,target)
- for(var/i=0 to iter)
- step_away(A,target)
- sleep(2)
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return
-
- get_equip_info()
- return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]"
-
- 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
-
- can_attach(obj/mecha/M as obj)
- if(..())
- if(!istype(M, /obj/mecha/combat/honker))
- if(!M.proc_res["dynattackby"])
- return 1
- return 0
-
- attach(obj/mecha/M as obj)
- ..()
- chassis.proc_res["dynattackby"] = src
- return
-
- detach()
- chassis.proc_res["dynattackby"] = null
- ..()
- return
-
- get_equip_info()
- if(!chassis) return
- return "* [src.name]"
-
- proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(!action_checks(user))
- return chassis.dynattackby(W,user, params)
- chassis.log_message("Attacked by [W]. Attacker - [user]")
- if(prob(chassis.deflect_chance*deflect_coeff))
- to_chat(user, "\red 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
-
- 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
-
- attach(obj/mecha/M as obj)
- ..()
- chassis.proc_res["dynbulletdamage"] = src
- chassis.proc_res["dynhitby"] = src
- return
-
- detach()
- chassis.proc_res["dynbulletdamage"] = null
- chassis.proc_res["dynhitby"] = null
- ..()
- return
-
- get_equip_info()
- if(!chassis) return
- return "* [src.name]"
-
- proc/dynbulletdamage(var/obj/item/projectile/Proj)
- if(!action_checks(src))
- return chassis.dynbulletdamage(Proj)
- if(prob(chassis.deflect_chance*deflect_coeff))
- chassis.occupant_message("\blue The armor deflects incoming projectile.")
- chassis.visible_message("The [chassis.name] armor deflects the projectile")
- chassis.log_append_to_last("Armor saved.")
- else
- chassis.take_damage(round(Proj.damage*src.damage_coeff),Proj.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
-
- proc/dynhitby(atom/movable/A)
- if(!action_checks(A))
- return chassis.dynhitby(A)
- if(prob(chassis.deflect_chance*deflect_coeff) || istype(A, /mob/living) || istype(A, /obj/item/mecha_parts/mecha_tracking))
- chassis.occupant_message("\blue The [A] bounces off the armor.")
- chassis.visible_message("The [A] bounces off the [chassis] armor")
- chassis.log_append_to_last("Armor saved.")
- if(istype(A, /mob/living))
- var/mob/living/M = A
- M.take_organ_damage(10)
- else if(istype(A, /obj))
- var/obj/O = A
- if(O.throwforce)
- chassis.take_damage(round(O.throwforce*damage_coeff))
- chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/repair_droid
- name = "Repair Droid"
- desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost 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)
-
- New()
- ..()
- pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0)
- pr_repair_droid.set_delay(equip_cooldown)
- return
-
- attach(obj/mecha/M as obj)
- ..()
- droid_overlay = new(src.icon, icon_state = "repair_droid")
- M.overlays += droid_overlay
- return
-
- Destroy()
- chassis.overlays -= droid_overlay
- return ..()
-
- detach()
- chassis.overlays -= droid_overlay
- pr_repair_droid.stop()
- ..()
- return
-
- get_equip_info()
- if(!chassis) return
- return "* [src.name] - [pr_repair_droid.active()?"Dea":"A"]ctivate"
-
-
- 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
-
- process(var/obj/item/mecha_parts/mecha_equipment/repair_droid/RD as obj)
- if(!RD.chassis)
- stop()
- RD.set_ready_state(1)
- return
- var/health_boost = RD.health_boost
- var/repaired = 0
- if(RD.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
- health_boost *= -2
- else if(RD.chassis.hasInternalDamage() && prob(15))
- for(var/int_dam_flag in RD.repairable_damage)
- if(RD.chassis.hasInternalDamage(int_dam_flag))
- RD.chassis.clearInternalDamage(int_dam_flag)
- repaired = 1
- break
- if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health))
- RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health)
- repaired = 1
- if(repaired)
- if(RD.chassis.use_power(RD.energy_drain))
- RD.set_ready_state(0)
- else
- stop()
- RD.set_ready_state(1)
- return
- else
- RD.set_ready_state(1)
- return
-
-
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
- name = "Energy Relay"
- desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low."
- icon_state = "tesla"
- origin_tech = "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)
-
- New()
- ..()
- pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0)
- pr_energy_relay.set_delay(equip_cooldown)
- return
-
- detach()
- pr_energy_relay.stop()
-// chassis.proc_res["dynusepower"] = null
- chassis.proc_res["dyngetcharge"] = null
- ..()
- return
-
- attach(obj/mecha/M)
- ..()
- chassis.proc_res["dyngetcharge"] = src
-// chassis.proc_res["dynusepower"] = src
- return
-
- can_attach(obj/mecha/M)
- if(..())
- if(!M.proc_res["dyngetcharge"])// && !M.proc_res["dynusepower"])
- return 1
- return 0
-
- 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
-
- proc/get_power_channel(var/area/A)
- var/pow_chan
- if(A)
- for(var/c in use_channels)
- if(A.powered(c))
- pow_chan = c
- break
- return pow_chan
-
- 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
-
- get_equip_info()
- if(!chassis) return
- return "* [src.name] - [pr_energy_relay.active()?"Dea":"A"]ctivate"
-
-/* proc/dynusepower(amount)
- if(!equip_ready) //enabled
- var/area/A = get_area(chassis)
- var/pow_chan = get_power_channel(A)
- if(pow_chan)
- A.master.use_power(amount*coeff, pow_chan)
- return 1
- return chassis.dynusepower(amount)*/
-
-/datum/global_iterator/mecha_energy_relay
-
- 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
-
- action(target)
- if(chassis)
- var/result = load_fuel(target)
- var/message
- if(isnull(result))
- message = "[fuel_name] traces in target minimal. [target] cannot be used as fuel."
- else if(!result)
- message = "Unit is full."
- else
- message = "[result] unit\s of [fuel_name] successfully loaded."
- send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
- occupant_message(message)
- return
-
- proc/load_fuel(var/obj/item/I)
- if(istype(I) && (fuel_type in I.materials))
- if(istype(I, /obj/item/stack/sheet))
- var/obj/item/stack/sheet/P = I
- var/to_load = max(max_fuel - P.amount*P.perunit,0)
- if(to_load)
- var/units = min(max(round(to_load / P.perunit),1),P.amount)
- if(units)
- var/added_fuel = units * P.perunit
- fuel_amount += added_fuel
- P.use(units)
- return added_fuel
- else
- return 0
- else // Some other object containing our fuel's type, so we just eat it (ores mainly)
- var/to_load = max(min(I.materials[fuel_type], max_fuel - fuel_amount),0)
- if(to_load == 0)
- return 0
- fuel_amount += to_load
- qdel(I)
- return to_load
- else if(istype(I, /obj/structure/ore_box))
- var/fuel_added = 0
- for(var/baz in I.contents) // Istypeless loop
- var/obj/item/O = baz
- if(fuel_type in O.materials)
- fuel_added = load_fuel(O)
- break
- return fuel_added
- return
-
- attackby(weapon,mob/user, params)
- var/result = load_fuel(weapon)
- var/weapon_name = "[weapon]"
- if(isnull(result))
- user.visible_message("[user] tries to shove [weapon_name] into [src], but \the [src] rejects it.","[fuel_name] traces in target minimal. [weapon_name] cannot be used as fuel.")
- else if(!result)
- to_chat(user, "Unit is full.")
- else
- user.visible_message("[user] loads [src] with \the [weapon_name].","[result] unit\s of [fuel_name] successfully loaded.")
- return
-
- 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.temperature : T20C
- T.visible_message("The [src] suddenly disgorges a cloud of plasma.")
- T.assume_air(GM)
- return
-
-/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] succesfully loaded.")
- chassis.log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
- else
- chassis.occupant_message("You must hold still while handling objects.")
- O.anchored = initial(O.anchored)
- else
- chassis.occupant_message("Not enough room in cargo compartment.")
- else
- chassis.occupant_message("[target] is firmly secured.")
-
- else if(istype(target,/mob/living))
- var/mob/living/M = target
- if(M.stat>1) return
- if(chassis.occupant.a_intent == I_HARM)
- chassis.occupant_message("\red You obliterate [target] with [src.name], leaving blood and guts everywhere.")
- chassis.visible_message("\red [chassis] destroys [target] in an unholy fury.")
- if(chassis.occupant.a_intent == I_DISARM)
- chassis.occupant_message("\red You tear [target]'s limbs off with [src.name].")
- chassis.visible_message("\red [chassis] rips [target]'s arms off.")
- else
- step_away(M,chassis)
- chassis.occupant_message("You smash into [target], sending them flying.")
- chassis.visible_message("[chassis] tosses [target] like a piece of paper.")
- set_ready_state(0)
- chassis.use_power(energy_drain)
- do_after_cooldown()
- return 1
-
-/obj/item/mecha_parts/mecha_equipment/tool/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()
- processing_objects.Add(src)
-
-/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/process()
- if(!loc)
- processing_objects.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/mimercd
- name = "Mounted MRCD"
- desc = "An exosuit-mounted Mime Rapid Construction Device. (Can be attached to: Recitence)"
- icon_state = "mecha_rcd"
- origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4"
- equip_cooldown = 10
- energy_drain = 250
- range = MELEE|RANGED
-
-/obj/item/mecha_parts/mecha_equipment/tool/mimercd/can_attach(obj/mecha/combat/recitence/M as obj)
- if(..())
- if(istype(M))
- return 1
- return 0
-
-/obj/item/mecha_parts/mecha_equipment/tool/mimercd/action(atom/target)
- if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve
- return
- if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock))
- target = get_turf(target)
- if(!action_checks(target) || get_dist(chassis, target)>3)
- return
-
- if(istype(target, /turf/simulated/floor))
- occupant_message("Building Wall...")
- set_ready_state(0)
- if(do_after_cooldown(target))
- new /obj/structure/barricade/mime/mrcd(target)
- chassis.spark_system.start()
- chassis.use_power(energy_drain*2)
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..4ff69a0d34e
--- /dev/null
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -0,0 +1,452 @@
+//Hydraulic clamp, Kill clamp, Extinguisher, RCD, Mime 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)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/attach(obj/mecha/M)
+ ..()
+ 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 == I_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", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])")
+ start_cooldown()
+ 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 == I_HARM)
+ target.visible_message("[chassis] destroys [target] in an unholy fury.",
+ "[chassis] destroys [target] in an unholy fury.")
+ M.gib()
+ /*if(chassis.occupant.a_intent == I_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 = new /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)
+ 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. (Can be attached to: Any exosuit)"
+ 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/canRwall = 0
+
+/obj/item/mecha_parts/mecha_equipment/rcd/New()
+ rcd_list += src
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/rcd/Destroy()
+ rcd_list -= src
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target)
+ if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve
+ return
+
+ if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock))
+ target = get_turf(target)
+
+ if(!action_checks(target) || get_dist(chassis, target)>3)
+ return
+ playsound(chassis, 'sound/machines/click.ogg', 50, 1)
+
+ switch(mode)
+ if(0)
+ if(istype(target, /turf/simulated/wall))
+ if(istype(target, /turf/simulated/wall/r_wall) && !canRwall)
+ return 0
+ var/turf/simulated/wall/W = target
+ occupant_message("Deconstructing [target]...")
+ 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 [target]...")
+ if(do_after_cooldown(F))
+ chassis.spark_system.start()
+ F.ChangeTurf(/turf/space)
+ F.air_update_turf()
+ 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))
+ 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/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.")
+
+/obj/item/mecha_parts/mecha_equipment/rcd/get_equip_info()
+ return "[..()] \[D|C|A\]"
+
+
+/obj/item/mecha_parts/mecha_equipment/mimercd
+ name = "mounted MRCD"
+ desc = "An exosuit-mounted Mime Rapid Construction Device. (Can be attached to: Recitence)"
+ icon_state = "mecha_rcd"
+ origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4"
+ equip_cooldown = 10
+ energy_drain = 250
+ range = MELEE|RANGED
+
+/obj/item/mecha_parts/mecha_equipment/mimercd/can_attach(obj/mecha/combat/recitence/M)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/mimercd/action(atom/target)
+ if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve
+ return
+ if(!istype(target, /turf))
+ target = get_turf(target)
+ if(!action_checks(target) || get_dist(chassis, target)>3)
+ return
+
+ if(istype(target, /turf/simulated/floor))
+ occupant_message("Building Wall...")
+ if(do_after_cooldown(target))
+ new /obj/structure/barricade/mime/mrcd(target)
+ chassis.spark_system.start()
+
+
+
+/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)
+ return ..()
+
+/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/mecha.dm b/code/game/mecha/mecha.dm
index c425ec0edef..69189e51456 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -58,10 +58,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
@@ -70,7 +66,9 @@
var/datum/events/events
var/turf/crashing = null
- var/stepsound = 'sound/mecha/mechturn.ogg'
+
+ var/stepsound = 'sound/mecha/mechstep.ogg'
+ var/turnsound = 'sound/mecha/mechturn.ogg'
var/melee_cooldown = 10
var/melee_can_hit = 1
@@ -83,16 +81,18 @@
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)
+
spark_system.set_up(2, 0, src)
spark_system.attach(src)
add_cell()
- add_iterators()
+
+ processing_objects.Add(src)
removeVerb(/obj/mecha/verb/disconnect_from_port)
- log_message("[src.name] created.")
- loc.Entered(src)
+ log_message("[src] created.")
mechas_list += src //global mech list
prepare_huds()
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
@@ -100,7 +100,6 @@
diag_hud_set_mechhealth()
diag_hud_set_mechcell()
diag_hud_set_mechstat()
- return
////////////////////////
////// Helpers /////////
@@ -140,29 +139,6 @@
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/mecha_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, iMaintenance protocols in effect.")
@@ -230,28 +180,30 @@
return
if(src == target)
return
- var/dir_to_target = get_dir(src,target)
- if(dir_to_target && !(dir_to_target & src.dir))//wrong direction
+
+ var/dir_to_target = get_dir(src, target)
+ if(dir_to_target && !(dir_to_target & dir))//wrong direction
return
+
if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
target = safepick(view(3,target))
if(!target)
return
+
if(!target.Adjacent(src))
if(selected && selected.is_ranged())
selected.action(target, params)
else if(selected && selected.is_melee())
selected.action(target, params)
else
- if(internal_damage&MECHA_INT_CONTROL_LOST)
- target = safepick(oview(1,src))
- if(!melee_can_hit || !istype(target, /atom))
+ if(internal_damage & MECHA_INT_CONTROL_LOST)
+ target = safepick(oview(1, src))
+ if(!melee_can_hit || !isatom(target))
return
target.mech_melee_attack(src)
melee_can_hit = 0
- if(mecha_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)
@@ -293,54 +245,65 @@
events.fireEvent("onMove",get_turf(src))
/obj/mecha/Process_Spacemove(var/movement_dir = 0)
- if(occupant)
- return occupant.Process_Spacemove(movement_dir) //We'll just say you used the clamp to grab the wall
- return ..()
+ . = ..()
+ if(.)
+ return 1
-/obj/mecha/relaymove(mob/user,direction)
- if(user != src.occupant) //While not "realistic", this piece is player friendly.
+ var/atom/movable/backup = get_spacemove_backup()
+ if(backup)
+ if(istype(backup) && movement_dir && !backup.anchored)
+ if(backup.newtonian_move(turn(movement_dir, 180)))
+ if(occupant)
+ to_chat(occupant, "You push off of [backup] to propel yourself.")
+ return 1
+
+/obj/mecha/relaymove(mob/user, direction)
+ if(!direction)
+ return
+ if(user != occupant) //While not "realistic", this piece is player friendly.
user.forceMove(get_turf(src))
- to_chat(user, "You climb out from [src]")
+ to_chat(user, "You climb out from [src].")
return 0
if(connected_port)
if(world.time - last_message > 20)
- src.occupant_message("Unable to move while connected to the air system port")
+ occupant_message("Unable to move while connected to the air system port!")
last_message = world.time
return 0
if(state)
- occupant_message("Maintenance protocols in effect")
+ occupant_message("Maintenance protocols in effect.")
return
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))
return 0
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)
+ else if(dir != direction)
move_result = mechturn(direction)
else
move_result = mechstep(direction)
+
+ can_move = 0
+ spawn(step_in)
+ can_move = 1
+
if(move_result)
- can_move = 0
use_power(step_energy_drain)
- if(mecha_do_after(step_in))
- can_move = 1
return 1
return 0
+
/obj/mecha/proc/mechturn(direction)
dir = direction
- if(stepsound)
- playsound(src,stepsound,40,1)
+ if(turnsound)
+ playsound(src,turnsound,40,1)
return 1
/obj/mecha/proc/mechstep(direction)
@@ -354,12 +317,13 @@
if(result && stepsound)
playsound(src,stepsound,40,1)
return result
+
+
-/obj/mecha/Bump(var/atom/obstacle)
-// src.inertia_dir = null
- if(src.throwing)//high velocity mechas in your face!
+/obj/mecha/Bump(var/atom/obstacle, bump_allowed)
+ if(throwing) //high velocity mechas in your face!
var/breakthrough = 0
- if(istype(obstacle, /obj/structure/window/))
+ if(istype(obstacle, /obj/structure/window))
qdel(obstacle)
breakthrough = 1
@@ -385,7 +349,7 @@
else if(istype(obstacle, /obj/structure/reagent_dispensers/fueltank))
obstacle.ex_act(1)
- else if(istype(obstacle, /mob/living))
+ else if(isliving(obstacle))
var/mob/living/L = obstacle
var/hit_sound = list('sound/weapons/genhit1.ogg','sound/weapons/genhit2.ogg','sound/weapons/genhit3.ogg')
if(L.flags & GODMODE)
@@ -400,34 +364,34 @@
breakthrough = 1
else
- src.throwing = 0//so mechas don't get stuck when landing after being sent by a Mass Driver
- src.crashing = null
+ throwing = 0 //so mechas don't get stuck when landing after being sent by a Mass Driver
+ crashing = null
if(breakthrough)
if(crashing)
spawn(1)
- src.throw_at(crashing, 50, src.throw_speed)
+ throw_at(crashing, 50, throw_speed)
else
spawn(1)
crashing = get_distant_turf(get_turf(src), dir, 3)//don't use get_dir(src, obstacle) or the mech will stop if he bumps into a one-direction window on his tile.
- src.throw_at(crashing, 50, src.throw_speed)
+ throw_at(crashing, 50, throw_speed)
- if(istype(obstacle, /obj))
- var/obj/O = obstacle
- if(istype(O, /obj/effect/portal)) //derpfix
- src.anchored = 0
- O.Bumped(src)
- spawn(0)//countering portal teleport spawn(0), hurr
- src.anchored = 1
- else if(!O.anchored)
- step(obstacle,src.dir)
- else //I have no idea why I disabled this
- obstacle.Bumped(src)
- else if(istype(obstacle, /mob))
- step(obstacle,src.dir)
else
- obstacle.Bumped(src)
- return
+ if(bump_allowed)
+ if(..())
+ return
+ if(isobj(obstacle))
+ var/obj/O = obstacle
+ if(istype(O, /obj/effect/portal)) //derpfix
+ anchored = 0
+ O.Bumped(src)
+ spawn(0) //countering portal teleport spawn(0), hurr
+ anchored = 1
+ else if(!O.anchored)
+ step(obstacle, dir)
+ else if(ismob(obstacle))
+ step(obstacle, dir)
+
///////////////////////////////////
//////// Internal damage ////////
@@ -436,7 +400,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.")
- pr_int_temp_processor.start()
+ occupant_message("Life support system reactivated.")
if(MECHA_INT_FIRE)
- occupant_message("Internal fire extinquished.")
+ occupant_message("Internal fire extinquished.")
if(MECHA_INT_TANK_BREACH)
- occupant_message("Damaged internal tank has been sealed.")
+ occupant_message("Damaged internal tank has been sealed.")
diag_hud_set_mechstat()
- return
////////////////////////////////////////
@@ -496,8 +456,8 @@
/obj/mecha/proc/update_health()
- if(src.health > 0)
- src.spark_system.start()
+ if(health > 0)
+ spark_system.start()
diag_hud_set_mechhealth()
else
qdel(src)
@@ -506,108 +466,109 @@
/obj/mecha/attack_hand(mob/living/user as mob)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
- src.log_message("Attack by hand/paw. Attacker - [user].",1)
+ log_message("Attack by hand/paw. Attacker - [user].",1)
-
- if((HULK in user.mutations) && !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))
- user.visible_message("[user] hits [src.name], doing some damage.", "You hit [src.name] with all your might. The metal creaks and bends.")
+ if((HULK in user.mutations) && !prob(deflect_chance))
+ 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 [name], doing some damage.",
+ "You hit [name] with all your might. The metal creaks and bends.")
else
- user.visible_message("[user] hits [src.name]. Nothing happens","You hit [src.name] with no visible effect.")
- src.log_append_to_last("Armor saved.")
+ user.visible_message("[user] hits [name]. Nothing happens","You hit [name] with no visible effect.")
+ log_append_to_last("Armor saved.")
return
/obj/mecha/attack_alien(mob/living/user as mob)
- src.log_message("Attack by alien. Attacker - [user].",1)
+ log_message("Attack by alien. Attacker - [user].",1)
user.changeNext_move(CLICK_CD_MELEE)
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)
+ if(!prob(deflect_chance))
+ take_damage(15)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "\red You slash at the armored suit!")
- visible_message("\red The [user] slashes at [src.name]'s armor!")
+ visible_message("\red The [user] slashes at [name]'s armor!")
else
- src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ log_append_to_last("Armor saved.")
+ playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "\green Your claws had no effect!")
- src.occupant_message("\blue The [user]'s claws are stopped by the armor.")
- visible_message("\blue The [user] rebounds off [src.name]'s armor!")
+ occupant_message("\blue The [user]'s claws are stopped by the armor.")
+ visible_message("\blue The [user] rebounds off [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)
+ log_message("Attack by simple animal. Attacker - [user].",1)
if(user.melee_damage_upper == 0)
user.custom_emote(1, "[user.friendly] [src]")
else
user.do_attack_animation(src)
- if(!prob(src.deflect_chance))
+ if(!prob(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))
+ 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]!")
user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
else
- src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1)
- src.occupant_message("\blue The [user]'s attack is stopped by the armor.")
- visible_message("\blue The [user] rebounds off [src.name]'s armor!")
- user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
+ log_append_to_last("Armor saved.")
+ playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1)
+ occupant_message("\blue The [user]'s attack is stopped by the armor.")
+ visible_message("\blue The [user] rebounds off [name]'s armor!")
+ user.attack_log += text("\[[time_stamp()]\] attacked [name]")
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
+ log_message("Hit by [A].",1)
-/obj/mecha/proc/dynhitby(atom/movable/A)
+ var/def_coeff = 1
+ 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())
+ def_coeff = B.deflect_coeff
+ dam_coeff = B.damage_coeff
+ counter_tracking = 1
+ break
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.occupant_message("\blue The [A] bounces off the armor.")
- src.visible_message("The [A] bounces off the [src.name] armor")
- src.log_append_to_last("Armor saved.")
- if(istype(A, /mob/living))
+ if(!counter_tracking)
+ A.forceMove(src)
+ visible_message("The [A] fastens firmly to [src].")
+ return
+
+ if(prob(deflect_chance * def_coeff) || ismob(A))
+ occupant_message("[A] bounces off the armor.")
+ visible_message("[A] bounces off the [src]\s armor!")
+ log_append_to_last("Armor saved.")
+ if(isliving(A))
var/mob/living/M = A
- M.take_organ_damage(10)
- else if(istype(A, /obj))
+ M.take_organ_damage(10)
+
+ if(isobj(A))
var/obj/O = A
if(O.throwforce)
- src.take_damage(O.throwforce)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- return
+ take_damage(O.throwforce * dam_coeff)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
/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
+ log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1)
-/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj)
- if(prob(src.deflect_chance))
- src.occupant_message("\blue The armor deflects incoming projectile.")
- 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)
+ var/deflection = 1
+ 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(deflect_chance & deflection) && (Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ visible_message("[src] is hit by [Proj].")
+ take_damage(Proj.damage * dam_coeff, Proj.flag)
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT))
Proj.on_hit(src)
- return
+
/obj/mecha/Destroy()
go_out()
@@ -615,19 +576,11 @@
if(isAI(M))
M.gib() //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. Forever.
else
- M.Move(loc)
+ M.forceMove(loc)
if(prob(30))
explosion(get_turf(loc), 0, 0, 1, 3)
- if(istype(src, /obj/mecha/working/ripley/))
- var/obj/mecha/working/ripley/R = src
- if(R.cargo)
- for(var/obj/O in R.cargo) //Dump contents of stored cargo
- O.forceMove(loc)
- R.cargo -= O
- loc.Entered(O)
-
if(wreckage)
var/obj/effect/decal/mecha_wreckage/WR = new wreckage(loc)
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
@@ -654,65 +607,43 @@
qdel(cell)
if(internal_tank)
qdel(internal_tank)
+
+ processing_objects.Remove(src)
equipment.Cut()
cell = null
internal_tank = null
-
- qdel(pr_int_temp_processor)
- qdel(pr_give_air)
- qdel(pr_internal_damage)
+ if(loc)
+ loc.assume_air(cabin_air)
+ air_update_turf()
+ else
+ qdel(cabin_air)
+ cabin_air = null
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
return ..()
/obj/mecha/ex_act(severity)
- src.log_message("Affected by explosion of severity: [severity].",1)
- if(prob(src.deflect_chance))
+ log_message("Affected by explosion of severity: [severity].",1)
+ if(prob(deflect_chance))
severity++
- src.log_append_to_last("Armor saved, changing severity to [severity].")
+ log_append_to_last("Armor saved, changing severity to [severity].")
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
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)
+ take_damage(initial(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)
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
-
-/*Will fix later -Sieve
-/obj/mecha/attack_blob(mob/user as mob)
- src.log_message("Attack by blob. Attacker - [user].",1)
- if(!prob(src.deflect_chance))
- src.take_damage(6)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1)
- to_chat(user, "\red You smash at the armored suit!")
- for(var/mob/V in viewers(src))
- if(V.client && !(V.blinded))
- V.show_message("\red The [user] smashes against [src.name]'s armor!", 1)
- else
- src.log_append_to_last("Armor saved.")
- playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1)
- to_chat(user, "\green Your attack had no effect!")
- src.occupant_message("\blue The [user]'s attack is stopped by the armor.")
- for(var/mob/V in viewers(src))
- if(V.client && !(V.blinded))
- V.show_message("\blue The [user] rebounds off the [src.name] armor!", 1)
- return
-*/
+ take_damage(initial(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)
//TODO
/obj/mecha/blob_act()
@@ -721,45 +652,23 @@
/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
+ use_power((cell.charge / 2) / severity)
+ take_damage(50 / severity, "energy")
+ 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)
/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, params)
- src.log_message("Attacked by [W]. Attacker - [user]")
- user.changeNext_move(CLICK_CD_MELEE)
- user.do_attack_animation(src)
- if(prob(src.deflect_chance))
- to_chat(user, "\red The [W] bounces off [src.name] armor.")
- src.log_append_to_last("Armor saved.")
-/*
- for(var/mob/V in viewers(src))
- if(V.client && !(V.blinded))
- V.show_message("The [W] bounces off [src.name] armor.", 1)
-*/
- else
- src.occupant_message("[user] hits [src] with [W].")
- 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
+ if(exposed_temperature > 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))
//////////////////////
////// AttackBy //////
//////////////////////
-/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
-
- if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain))
+/obj/mecha/attackby(obj/item/weapon/W, mob/user, params)
+ if(istype(W, /obj/item/device/mmi))
if(mmi_move_inside(W,user))
to_chat(user, "[src]-MMI interface initialized successfuly")
else
@@ -770,13 +679,15 @@
var/obj/item/mecha_parts/mecha_equipment/E = W
spawn()
if(E.can_attach(src))
- user.drop_item()
+ if(!user.drop_item())
+ return
E.attach(src)
- user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]")
+ user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src].")
else
- to_chat(user, "You were unable to attach [W] to [src]")
+ to_chat(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(W.GetID())
if(add_req_access || maint_access)
if(internals_access_allowed(usr))
var/obj/item/weapon/card/id/id_card
@@ -788,10 +699,11 @@
output_maintenance_dialog(id_card, user)
return
else
- to_chat(user, "\red Invalid ID: Access denied.")
+ to_chat(user, "Invalid ID: Access denied.")
else
- to_chat(user, "\red Maintenance protocols disabled by operator.")
- else if(istype(W, /obj/item/weapon/wrench))
+ to_chat(user, "Maintenance protocols disabled by operator.")
+
+ else if(iswrench(W))
if(state==1)
state = 2
to_chat(user, "You undo the securing bolts.")
@@ -799,7 +711,8 @@
state = 1
to_chat(user, "You tighten the securing bolts.")
return
- else if(istype(W, /obj/item/weapon/crowbar))
+
+ else if(iscrowbar(W))
if(state==2)
state = 3
to_chat(user, "You open the hatch to the power unit")
@@ -815,7 +728,6 @@
go_out()
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
@@ -826,58 +738,61 @@
else
to_chat(user, "There's not enough wire to finish the task.")
return
- else if(istype(W, /obj/item/weapon/screwdriver))
+
+ else if(isscrewdriver(W) && user.a_intent != I_HARM)
if(hasInternalDamage(MECHA_INT_TEMP_CONTROL))
clearInternalDamage(MECHA_INT_TEMP_CONTROL)
- to_chat(user, "You repair the damaged temperature controller.")
- else if(state==3 && src.cell)
- src.cell.forceMove(src.loc)
- src.cell = null
+ to_chat(user, "You repair the damaged temperature controller.")
+ else if(state==3 && cell)
+ cell.forceMove(loc)
+ cell = null
state = 4
- to_chat(user, "You unscrew and pry out the powercell.")
- src.log_message("Powercell removed")
- else if(state==4 && src.cell)
+ to_chat(user, "You unscrew and pry out the powercell.")
+ log_message("Powercell removed")
+ else if(state==4 && cell)
state=3
- to_chat(user, "You screw the cell in place")
+ to_chat(user, "You screw the cell in place.")
return
else if(istype(W, /obj/item/weapon/stock_parts/cell))
if(state==4)
- if(!src.cell)
- to_chat(user, "You install the powercell")
- user.drop_item()
+ if(!cell)
+ if(!user.drop_item())
+ return
+ to_chat(user, "You install the powercell.")
W.forceMove(src)
- src.cell = W
- src.log_message("Powercell installed")
+ cell = W
+ log_message("Powercell installed")
else
- to_chat(user, "There's already a powercell installed.")
+ to_chat(user, "There's already a powercell installed.")
return
- else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != I_HARM)
+ else if(iswelder(W) && user.a_intent != I_HARM)
var/obj/item/weapon/weldingtool/WT = W
- if(WT.remove_fuel(0,user))
- if(hasInternalDamage(MECHA_INT_TANK_BREACH))
- clearInternalDamage(MECHA_INT_TANK_BREACH)
- to_chat(user, "\blue You repair the damaged gas tank.")
+ if(healthYou repair the damaged gas tank.")
+ else
+ user.visible_message("[user] repairs some damage to [name].")
+ health += min(10, initial(health)-health)
+ else
+ to_chat(user, "The welder must be on for this task!")
+ return 1
else
- return
- if(src.healthThe [name] is at full integrity!")
+ return 1
else if(istype(W, /obj/item/mecha_parts/mecha_tracking))
if(!user.unEquip(W))
to_chat(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]")
+ user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src].")
return
else if(istype(W, /obj/item/weapon/paintkit))
-
if(occupant)
to_chat(user, "You can't customize a mech while someone is piloting it - that would be unsafe!")
return
@@ -886,7 +801,7 @@
var/found = null
for(var/type in P.allowed_types)
- if(type==src.initial_icon)
+ if(type == initial_icon)
found = 1
break
@@ -896,43 +811,41 @@
user.visible_message("[user] opens [P] and spends some quality time customising [src].")
- src.name = P.new_name
- src.desc = P.new_desc
- src.initial_icon = P.new_icon
- src.reset_icon()
+ name = P.new_name
+ desc = P.new_desc
+ initial_icon = P.new_icon
+ reset_icon()
user.drop_item()
qdel(P)
else
- call((proc_res["dynattackby"]||src), "dynattackby")(W,user)
-/*
- src.log_message("Attacked by [W]. Attacker - [user]")
- if(prob(src.deflect_chance))
- to_chat(user, "\red The [W] bounces off [src.name] armor.")
- src.log_append_to_last("Armor saved.")
-/*
- for(var/mob/V in viewers(src))
- if(V.client && !(V.blinded))
- V.show_message("The [W] bounces off [src.name] armor.", 1)
-*/
- else
- src.occupant_message("[user] hits [src] with [W].")
- 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))
-*/
- diag_hud_set_mechhealth()
- diag_hud_set_mechcell()
- diag_hud_set_mechstat()
- return
+ return attacked_by(W, user)
+
+/obj/mecha/proc/attacked_by(obj/item/I, mob/user)
+ log_message("Attacked by [I]. 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))
+ to_chat(user, "[I] bounces off [src]\s armor.")
+ log_append_to_last("Armor saved.")
+ else
+ user.visible_message("[user] hits [src] with [I].", "You hit [src] with [I].")
+ take_damage(round(I.force * dam_coeff), I.damtype)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+
/obj/mecha/emag_act(user as mob)
if(istype(src, /obj/mecha/working/ripley) && emagged == 0)
emagged = 1
to_chat(usr, "\blue You slide the card through the [src]'s ID slot.")
- playsound(src.loc, "sparks", 100, 1)
- src.desc += "The mech's equipment slots spark dangerously!"
+ playsound(loc, "sparks", 100, 1)
+ desc += "The mech's equipment slots spark dangerously!"
else
to_chat(usr, "\red The [src]'s ID slot rejects the card.")
return
@@ -1033,7 +946,6 @@
var/turf/T = get_turf(src)
if(T)
. = T.return_air()
- return
/obj/mecha/remove_air(amount)
if(use_internal_tank)
@@ -1042,7 +954,6 @@
var/turf/T = get_turf(src)
if(T)
return T.remove_air(amount)
- return
/obj/mecha/return_air()
if(use_internal_tank)
@@ -1050,25 +961,15 @@
return get_turf_air()
/obj/mecha/proc/return_pressure()
- . = 0
- if(use_internal_tank)
- . = cabin_air.return_pressure()
- else
- var/datum/gas_mixture/t_air = get_turf_air()
- if(t_air)
- . = t_air.return_pressure()
- return
+ var/datum/gas_mixture/t_air = return_air()
+ if(t_air)
+ . = t_air.return_pressure()
//skytodo: //No idea what you want me to do here, mate.
/obj/mecha/proc/return_temperature()
- . = 0
- if(use_internal_tank)
- . = cabin_air.return_temperature()
- else
- var/datum/gas_mixture/t_air = get_turf_air()
- if(t_air)
- . = t_air.return_temperature()
- return
+ var/datum/gas_mixture/t_air = return_air()
+ if(t_air)
+ . = t_air.return_temperature()
/obj/mecha/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port)
//Make sure not already connected to something else
@@ -1076,7 +977,7 @@
return 0
//Make sure are close enough for a valid connection
- if(new_port.loc != src.loc)
+ if(new_port.loc != loc)
return 0
//Perform the connection
@@ -1093,7 +994,7 @@
connected_port.connected_device = null
connected_port = null
- src.log_message("Disconnected from gas port.")
+ log_message("Disconnected from gas port.")
return 1
/obj/mecha/portableConnectorReturnAir()
@@ -1110,21 +1011,21 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
- if(!src.occupant) return
- if(usr!=src.occupant)
+ if(!occupant) return
+ if(usr!=occupant)
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("\blue [name] connects to the port.")
- src.verbs += /obj/mecha/verb/disconnect_from_port
- src.verbs -= /obj/mecha/verb/connect_to_port
+ occupant_message("\blue [name] connects to the port.")
+ verbs += /obj/mecha/verb/disconnect_from_port
+ verbs -= /obj/mecha/verb/connect_to_port
return
else
- src.occupant_message("\red [name] failed to connect to the port.")
+ occupant_message("\red [name] failed to connect to the port.")
return
else
- src.occupant_message("Nothing happens")
+ occupant_message("Nothing happens")
/obj/mecha/verb/disconnect_from_port()
@@ -1132,15 +1033,15 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
- if(!src.occupant) return
- if(usr!=src.occupant)
+ if(!occupant) return
+ if(usr!=occupant)
return
if(disconnect())
- src.occupant_message("\blue [name] disconnects from the port.")
- src.verbs -= /obj/mecha/verb/disconnect_from_port
- src.verbs += /obj/mecha/verb/connect_to_port
+ occupant_message("\blue [name] disconnects from the port.")
+ verbs -= /obj/mecha/verb/disconnect_from_port
+ verbs += /obj/mecha/verb/connect_to_port
else
- src.occupant_message("\red [name] is not connected to the port at the moment.")
+ occupant_message("\red [name] is not connected to the port at the moment.")
/obj/mecha/verb/toggle_lights()
set name = "Toggle Lights"
@@ -1151,7 +1052,7 @@
lights = !lights
if(lights) set_light(light_range + lights_power)
else set_light(light_range - lights_power)
- src.occupant_message("Toggled lights [lights?"on":"off"].")
+ occupant_message("Toggled lights [lights?"on":"off"].")
log_message("Toggled lights [lights?"on":"off"].")
return
@@ -1161,98 +1062,103 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
- if(usr!=src.occupant)
+ if(usr!=occupant)
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"].")
+ occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
+ 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.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other
+/obj/mecha/MouseDrop_T(mob/M, mob/user)
+ if(user.incapacitated())
return
if(user != M)
return
- src.log_message("[user] tries to move in.")
- if(src.occupant)
- to_chat(usr, "The [src.name] is already occupied!")
- src.log_append_to_last("Permission denied.")
+ log_message("[user] tries to move in.")
+ if(occupant)
+ to_chat(user, "The [src] is already occupied!")
+ log_append_to_last("Permission denied.")
return
var/passed
- if(src.dna)
- if(user.stat || ishuman(user))
- if(user.dna.unique_enzymes==src.dna)
+ if(dna)
+ if(ishuman(user))
+ if(user.dna.unique_enzymes == dna)
passed = 1
- else if(src.operation_allowed(user))
+ else if(operation_allowed(user))
passed = 1
if(!passed)
to_chat(user, "Access denied.")
- src.log_append_to_last("Permission denied.")
+ log_append_to_last("Permission denied.")
+ return
+ if(user.buckled)
+ to_chat(user, "You are currently buckled and cannot move.")
+ log_append_to_last("Permission denied.")
+ return
+ if(user.has_buckled_mobs()) //mob attached to us
+ to_chat(user, "You can't enter the exosuit with other creatures attached to you!")
return
for(var/mob/living/carbon/slime/S in range(1,user))
if(S.Victim == user)
to_chat(user, "You're too busy getting your life sucked out of you.")
return
- visible_message("[user] starts to climb into [src.name]")
+ visible_message("[user] starts to climb into [src]")
- if(enter_after(40,user))
- if(!src.occupant)
+ if(do_after(user, 40, target = src))
+ if(health <= 0)
+ to_chat(user, "You cannot get in the [name], it has been destroyed!")
+ else if(occupant)
+ to_chat(user, "[occupant] was faster! Try better next time, loser.")
+ else if(user.buckled)
+ to_chat(user, "You can't enter the exosuit while buckled.")
+ else if(user.has_buckled_mobs())
+ to_chat(user, "You can't enter the exosuit with other creatures attached to you!")
+ else
moved_inside(user)
- else if(src.occupant!=user)
- to_chat(user, "[src.occupant] was faster. Try better next time, loser.")
else
- to_chat(user, "You stop entering the exosuit.")
- return
+ to_chat(user, "You stop entering the exosuit!")
/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
- */
+ occupant = H
H.stop_pulling()
H.forceMove(src)
- src.occupant = H
- src.add_fingerprint(H)
- src.forceMove(src.loc)
- src.log_append_to_last("[H] moved in as pilot.")
- src.icon_state = src.reset_icon()
+ H.reset_view(src)
+ add_fingerprint(H)
+ //GrantActions(H, human_occupant=1)
+ forceMove(loc)
+ log_append_to_last("[H] moved in as pilot.")
+ icon_state = reset_icon()
dir = dir_in
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
if(!hasInternalDamage())
- occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ occupant << sound('sound/mecha/nominal.ogg', volume = 50)
return 1
else
return 0
/obj/mecha/proc/mmi_move_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob)
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
- to_chat(user, "Consciousness matrix not detected.")
+ to_chat(user, "Consciousness matrix not detected!")
return 0
else if(mmi_as_oc.brainmob.stat)
- to_chat(user, "Beta-rhythm below acceptable level.")
+ to_chat(user, "Beta-rhythm below acceptable level!")
return 0
else if(occupant)
- to_chat(user, "Occupant detected.")
+ to_chat(user, "Occupant detected!")
return 0
- else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes)
- to_chat(user, "Stop it!")
+ else if(dna && dna != mmi_as_oc.brainmob.dna.unique_enzymes)
+ to_chat(user, "Access denied. [name] is secured with a DNA lock.")
return 0
- //Added a message here since people assume their first click failed or something./N
-// to_chat(user, "Installing MMI, please stand by.")
- visible_message("\blue [usr] 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
- to_chat(user, "Occupant detected.")
+ to_chat(user, "Occupant detected!")
else
- to_chat(user, "You stop inserting the MMI.")
+ to_chat(user, "You stop inserting the MMI.")
return 0
/obj/mecha/proc/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob)
@@ -1277,14 +1183,14 @@
brainmob.canmove = 1
mmi_as_oc.loc = src
mmi_as_oc.mecha = src
- src.verbs -= /obj/mecha/verb/eject
- src.Entered(mmi_as_oc)
- src.Move(src.loc)
- src.icon_state = src.reset_icon()
+ verbs -= /obj/mecha/verb/eject
+ Entered(mmi_as_oc)
+ Move(loc)
+ icon_state = reset_icon()
dir = dir_in
- src.log_message("[mmi_as_oc] moved in as pilot.")
+ log_message("[mmi_as_oc] moved in as pilot.")
if(!hasInternalDamage())
- to_chat(src.occupant, sound('sound/mecha/nominal.ogg',volume=50))
+ to_chat(occupant, sound('sound/mecha/nominal.ogg',volume=50))
return 1
else
return 0
@@ -1306,88 +1212,65 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
- if(usr!=src.occupant)
+ if(usr!=occupant)
return
- //pr_update_stats.start()
- src.occupant << browse(src.get_stats_html(), "window=exosuit")
+ occupant << browse(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(usr!=src.occupant)
+ if(usr != occupant)
return
- src.go_out()
+ go_out()
add_fingerprint(usr)
- return
-/obj/mecha/proc/go_out(var/forced)
- if(!src.occupant) return
+/obj/mecha/Exited(atom/movable/M, 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
+ 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/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 << browse(null, "window=exosuit")
- 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)
- to_chat(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")
- if(istype(mob_container, /obj/item/device/mmi) || istype(mob_container, /obj/item/device/mmi/posibrain))
+ 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
+ L.reset_view()
mmi.mecha = null
- src.occupant.canmove = 0
- src.verbs += /obj/mecha/verb/eject
- src.occupant = null
- src.icon_state = src.reset_icon()+"-open"
- src.dir = dir_in
- return
+ mmi.update_icon()
+ L.canmove = 0
+ icon_state = initial(icon_state)+"-open"
+ dir = dir_in
+
+ if(L && L.client)
+ L.client.view = world.view
/////////////////////////
////// Access stuff /////
@@ -1397,14 +1280,14 @@
if(!ishuman(H))
return 0
for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt))
- if(src.check_access(ID,src.operation_req_access))
+ if(check_access(ID,operation_req_access))
return 1
return 0
/obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H)
for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt))
- if(src.check_access(ID,src.internals_req_access))
+ if(check_access(ID,internals_req_access))
return 1
return 0
@@ -1419,410 +1302,16 @@
I = pda.id
if(!istype(I) || !I.access) //not ID or no access
return 0
- if(access_list==src.operation_req_access)
+ if(access_list==operation_req_access)
for(var/req in access_list)
if(!(req in I.access)) //doesn't have this access
return 0
- else if(access_list==src.internals_req_access)
+ else if(access_list==internals_req_access)
for(var/req in access_list)
if(req in I.access)
return 1
return 1
-
-////////////////////////////////////
-///// 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 += {"[time2text(entry["time"],"DDD MMM DD hh:mm:ss")] 2555
- [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 ///////
-////////////////////////////////
-
-/obj/mecha/proc/occupant_message(message as text)
- if(message)
- if(src.occupant && src.occupant.client)
- to_chat(src.occupant, "[bicon(src)] [message]")
- return
-
-/obj/mecha/proc/log_message(message as text,red=null)
- log.len++
- log[log.len] = list("time"=world.timeofday,"message"="[red?"":null][message][red?"":null]")
- return log.len
-
-/obj/mecha/proc/log_append_to_last(message as text,red=null)
- var/list/last_entry = src.log[src.log.len]
- last_entry["message"] += "
[red?"":null][message][red?"":null]"
- return
-
-
-/////////////////
-///// 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.frequency < PUBLIC_LOW_FREQ || radio.frequency > PUBLIC_HIGH_FREQ))
- 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 = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, 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
- to_chat(user, "The securing bolts are now exposed.")
- else if(state==1)
- state = 0
- to_chat(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
- to_chat(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))
- to_chat(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(mecha_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 /////
///////////////////////
@@ -1834,9 +1323,9 @@
return call((proc_res["dyngetcharge"]||src), "dyngetcharge")()
/obj/mecha/proc/dyngetcharge()//returns null if no powercell, else returns cell.charge
- if(!src.cell) return
+ if(!cell) return
diag_hud_set_mechcell()
- return max(0, src.cell.charge)
+ return max(0, cell.charge)
/obj/mecha/proc/use_power(amount)
return call((proc_res["dynusepower"]||src), "dynusepower")(amount)
@@ -1872,122 +1361,88 @@
//////// Mecha global iterators ////////
//////////////////////////////////////////
+/obj/mecha/process()
+ process_internal_damage()
+ regulate_temp()
+ give_air()
+ update_huds()
-/datum/global_iterator/mecha_preserve_temp //normalizing cabin air temperature to 20 degrees celsium
- delay = 20
-
- 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)))
+/obj/mecha/proc/process_internal_damage()
+ if(!internal_damage)
return
-/datum/global_iterator/mecha_tank_give_air
- delay = 15
+ if(internal_damage & MECHA_INT_FIRE)
+ if(!(internal_damage & MECHA_INT_TEMP_CONTROL) && prob(5))
+ clearInternalDamage(MECHA_INT_FIRE)
+ if(internal_tank)
+ var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
+ if(int_tank_air.return_pressure() > internal_tank.maximum_pressure && !(internal_damage & MECHA_INT_TANK_BREACH))
+ setInternalDamage(MECHA_INT_TANK_BREACH)
- 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
+ if(int_tank_air && int_tank_air.return_volume() > 0)
+ int_tank_air.temperature = min(6000 + T0C, cabin_air.return_temperature() + rand(10, 15))
- 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.get_turf_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
- qdel(removed)
- else
- return stop()
+ 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_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)
+ air_update_turf()
+ else
+ qdel(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)
+
+/obj/mecha/proc/regulate_temp()
+ if(internal_damage & MECHA_INT_TEMP_CONTROL)
return
+ 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)))
-/datum/global_iterator/mecha_internal_damage // processing internal damage
-
- 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
- qdel(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)
+/obj/mecha/proc/give_air()
+ if(!internal_tank)
return
+ 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
+ qdel(removed)
-//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)
- 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
-
- "}
-
- 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
-*/
+/obj/mecha/proc/update_huds()
+ diag_hud_set_mechhealth()
+ diag_hud_set_mechcell()
+ diag_hud_set_mechstat()
/obj/mecha/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm
new file mode 100644
index 00000000000..c24a85b6967
--- /dev/null
+++ b/code/game/mecha/mecha_topic.dm
@@ -0,0 +1,393 @@
+
+////////////////////////////////////
+///// Rendering stats window ///////
+////////////////////////////////////
+
+/obj/mecha/proc/get_stats_html()
+ var/output = {"
+ [name] data
+
+
+
+
+
+ [get_stats_part()]
+
+
+ [get_equipment_list()]
+
+
+
+ [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"]
+ [dna?"DNA-locked:
[dna] \[Reset\]
":null]
+ "}
+ return output
+
+/obj/mecha/proc/get_commands()
+ var/output = {"
+
+
+
+
+ [(/obj/mecha/verb/eject in 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 = "[name] Log"
+ for(var/list/entry in log)
+ output += {"[time2text(entry["time"],"DDD MMM DD hh:mm:ss")] 2555
+ [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 ///////
+////////////////////////////////
+
+/obj/mecha/proc/occupant_message(message as text)
+ if(message)
+ if(occupant && occupant.client)
+ to_chat(occupant, "[bicon(src)] [message]")
+ return
+
+/obj/mecha/proc/log_message(message as text,red=null)
+ log.len++
+ log[log.len] = list("time"=world.timeofday,"message"="[red?"":null][message][red?"":null]")
+ return log.len
+
+/obj/mecha/proc/log_append_to_last(message as text,red=null)
+ var/list/last_entry = log[log.len]
+ last_entry["message"] += "
[red?"":null][message][red?"":null]"
+ return
+
+
+/////////////////
+///// Topic /////
+/////////////////
+
+/obj/mecha/Topic(href, href_list)
+ ..()
+ if(href_list["update_content"])
+ if(usr != occupant) return
+ send_byjax(occupant,"exosuit.browser","content",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 != occupant) return
+ var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip")
+ if(equip)
+ selected = equip
+ occupant_message("You switch to [equip]")
+ visible_message("[src] raises [equip]")
+ send_byjax(occupant,"exosuit.browser","eq_list",get_equipment_list())
+ return
+ if(href_list["eject"])
+ if(usr != occupant) return
+ eject()
+ return
+ if(href_list["toggle_lights"])
+ if(usr != occupant) return
+ toggle_lights()
+ return
+ if(href_list["toggle_airtank"])
+ if(usr != occupant) return
+ toggle_internal_tank()
+ return
+ if(href_list["rmictoggle"])
+ if(usr != occupant) return
+ radio.broadcasting = !radio.broadcasting
+ send_byjax(occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged"))
+ return
+ if(href_list["rspktoggle"])
+ if(usr != occupant) return
+ radio.listening = !radio.listening
+ send_byjax(occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged"))
+ return
+ if(href_list["rfreq"])
+ if(usr != occupant) return
+ var/new_frequency = (radio.frequency + filter.getNum("rfreq"))
+ if((radio.frequency < PUBLIC_LOW_FREQ || radio.frequency > PUBLIC_HIGH_FREQ))
+ new_frequency = sanitize_frequency(new_frequency)
+ radio.set_frequency(new_frequency)
+ send_byjax(occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]")
+ return
+ if(href_list["port_disconnect"])
+ if(usr != occupant) return
+ disconnect_from_port()
+ return
+ if(href_list["port_connect"])
+ if(usr != occupant) return
+ connect_to_port()
+ return
+ if(href_list["view_log"])
+ if(usr != occupant) return
+ occupant << browse(get_log_html(), "window=exosuit_log")
+ onclose(occupant, "exosuit_log")
+ return
+ if(href_list["change_name"])
+ if(usr != occupant) return
+ var/newname = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN)
+ if(newname && trim(newname))
+ name = newname
+ else
+ alert(occupant, "nope.avi")
+ return
+ if(href_list["toggle_id_upload"])
+ if(usr != occupant) return
+ add_req_access = !add_req_access
+ send_byjax(occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel")
+ return
+ if(href_list["toggle_maint_access"])
+ if(usr != occupant) return
+ if(state)
+ occupant_message("Maintenance protocols in effect")
+ return
+ maint_access = !maint_access
+ send_byjax(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
+ to_chat(user, "The securing bolts are now exposed.")
+ else if(state==1)
+ state = 0
+ to_chat(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
+ to_chat(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 != occupant)
+ return
+ if(occupant && !iscarbon(occupant))
+ to_chat(occupant, "You do not have any DNA!")
+ return
+ dna = occupant.dna.unique_enzymes
+ occupant_message("You feel a prick as the needle takes your DNA sample.")
+ return
+ if(href_list["reset_dna"])
+ if(usr != occupant) return
+ dna = null
+ if(href_list["repair_int_control_lost"])
+ if(usr != occupant) return
+ 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)
+
+ //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
diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm
index a63a8d3d6dd..ce28687a9e6 100644
--- a/code/game/mecha/medical/medical.dm
+++ b/code/game/mecha/medical/medical.dm
@@ -1,22 +1,7 @@
+/obj/mecha/medical
+ turnsound = 'sound/mecha/mechmove01.ogg'
+ stepsound = 'sound/mecha/mechstep.ogg'
+
/obj/mecha/medical/New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
- return
-
-
-/obj/mecha/medical/mechturn(direction)
- dir = direction
- playsound(src,'sound/mecha/mechmove01.ogg',40,1)
- return 1
-
-/obj/mecha/medical/mechstep(direction)
- var/result = step(src,direction)
- if(result)
- playsound(src,'sound/mecha/mechstep.ogg',25,1)
- return result
-
-/obj/mecha/medical/mechsteprand()
- var/result = step_rand(src)
- if(result)
- playsound(src,'sound/mecha/mechstep.ogg',25,1)
- return result
\ No newline at end of file
diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm
index deb3df8b4fc..b7a320adc77 100644
--- a/code/game/mecha/medical/odysseus.dm
+++ b/code/game/mecha/medical/odysseus.dm
@@ -12,44 +12,35 @@
step_energy_drain = 6
var/builtin_hud_user = 0
- moved_inside(var/mob/living/carbon/human/H as mob)
- if(..())
- if(H.glasses && istype(H.glasses, /obj/item/clothing/glasses/hud))
- occupant_message("Your [H.glasses] prevent you from using the built-in medical hud.")
- else
- var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED]
- A.add_hud_to(H)
- builtin_hud_user = 1
- return 1
+/obj/mecha/medical/odysseus/moved_inside(var/mob/living/carbon/human/H)
+ . = ..()
+ if(. && ishuman(H))
+ if(istype(H.glasses, /obj/item/clothing/glasses/hud))
+ occupant_message("[H.glasses] prevent you from using the built-in medical hud.")
else
- return 0
-
- mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob)
- if(..())
- if(occupant.client)
- var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED]
- A.add_hud_to(occupant)
- builtin_hud_user = 1
- return 1
- else
- return 0
-
- go_out()
- if(istype(occupant,/mob/living/carbon/human) && builtin_hud_user)
- var/mob/living/carbon/human/H = occupant
var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED]
- A.remove_hud_from(H)
- builtin_hud_user = 0
- else if((istype(occupant, /mob/living/carbon/brain) || pilot_is_mmi()) && builtin_hud_user )
- var/mob/living/carbon/brain/H = occupant
+ A.add_hud_to(H)
+ builtin_hud_user = 1
+
+/obj/mecha/medical/odysseus/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc, mob/user)
+ . = ..()
+ if(.)
+ if(occupant.client)
var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED]
- A.remove_hud_from(H)
- builtin_hud_user = 0
+ A.add_hud_to(occupant)
+ builtin_hud_user = 1
- ..()
- return
+/obj/mecha/medical/odysseus/go_out()
+ if(ishuman(occupant) && builtin_hud_user)
+ var/mob/living/carbon/human/H = occupant
+ var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED]
+ A.remove_hud_from(H)
+ builtin_hud_user = 0
+ else if((isbrain(occupant) || pilot_is_mmi()) && builtin_hud_user)
+ var/mob/living/carbon/brain/H = occupant
+ var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED]
+ A.remove_hud_from(H)
+ builtin_hud_user = 0
+
+ . = ..()
-//TODO - Check documentation for client.eye and client.perspective...
-/obj/item/clothing/glasses/hud/health/mech
- name = "Integrated Medical Hud"
- HUDType = DATA_HUD_MEDICAL_ADVANCED
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 2a4f6adf189..c2ddd11d787 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -14,52 +14,46 @@
var/list/cargo = new
var/cargo_capacity = 15
-/*
-/obj/mecha/working/ripley/New()
- ..()
- return
-*/
-
/obj/mecha/working/ripley/Move()
. = ..()
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)
- A.loc = loc
+ while(damage_absorption.["brute"] < 0.6)
+ new /obj/item/asteroid/goliath_hide(loc)
+ damage_absorption.["brute"] = damage_absorption.["brute"] + 0.1 //If a goliath-plated ripley gets killed, all the plates drop
+ for(var/atom/movable/A in cargo)
+ A.forceMove(loc)
step_rand(A)
cargo.Cut()
return ..()
/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")
+ 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/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")
+ if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3)
+ overlays = null
+ overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g")
+ else if(damage_absorption.["brute"] == 0.3)
+ overlays = null
+ overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full")
/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")
+ if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3)
+ overlays = null
+ overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g")
+ else if(damage_absorption.["brute"] == 0.3)
+ overlays = null
+ overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full")
/obj/mecha/working/ripley/firefighter
desc = "Standart APLU chassis was refitted with additional thermal protection and cistern."
@@ -90,7 +84,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
@@ -102,10 +96,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
@@ -117,12 +111,12 @@
cargo.Add(new /obj/structure/ore_box(src))
//Attach hydrolic 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
+ for(var/obj/item/mecha_parts/mecha_tracking/B in 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)
@@ -134,14 +128,14 @@
..()
if(href_list["drop_from_cargo"])
var/obj/O = locate(href_list["drop_from_cargo"])
- if(O && O in src.cargo)
- src.occupant_message("\blue You unload [O].")
+ if(O && O in cargo)
+ occupant_message("\blue You unload [O].")
O.loc = get_turf(src)
- src.cargo -= O
+ cargo -= O
var/turf/T = get_turf(O)
if(T)
T.Entered(O)
- src.log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]")
+ log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - cargo.len]")
return
@@ -149,8 +143,8 @@
/obj/mecha/working/ripley/get_stats_part()
var/output = ..()
output += "Cargo Compartment Contents:"
- if(src.cargo.len)
- for(var/obj/O in src.cargo)
+ if(cargo.len)
+ for(var/obj/O in cargo)
output += "
Unload : [O]
"
else
output += "Nothing"
@@ -159,12 +153,12 @@
/obj/mecha/working/ripley/Destroy()
for(var/mob/M in src)
- if(M==src.occupant)
+ if(M == occupant)
continue
M.loc = get_turf(src)
M.loc.Entered(M)
step_rand(M)
- for(var/atom/movable/A in src.cargo)
+ for(var/atom/movable/A in cargo)
A.loc = get_turf(src)
var/turf/T = get_turf(A)
if(T)
@@ -179,9 +173,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)
\ No newline at end of file
diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm
index 7a59b6190ed..ccbfe2ef21b 100644
--- a/code/game/mecha/working/working.dm
+++ b/code/game/mecha/working/working.dm
@@ -4,29 +4,3 @@
/obj/mecha/working/New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
- return
-
-/*
-/obj/mecha/working/melee_action(atom/target as obj|mob|turf)
- if(internal_damage&MECHA_INT_CONTROL_LOST)
- target = pick(oview(1,src))
- if(selected_tool)
- selected_tool.action(target)
- return
-*/
-
-/obj/mecha/working/range_action(atom/target as obj|mob|turf)
- return
-
-/*
-/obj/mecha/working/get_stats_part()
- var/output = ..()
- output += "
[src.name] Tools:"
- if(equipment.len)
- for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
- output += "[selected==MT?"
":""][MT.get_equip_info()][selected==MT?"":""]
"
- else
- output += "None"
- output += "
"
- return output
-*/
\ No newline at end of file
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index cead6e33ffd..4c61393d9f7 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -29,6 +29,11 @@
. = ..()
unbuckle_mob()
+/atom/movable/proc/has_buckled_mobs()
+ if(buckled_mob)
+ return TRUE
+ return FALSE
+
//procs that handle the actual buckling and unbuckling
/atom/movable/proc/buckle_mob(mob/living/M)
if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || M.buckled_mob || buckled_mob || (buckle_requires_restraints && !M.restrained()) || M == src)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 5946ef77f0a..3a04a11f9e6 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -200,6 +200,9 @@
levelupdate()
CalculateAdjacentTurfs()
+ if(air_master && !ignore_air)
+ air_master.add_to_active(src)
+
if(!keep_cabling && !can_have_cabling())
for(var/obj/structure/cable/C in contents)
qdel(C)
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index a76dfa9a699..0c24daf977c 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -436,10 +436,9 @@ var/global/list/rockTurfEdgeCache = list(
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))
M.selected.action(src)
- else
- return
+
/**********************Asteroid**************************/
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 93b94e74f9e..1d2b40c6a70 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -90,21 +90,23 @@
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/mob/visible_message(var/message, var/self_message, var/blind_message)
- for(var/mob/M in viewers(src))
+ for(var/mob/M in get_mobs_in_view(7, src))
if(M.see_invisible < invisibility)
continue //can't view the invisible
var/msg = message
- if(self_message && M==src)
+ if(self_message && M == src)
msg = self_message
- M.show_message( msg, 1, blind_message, 2)
+ M.show_message(msg, 1, blind_message, 2)
// Show a message to all mobs in sight of this atom
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/atom/proc/visible_message(var/message, var/blind_message)
- for(var/mob/M in viewers(src))
- M.show_message( message, 1, blind_message, 2)
+ for(var/mob/M in get_mobs_in_view(7, src))
+ if(!M.client)
+ continue
+ M.show_message(message, 1, blind_message, 2)
// Show a message to all mobs in earshot of this one
// This would be for audible actions by the src mob
@@ -118,7 +120,7 @@
range = hearing_distance
var/msg = message
for(var/mob/M in get_mobs_in_view(range, src))
- if(self_message && M==src)
+ if(self_message && M == src)
msg = self_message
M.show_message(msg, 2, deaf_message, 1)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 69e29fa9aa8..4c210f6f8f8 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -408,44 +408,42 @@
///Called by /client/Move()
///For moving in space
///Return 1 for movement 0 for none
-/mob/Process_Spacemove(var/movement_dir = 0)
-
+/mob/Process_Spacemove(movement_dir = 0)
if(..())
return 1
+ var/atom/movable/backup = get_spacemove_backup()
+ if(backup)
+ if(istype(backup) && movement_dir && !backup.anchored)
+ if(backup.newtonian_move(turn(movement_dir, 180))) //You're pushing off something movable, so it moves
+ src << "
You push off of [backup] to propel yourself."
+ return 1
+ return 0
+/mob/get_spacemove_backup()
var/atom/movable/dense_object_backup
- for(var/atom/A in orange(1, get_turf(src)))
+ for(var/A in orange(1, get_turf(src)))
if(isarea(A))
continue
-
else if(isturf(A))
var/turf/turf = A
- if(istype(turf,/turf/space))
+ if(istype(turf, /turf/space))
continue
-
if(!turf.density && !mob_negates_gravity())
continue
-
- return 1
-
+ return A
else
var/atom/movable/AM = A
if(AM == buckled) //Kind of unnecessary but let's just be sure
continue
- if(AM.density)
+ if(!AM.CanPass(src) || AM.density)
if(AM.anchored)
- return 1
+ return AM
if(pulling == AM)
continue
dense_object_backup = AM
+ break
+ . = dense_object_backup
- if(movement_dir && dense_object_backup)
- if(dense_object_backup.newtonian_move(turn(movement_dir, 180))) //You're pushing off something movable, so it moves
- to_chat(src, "
You push off of [dense_object_backup] to propel yourself.")
-
-
- return 1
- return 0
/mob/proc/mob_has_gravity(turf/T)
return has_gravity(src, T)
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index f292209ac3e..1a26599b93a 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -601,7 +601,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")
@@ -610,7 +610,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")
@@ -619,7 +619,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")
@@ -628,7 +628,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")
@@ -638,7 +638,7 @@
id = "mech_sleeper"
build_type = MECHFAB
req_tech = list("biotech" = 2)
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/sleeper
+ build_path = /obj/item/mecha_parts/mecha_equipment/medical/sleeper
materials = list(MAT_METAL=5000,MAT_GLASS=10000)
construction_time = 100
category = list("Exosuit Equipment")
@@ -648,7 +648,7 @@
id = "mech_syringe_gun"
build_type = MECHFAB
req_tech = list("magnets" = 3,"biotech" = 3)
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
+ build_path = /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun
materials = list(MAT_METAL=3000,MAT_GLASS=2000)
construction_time = 200
category = list("Exosuit Equipment")
@@ -723,7 +723,7 @@
desc = "An exosuit-mounted Mime Rapid Construction Device."
id = "mech_mrcd"
build_type = MECHFAB
- build_path = /obj/item/mecha_parts/mecha_equipment/tool/mimercd
+ build_path = /obj/item/mecha_parts/mecha_equipment/mimercd
materials = list(MAT_METAL=30000,MAT_TRANQUILLITE=10000)
construction_time = 700
category = list("Exosuit Equipment")
@@ -735,7 +735,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")
@@ -744,7 +744,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")
@@ -788,7 +788,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")
diff --git a/code/modules/research/xenoarchaeology/artifact/artifact.dm b/code/modules/research/xenoarchaeology/artifact/artifact.dm
index 82caa2b9be5..57759308aee 100644
--- a/code/modules/research/xenoarchaeology/artifact/artifact.dm
+++ b/code/modules/research/xenoarchaeology/artifact/artifact.dm
@@ -59,7 +59,7 @@
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))
M.selected.action(src)
/obj/structure/boulder/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm b/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm
index 4b16c25aeea..6544deb1d68 100644
--- a/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm
+++ b/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm
@@ -3,40 +3,11 @@
icon_state = "engineering_pod"
desc = "Stubby and round, it has a human sized access hatch on the top."
wreckage = /obj/effect/decal/mecha_wreckage/hoverpod
+ stepsound = 'sound/machines/hiss.ogg'
/obj/mecha/working/hoverpod/Process_Spacemove(var/movement_dir = 0)
return 1 // puts the hover in hoverpod
-//these three procs overriden to play different sounds
-/obj/mecha/working/hoverpod/mechturn(direction)
- dir = direction
- //playsound(src,'sound/machines/hiss.ogg',40,1)
- return 1
-
-/obj/mecha/working/hoverpod/mechstep(direction)
- var/result = step(src,direction)
- if(result)
- playsound(src,'sound/machines/hiss.ogg',40,1)
- return result
-
-
-/obj/mecha/working/hoverpod/mechsteprand()
- var/result = step_rand(src)
- if(result)
- playsound(src,'sound/machines/hiss.ogg',40,1)
- return result
-
/obj/effect/decal/mecha_wreckage/hoverpod
name = "Hover pod wreckage"
icon_state = "engineering_pod-broken"
-
- /*New()
- ..()
- var/list/parts = list(
-
- for(var/i=0;i<2;i++)
- if(!isemptylist(parts) && prob(40))
- var/part = pick(parts)
- welder_salvage += part
- parts -= part
- return*/
diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm
index d02787eb3b5..fa7c8c63451 100644
--- a/code/modules/surgery/generic.dm
+++ b/code/modules/surgery/generic.dm
@@ -214,7 +214,7 @@
//drill bone
/datum/surgery_step/generic/drill
name = "drill bone"
- allowed_tools = list(/obj/item/weapon/surgicaldrill = 100, /obj/item/weapon/pickaxe/drill = 60, /obj/item/mecha_parts/mecha_equipment/tool/drill = 60, /obj/item/weapon/screwdriver = 20)
+ allowed_tools = list(/obj/item/weapon/surgicaldrill = 100, /obj/item/weapon/pickaxe/drill = 60, /obj/item/mecha_parts/mecha_equipment/drill = 60, /obj/item/weapon/screwdriver = 20)
time = 30
/datum/surgery_step/generic/drill/begin_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
diff --git a/paradise.dme b/paradise.dme
index c75e5fc0c2c..c4dcba43636 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -639,6 +639,7 @@
#include "code\game\mecha\mecha_construction_paths.dm"
#include "code\game\mecha\mecha_control_console.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\paintkits.dm"
#include "code\game\mecha\combat\combat.dm"
@@ -650,7 +651,9 @@
#include "code\game\mecha\combat\recitence.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"