[src.get_equipment_list()]
@@ -97,7 +96,7 @@
"}
return output
-/obj/mecha/combat/honker/get_commands()
+/obj/vehicle/sealed/mecha/combat/honker/get_commands()
var/output = {"
"}
@@ -113,8 +120,8 @@
return output
-/obj/mecha/combat/honker/get_equipment_list()
- if(!equipment.len)
+/obj/vehicle/sealed/mecha/combat/honker/get_equipment_list()
+ if(!LAZYLEN(equipment))
return
var/output = "
Honk-ON-Systems:"
for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
@@ -122,19 +129,12 @@
output += "
"
return output
+/obj/vehicle/sealed/mecha/combat/honker/play_stepsound()
+ if(squeak)
+ playsound(src, "clownstep", 70, 1)
+ squeak = !squeak
-
-/obj/mecha/combat/honker/mechstep(direction)
- var/result = step(src,direction)
- if(result)
- if(!squeak)
- playsound(src, "clownstep", 70, 1)
- squeak = 1
- else
- squeak = 0
- return result
-
-/obj/mecha/combat/honker/Topic(href, href_list)
+/obj/vehicle/sealed/mecha/combat/honker/Topic(href, href_list)
..()
if (href_list["play_sound"])
switch(href_list["play_sound"])
@@ -148,11 +148,20 @@
playsound(src, 'sound/items/carhorn.ogg', 80) //soundfile has lower than average volume
if("party_horn")
playsound(src, 'sound/items/party_horn.ogg', 50)
+ if("reee")
+ playsound(src, 'sound/effects/reee.ogg', 50)
+ if("weeoo1")
+ playsound(src, 'sound/items/weeoo1.ogg', 50)
+ if("hiss1")
+ playsound(src, 'sound/voice/hiss1.ogg', 50)
+ if("armbomb")
+ playsound(src, 'sound/weapons/armbomb.ogg', 50)
+ if("saberon")
+ playsound(src, 'sound/weapons/saberon.ogg', 50)
+ if("airlock_alien_prying")
+ playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50)
+ if("lightningbolt")
+ playsound(src, 'sound/magic/lightningbolt.ogg', 50)
+ if("explosionfar")
+ playsound(src, 'sound/effects/explosionfar.ogg', 50)
return
-
-/proc/rand_hex_color()
- var/list/colors = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f")
- var/color=""
- for (var/i=0;i<6;i++)
- color = color+pick(colors)
- return color
diff --git a/code/game/mecha/combat/marauder.dm b/code/modules/vehicles/mecha/combat/marauder.dm
similarity index 61%
rename from code/game/mecha/combat/marauder.dm
rename to code/modules/vehicles/mecha/combat/marauder.dm
index 5c60a97864..d595509d2e 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/modules/vehicles/mecha/combat/marauder.dm
@@ -1,38 +1,32 @@
-/obj/mecha/combat/marauder
+/obj/vehicle/sealed/mecha/combat/marauder
desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations."
name = "\improper Marauder"
icon_state = "marauder"
- step_in = 5
+ movedelay = 5
max_integrity = 500
deflect_chance = 25
- armor = list("melee" = 50, "bullet" = 55, "laser" = 40, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
+ armor = list(MELEE = 50, BULLET = 55, LASER = 40, ENERGY = 30, BOMB = 30, BIO = 0, RAD = 60, FIRE = 100, ACID = 100)
max_temperature = 60000
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- infra_luminosity = 3
operation_req_access = list(ACCESS_CENT_SPECOPS)
- internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
+ internals_req_access = list(ACCESS_CENT_SPECOPS)
wreckage = /obj/structure/mecha_wreckage/marauder
- add_req_access = 0
+ mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS
internal_damage_threshold = 25
force = 45
- max_equip = 4
- bumpsmash = 1
+ max_equip = 5
+ bumpsmash = TRUE
-/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0)
- ..()
- smoke_action.Grant(user, src)
- thrusters_action.Grant(user, src)
- zoom_action.Grant(user, src)
-
-/obj/mecha/combat/marauder/RemoveActions(mob/living/user, human_occupant = 0)
- ..()
- smoke_action.Remove(user)
- thrusters_action.Remove(user)
- zoom_action.Remove(user)
-
-/obj/mecha/combat/marauder/loaded/Initialize()
+/obj/vehicle/sealed/mecha/combat/marauder/generate_actions()
. = ..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_smoke)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_zoom)
+
+/obj/vehicle/sealed/mecha/combat/marauder/loaded/Initialize()
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
ME.attach(src)
@@ -42,23 +36,24 @@
ME.attach(src)
max_ammo()
-/obj/mecha/combat/marauder/seraph
+/obj/vehicle/sealed/mecha/combat/marauder/seraph
desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel."
name = "\improper Seraph"
icon_state = "seraph"
operation_req_access = list(ACCESS_CENT_SPECOPS)
- internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
- step_in = 3
+ internals_req_access = list(ACCESS_CENT_SPECOPS)
+ movedelay = 3
max_integrity = 550
wreckage = /obj/structure/mecha_wreckage/seraph
internal_damage_threshold = 20
force = 55
- max_equip = 5
+ max_equip = 6
-/obj/mecha/combat/marauder/seraph/Initialize()
+/obj/vehicle/sealed/mecha/combat/marauder/seraph/Initialize()
. = ..()
- var/obj/item/mecha_parts/mecha_equipment/ME
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
ME.attach(src)
@@ -70,16 +65,22 @@
ME.attach(src)
max_ammo()
-/obj/mecha/combat/marauder/mauler
+/obj/vehicle/sealed/mecha/combat/marauder/mauler
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model."
name = "\improper Mauler"
icon_state = "mauler"
operation_req_access = list(ACCESS_SYNDICATE)
internals_req_access = list(ACCESS_SYNDICATE)
wreckage = /obj/structure/mecha_wreckage/mauler
- max_equip = 5
+ max_equip = 6
+ destruction_sleep_duration = 20
-/obj/mecha/combat/marauder/mauler/loaded/Initialize()
+/obj/vehicle/sealed/mecha/combat/marauder/mauler/Initialize()
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src)
+ ME.attach(src)
+
+/obj/vehicle/sealed/mecha/combat/marauder/mauler/loaded/Initialize()
. = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src)
ME.attach(src)
diff --git a/code/game/mecha/medical/medigax.dm b/code/modules/vehicles/mecha/combat/medigax.dm
similarity index 54%
rename from code/game/mecha/medical/medigax.dm
rename to code/modules/vehicles/mecha/combat/medigax.dm
index 98b7c9455b..6b2f54a976 100644
--- a/code/game/mecha/medical/medigax.dm
+++ b/code/modules/vehicles/mecha/combat/medigax.dm
@@ -1,34 +1,36 @@
-/obj/mecha/medical/medigax
+/obj/vehicle/sealed/mecha/medical/medigax
desc = "A Gygax with it's actuator overload stripped and a slick white paint scheme, for medical use, These exosuits are developed and produced by Vey-Med. (© All rights reserved)."
name = "\improper Medical Gygax"
icon_state = "medigax"
- step_in = 1.75 // a little faster than an odysseus
- max_temperature = 25000
+ allow_diagonal_movement = TRUE
+ movedelay = 2
+ dir_in = 1 //Facing North.
max_integrity = 250
- wreckage = /obj/structure/mecha_wreckage/odysseus
- armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
- internal_damage_threshold = 35
deflect_chance = 15
+ armor = list(MELEE = 25, BULLET = 20, LASER = 30, ENERGY = 15, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
+ max_temperature = 25000
+ wreckage = /obj/structure/mecha_wreckage/odysseus
+ internal_damage_threshold = 35
step_energy_drain = 6
infra_luminosity = 6
+ internals_req_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL)
-
-/obj/mecha/medical/medigax/moved_inside(mob/living/carbon/human/H)
+/obj/vehicle/sealed/mecha/medical/medigax/moved_inside(mob/living/carbon/human/H)
. = ..()
if(.)
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
hud.add_hud_to(H)
-/obj/mecha/medical/medigax/go_out()
- if(isliving(occupant))
- var/mob/living/carbon/human/L = occupant
+/obj/vehicle/sealed/mecha/medical/medigax/remove_occupant(mob/M)
+ if(isliving(M))
+ var/mob/living/L = M
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
hud.remove_hud_from(L)
- ..()
+ return ..()
-/obj/mecha/medical/medigax/mmi_moved_inside(obj/item/mmi/mmi_as_oc, mob/user)
+/obj/vehicle/sealed/mecha/medical/medigax/mmi_moved_inside(obj/item/mmi/M, mob/user)
. = ..()
if(.)
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
- var/mob/living/brain/B = mmi_as_oc.brainmob
+ var/mob/living/brain/B = M.brainmob
hud.add_hud_to(B)
diff --git a/code/game/mecha/combat/neovgre.dm b/code/modules/vehicles/mecha/combat/neovgre.dm
similarity index 65%
rename from code/game/mecha/combat/neovgre.dm
rename to code/modules/vehicles/mecha/combat/neovgre.dm
index 75470abe88..8085200246 100644
--- a/code/game/mecha/combat/neovgre.dm
+++ b/code/modules/vehicles/mecha/combat/neovgre.dm
@@ -1,52 +1,49 @@
-/obj/mecha/combat/neovgre
+/obj/vehicle/sealed/mecha/combat/neovgre
name = "Neovgre, the Anima Bulwark"
- desc = "Nezbere's most powerful creation, a mighty war machine of unmatched power said to have ended wars in a single night."
+ desc = "Nezbere's most powerful creation, a mighty war machine of unmatched power said to have ended wars in a single night. Armed with a heavy laser and a tesla sphere generator. Requires a pilot and a gunner."
icon = 'icons/mecha/neovgre.dmi'
icon_state = "neovgre"
max_integrity = 500 //This is THE ratvarian superweaon, its deployment is an investment
- armor = list("melee" = 50, "bullet" = 40, "laser" = 25, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) //Its similar to the clockwork armour albeit with a few buffs becuase RATVARIAN SUPERWEAPON!!
+ armor = list(MELEE = 50, BULLET = 40, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) //Its similar to the clockwork armour albeit with a few buffs becuase RATVARIAN SUPERWEAPON!!
force = 50 //SMASHY SMASHY!!
+ movedelay = 3
internal_damage_threshold = 0
- step_in = 3
pixel_x = -16
layer = ABOVE_MOB_LAYER
- breach_time = 100 //ten seconds till all goes to shit
- recharge_rate = 100
+ var/breach_time = 100 //ten seconds till all goes to shit
+ var/recharge_rate = 100
internals_req_access = list()
- add_req_access = 0
wreckage = /obj/structure/mecha_wreckage/durand/neovgre
stepsound = 'sound/mecha/neostep2.ogg'
turnsound = 'sound/mecha/powerloader_step.ogg'
+ max_occupants = 2
-/obj/mecha/combat/neovgre/GrantActions(mob/living/user, human_occupant = 0) //No Eject action for you sonny jim, your life for Ratvar!
- internals_action.Grant(user, src)
- cycle_action.Grant(user, src)
- lights_action.Grant(user, src)
- stats_action.Grant(user, src)
- strafing_action.Grant(user, src)
+//override this proc if you need to split up mecha control between multiple people (see savannah_ivanov.dm)
+/obj/vehicle/sealed/mecha/combat/neovgre/auto_assign_occupant_flags(mob/M)
+ if(driver_amount() < max_drivers)
+ add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS)
+ else
+ add_control_flags(M, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
-/obj/mecha/combat/neovgre/RemoveActions(mob/living/user, human_occupant = 0)
- internals_action.Remove(user)
- cycle_action.Remove(user)
- lights_action.Remove(user)
- stats_action.Remove(user)
- strafing_action.Remove(user)
+/obj/vehicle/sealed/mecha/combat/neovgre/mob_exit(mob/M, silent, forced)
+ if(forced)
+ ..()
-/obj/mecha/combat/neovgre/MouseDrop_T(mob/M, mob/user)
+/obj/vehicle/sealed/mecha/combat/neovgre/MouseDrop_T(mob/M, mob/user)
if(!is_servant_of_ratvar(user))
to_chat(user, "
BEGONE HEATHEN!")
return
else
..()
-/obj/mecha/combat/neovgre/moved_inside(mob/living/carbon/human/H)
+/obj/vehicle/sealed/mecha/combat/neovgre/moved_inside(mob/living/carbon/human/H)
var/list/Itemlist = H.get_contents()
for(var/obj/item/clockwork/slab/W in Itemlist)
to_chat(H, "
You safely store [W] inside [src].")
qdel(W)
. = ..()
-/obj/mecha/combat/neovgre/obj_destruction()
+/obj/vehicle/sealed/mecha/combat/neovgre/obj_destruction()
for(var/mob/M in src)
to_chat(M, "
You are consumed by the fires raging within Neovgre...")
M.dust()
@@ -54,15 +51,15 @@
src.visible_message("
The reactor has gone critical, its going to blow!")
addtimer(CALLBACK(src,.proc/go_critical),breach_time)
-/obj/mecha/combat/neovgre/proc/go_critical()
+/obj/vehicle/sealed/mecha/combat/neovgre/proc/go_critical()
explosion(get_turf(loc), 3, 5, 10, 20, 30)
Destroy(src)
-/obj/mecha/combat/neovgre/container_resist(mob/living/user)
+/obj/vehicle/sealed/mecha/combat/neovgre/container_resist(mob/living/user)
to_chat(user, "
Neovgre requires a lifetime commitment friend, no backing out now!")
return
-/obj/mecha/combat/neovgre/process()
+/obj/vehicle/sealed/mecha/combat/neovgre/process()
..()
if(!obj_integrity) //Integrity is zero but we would heal out of that state if we went into this before it recognises it being zero
return
@@ -80,11 +77,13 @@
if(obj_integrity < max_integrity && istype(loc, /turf/open/floor/clockwork))
obj_integrity += min(max_integrity - obj_integrity, max_integrity / 200)
-/obj/mecha/combat/neovgre/Initialize()
+/obj/vehicle/sealed/mecha/combat/neovgre/Initialize()
.=..()
GLOB.neovgre_exists ++
var/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/N = new
N.attach(src)
+ var/obj/item/mecha_parts/mecha_equipment/weapon/energy/tesla/shocking = new
+ shocking.attach(src)
/obj/structure/mecha_wreckage/durand/neovgre
name = "\improper Neovgre wreckage?"
@@ -97,7 +96,7 @@
desc = "Please re-attach this to neovgre and stop asking questions about why it looks like a normal Nanotrasen issue Solaris laser cannon - Nezbere"
fire_sound = 'sound/weapons/neovgre_laser.ogg'
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/can_attach(obj/mecha/combat/neovgre/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/can_attach(obj/vehicle/sealed/mecha/combat/neovgre/M)
if(istype(M))
return 1
return 0
diff --git a/code/modules/vehicles/mecha/combat/phazon.dm b/code/modules/vehicles/mecha/combat/phazon.dm
new file mode 100644
index 0000000000..c964b17e36
--- /dev/null
+++ b/code/modules/vehicles/mecha/combat/phazon.dm
@@ -0,0 +1,21 @@
+/obj/vehicle/sealed/mecha/combat/phazon
+ desc = "This is a Phazon exosuit. The pinnacle of scientific research and pride of Nanotrasen, it uses cutting edge bluespace technology and expensive materials."
+ name = "\improper Phazon"
+ icon_state = "phazon"
+ movedelay = 2
+ dir_in = 2 //Facing South.
+ step_energy_drain = 3
+ max_integrity = 200
+ deflect_chance = 30
+ armor = list(MELEE = 30, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 30, BIO = 0, RAD = 50, FIRE = 100, ACID = 100)
+ max_temperature = 25000
+ wreckage = /obj/structure/mecha_wreckage/phazon
+ internal_damage_threshold = 25
+ force = 15
+ max_equip = 3
+ phase_state = "phazon-phase"
+
+/obj/vehicle/sealed/mecha/combat/phazon/generate_actions()
+ . = ..()
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_phasing)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_switch_damtype)
diff --git a/code/game/mecha/combat/reticence.dm b/code/modules/vehicles/mecha/combat/reticence.dm
similarity index 66%
rename from code/game/mecha/combat/reticence.dm
rename to code/modules/vehicles/mecha/combat/reticence.dm
index 7343a85483..54f13e0fa9 100644
--- a/code/game/mecha/combat/reticence.dm
+++ b/code/modules/vehicles/mecha/combat/reticence.dm
@@ -1,26 +1,25 @@
-/obj/mecha/combat/reticence
+/obj/vehicle/sealed/mecha/combat/reticence
desc = "A silent, fast, and nigh-invisible miming exosuit. Popular among mimes and mime assassins."
name = "\improper reticence"
icon_state = "reticence"
- step_in = 2
+ movedelay = 2
dir_in = 1 //Facing North.
max_integrity = 100
deflect_chance = 3
- armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
+ armor = list(MELEE = 25, BULLET = 20, LASER = 30, ENERGY = 15, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
max_temperature = 15000
wreckage = /obj/structure/mecha_wreckage/reticence
operation_req_access = list(ACCESS_THEATRE)
- internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
- add_req_access = 0
+ internals_req_access = list(ACCESS_ROBOTICS, ACCESS_THEATRE)
+ mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS
internal_damage_threshold = 25
max_equip = 2
step_energy_drain = 3
color = "#87878715"
stepsound = null
turnsound = null
- opacity = 0
-/obj/mecha/combat/reticence/loaded/Initialize()
+/obj/vehicle/sealed/mecha/combat/reticence/loaded/Initialize()
. = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced
ME.attach(src)
diff --git a/code/modules/vehicles/mecha/equipment/mecha_equipment.dm b/code/modules/vehicles/mecha/equipment/mecha_equipment.dm
new file mode 100644
index 0000000000..1d104291f3
--- /dev/null
+++ b/code/modules/vehicles/mecha/equipment/mecha_equipment.dm
@@ -0,0 +1,153 @@
+//DO NOT ADD MECHA PARTS TO THE GAME WITH THE DEFAULT "SPRITE ME" SPRITE!
+//I'm annoyed I even have to tell you this! SPRITE FIRST, then commit.
+
+/obj/item/mecha_parts/mecha_equipment
+ name = "mecha equipment"
+ icon = 'icons/mecha/mecha_equipment.dmi'
+ icon_state = "mecha_equip"
+ force = 5
+ max_integrity = 300
+ var/equip_cooldown = 0
+ var/equip_ready = TRUE //whether the equipment is ready for use. (or deactivated/activated for static stuff)
+ var/energy_drain = 0
+ var/obj/vehicle/sealed/mecha/chassis = null
+ ///Bitflag. Determines the range of the equipment.
+ var/range = MECHA_MELEE
+ /// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this.
+ var/mech_flags = NONE
+ var/salvageable = 1
+ var/detachable = TRUE // Set to FALSE for built-in equipment that cannot be removed
+ var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates
+ var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist.
+ var/destroy_sound = 'sound/mecha/critdestr.ogg'
+
+/obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page()
+ if(chassis)
+ send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
+ send_byjax(chassis.occupants,"exosuit.browser","equipment_menu",chassis.get_equipment_menu(),"dropdowns")
+ return TRUE
+ return
+
+/obj/item/mecha_parts/mecha_equipment/proc/update_equip_info()
+ if(chassis)
+ send_byjax(chassis.occupants,"exosuit.browser","[REF(src)]",get_equip_info())
+ return TRUE
+ return
+
+/obj/item/mecha_parts/mecha_equipment/Destroy()
+ if(chassis)
+ LAZYREMOVE(chassis.equipment, src)
+ if(chassis.selected == src)
+ chassis.selected = null
+ update_chassis_page()
+ log_message("[src] is destroyed.", LOG_MECHA)
+ if(chassis.occupants)
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]
[src] is destroyed!")
+ playsound(chassis, destroy_sound, 50)
+ if(!detachable) //If we're a built-in nondetachable equipment, let's lock up the slot that we were in.
+ chassis.max_equip--
+ chassis = null
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
+ if(can_attach(M))
+ if(!user.temporarilyRemoveItemFromInventory(src))
+ return FALSE
+ attach(M)
+ user.visible_message("
[user] attaches [src] to [M].", "
You attach [src] to [M].")
+ return TRUE
+ to_chat(user, "
You are unable to attach [src] to [M]!")
+ return FALSE
+
+/obj/item/mecha_parts/mecha_equipment/proc/get_equip_info()
+ if(!chassis)
+ return
+ var/txt = "
* "
+ if(chassis.selected == src)
+ txt += "
[src.name]"
+ else if(selectable)
+ txt += "
[src.name]"
+ else
+ txt += "[src.name]"
+
+ return txt
+
+/obj/item/mecha_parts/mecha_equipment/proc/action_checks(atom/target)
+ if(!target)
+ return FALSE
+ if(!chassis)
+ return FALSE
+ if(!equip_ready)
+ return FALSE
+ if(energy_drain && !chassis.has_charge(energy_drain))
+ return FALSE
+ if(chassis.is_currently_ejecting)
+ return FALSE
+ if(chassis.equipment_disabled)
+ to_chat(chassis.occupants, "
Error -- Equipment control unit is unresponsive.")
+ return FALSE
+ if(TIMER_COOLDOWN_CHECK(chassis, COOLDOWN_MECHA_EQUIPMENT))
+ return FALSE
+ return TRUE
+
+/obj/item/mecha_parts/mecha_equipment/proc/action(mob/source, atom/target, params)
+ TIMER_COOLDOWN_START(chassis, COOLDOWN_MECHA_EQUIPMENT, equip_cooldown)//Cooldown is on the MECH so people dont bypass it by switching equipment
+ send_byjax(chassis.occupants,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ chassis.use_power(energy_drain)
+ return TRUE
+
+/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(atom/target, mob/user)
+ if(!chassis)
+ return FALSE
+ chassis.use_power(energy_drain)
+ return do_after(user, equip_cooldown, target, extra_checks = CALLBACK(src, .proc/do_after_checks, target))
+
+/obj/item/mecha_parts/mecha_equipment/proc/do_after_mecha(atom/target, mob/user, delay)
+ return do_after(user, delay, target, extra_checks = CALLBACK(src, .proc/do_after_checks, target))
+
+/// do after checks for the mecha equipment do afters
+/obj/item/mecha_parts/mecha_equipment/proc/do_after_checks(atom/target)
+ return chassis && (get_dir(chassis, target) & chassis.dir)
+
+/obj/item/mecha_parts/mecha_equipment/proc/can_attach(obj/vehicle/sealed/mecha/M)
+ if(LAZYLEN(M.equipment)
You start putting [target] into [src]...")
+ to_chat(source, "[icon2html(src, source)]You start putting [target] into [src]...")
chassis.visible_message("[chassis] starts putting [target] into \the [src].")
- if(do_after_cooldown(target))
- if(!patient_insertion_check(target))
+ if(do_after(source, equip_cooldown, target=target))
+ if(!chassis || src != chassis.selected || !(get_dir(chassis, target)&chassis.dir))
+ return
+ if(!patient_insertion_check(target, source))
return
target.forceMove(src)
patient = target
START_PROCESSING(SSobj, src)
update_equip_info()
- occupant_message("[target] successfully loaded into [src]. Life support functions engaged.")
+ to_chat(source, "[icon2html(src, source)][target] successfully loaded into [src]. Life support functions engaged.")
chassis.visible_message("[chassis] loads [target] into [src].")
- mecha_log_message("[target] loaded. Life support functions engaged.")
+ log_message("[target] loaded. Life support functions engaged.", LOG_MECHA)
+ return ..()
-/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target)
+/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target, mob/user)
if(target.buckled)
- occupant_message("[target] will not fit into the sleeper because [target.p_theyre()] buckled to [target.buckled]!")
+ to_chat(user, "[icon2html(src, user)][target] will not fit into the sleeper because [target.p_theyre()] 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!")
+ to_chat(user, "[icon2html(src, user)][target] will not fit into the sleeper because of the creatures attached to it!")
return
if(patient)
- occupant_message("The sleeper is already occupied!")
+ to_chat(user, "[icon2html(src, user)]The sleeper is already occupied!")
return
- return 1
+ return TRUE
/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.")
- mecha_log_message("[patient] ejected. Life support functions disabled.")
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][patient] ejected. Life support functions disabled.")
+ log_message("[patient] ejected. Life support functions disabled.", LOG_MECHA)
STOP_PROCESSING(SSobj, 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!")
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]Unable to detach [src] - equipment occupied!")
return
STOP_PROCESSING(SSobj, src)
return ..()
@@ -105,20 +107,23 @@
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)
- ..()
+ . = ..()
+ if(.)
+ return
+ if(!(usr in chassis.occupants))
+ return
if(href_list["eject"])
go_out()
if(href_list["view_stats"])
- chassis.occupant << browse(get_patient_stats(),"window=msleeper")
- onclose(chassis.occupant, "msleeper")
+ usr << browse(get_patient_stats(),"window=msleeper")
+ onclose(usr, "msleeper")
return
if(href_list["inject"])
var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG = locate() in chassis
var/datum/reagent/R = locate(href_list["inject"]) in SG.reagents.reagent_list
- if (istype(R))
+ if(istype(R))
inject_reagent(R, SG)
/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_stats()
@@ -186,7 +191,7 @@
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]
"
+ output += "Inject [R.name]
"
return output
@@ -195,9 +200,9 @@
return 0
var/to_inject = min(R.volume, inject_amount)
if(to_inject && patient.reagents.get_reagent_amount(R.type) + to_inject <= inject_amount*2)
- occupant_message("Injecting [patient] with [to_inject] units of [R.name].")
- mecha_log_message("Injecting [patient] with [to_inject] units of [R.name].")
- log_combat(chassis.occupant, patient, "injected", "[name] ([R] - [to_inject] units)")
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]Injecting [patient] with [to_inject] units of [R.name].")
+ log_message("Injecting [patient] with [to_inject] units of [R.name].", LOG_MECHA)
+ log_combat(chassis.occupants, patient, "injected", "[name] ([R] - [to_inject] units)")
SG.reagents.trans_id_to(patient,R.type,to_inject)
update_equip_info()
return
@@ -205,9 +210,9 @@
/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())
+ send_byjax(chassis.occupants,"msleeper.browser","lossinfo",get_patient_dam())
+ send_byjax(chassis.occupants,"msleeper.browser","reagents",get_patient_reagents())
+ send_byjax(chassis.occupants,"msleeper.browser","injectwith",get_available_reagents())
return 1
return
@@ -218,9 +223,8 @@
if(..())
return
if(!chassis.has_charge(energy_drain))
- set_ready_state(1)
- mecha_log_message("Deactivated.")
- occupant_message("[src] deactivated - no power.")
+ log_message("Deactivated.", LOG_MECHA)
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][src] deactivated - no power.")
STOP_PROCESSING(SSobj, src)
return
var/mob/living/carbon/M = patient
@@ -228,7 +232,10 @@
return
if(M.health > 0)
M.adjustOxyLoss(-1)
- M.AdjustAllImmobility(-80)
+ M.AdjustStun(-80)
+ M.AdjustKnockdown(-80)
+ M.AdjustParalyzed(-80)
+ M.AdjustImmobilized(-80)
M.AdjustUnconscious(-80)
if(M.reagents.get_reagent_amount(/datum/reagent/medicine/epinephrine) < 5)
M.reagents.add_reagent(/datum/reagent/medicine/epinephrine, 5)
@@ -254,15 +261,14 @@
var/synth_speed = 5 //[num] reagent units per cycle
energy_drain = 10
var/mode = 0 //0 - fire syringe, 1 - analyze reagents.
- range = MELEE|RANGED
+ range = MECHA_MELEE|MECHA_RANGED
equip_cooldown = 10
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Initialize()
. = ..()
create_reagents(max_volume, NO_REACT)
syringes = new
- known_reagents = list(/datum/reagent/medicine/epinephrine = "Epinephrine", /datum/reagent/medicine/charcoal = "Charcoal", /datum/reagent/medicine/prussian_blue = "Prussian Blue", \
- /datum/reagent/medicine/dexalin = "Dexalin", /datum/reagent/medicine/insulin = "Insulin", /datum/reagent/medicine/kelotane = "Kelotane", /datum/reagent/medicine/bicaridine = "Bicaridine")
+ known_reagents = list(/datum/reagent/medicine/epinephrine="Epinephrine")
processed_reagents = new
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/detach()
@@ -273,39 +279,35 @@
STOP_PROCESSING(SSobj, src)
return ..()
-/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/critfail()
- ..()
- if(reagents)
- reagents.reagents_holder_flags &= ~(NO_REACT)
-
-/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/can_attach(obj/vehicle/sealed/mecha/medical/M)
+ . = ..()
+ if(!istype(M))
+ return FALSE
/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)
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/action(mob/source, atom/movable/target, params)
if(!action_checks(target))
return
if(istype(target, /obj/item/reagent_containers/syringe))
return load_syringe(target)
if(istype(target, /obj/item/storage))//Loads syringes from boxes
for(var/obj/item/reagent_containers/syringe/S in target.contents)
- load_syringe(S)
+ load_syringe(S, source)
return
if(mode)
- return analyze_reagents(target)
+ return analyze_reagents(target, source)
if(!syringes.len)
- occupant_message("No syringes loaded.")
+ to_chat(source, "[icon2html(src, source)]No syringes loaded.")
return
if(reagents.total_volume<=0)
- occupant_message("No available reagents to load syringe with.")
+ to_chat(source, "[icon2html(src, source)]No available reagents to load syringe with.")
+ return
+ if(HAS_TRAIT(source, TRAIT_PACIFISM))
+ to_chat(source, "The [src] is lethally chambered! You don't want to risk harming anyone...")
return
var/turf/trg = get_turf(target)
var/obj/item/reagent_containers/syringe/mechsyringe = syringes[1]
@@ -314,11 +316,9 @@
syringes -= mechsyringe
mechsyringe.icon = 'icons/obj/chemical.dmi'
mechsyringe.icon_state = "syringeproj"
- playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
- mecha_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
+ playsound(chassis, 'sound/items/syringeproj.ogg', 50, TRUE)
+ log_message("Launched [mechsyringe] from [src] by [source], targeting [target].", LOG_MECHA)
+ spawn(0) //This code is trash and whoever wrote it should feel bad
for(var/i=0, i<6, i++)
if(!mechsyringe)
break
@@ -326,10 +326,10 @@
var/list/mobs = new
for(var/mob/living/carbon/M in mechsyringe.loc)
mobs += M
- var/mob/living/carbon/M = safepick(mobs)
- if(M)
+ if(length(mobs))
+ var/mob/living/carbon/M = pick(mobs)
var/R
- mechsyringe.visible_message(" [M] was hit by the syringe!")
+ mechsyringe.visible_message(" [M] is hit by the syringe!")
if(M.can_inject(null, 1))
if(mechsyringe.reagents)
for(var/datum/reagent/A in mechsyringe.reagents.reagent_list)
@@ -337,9 +337,9 @@
mechsyringe.icon_state = initial(mechsyringe.icon_state)
mechsyringe.icon = initial(mechsyringe.icon)
mechsyringe.reagents.reaction(M, INJECT)
- mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume)
+ mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume, log = TRUE)
M.take_bodypart_damage(2)
- log_combat(originaloccupant, M, "shot", "syringegun")
+ log_combat(source, M, "shot", "syringegun")
break
else if(mechsyringe.loc == trg)
mechsyringe.icon_state = initial(mechsyringe.icon_state)
@@ -352,7 +352,7 @@
mechsyringe.update_icon()
break
sleep(1)
- return 1
+ return ..()
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Topic(href,href_list)
@@ -376,12 +376,14 @@
if(processed_reagents.len)
message += " added to production"
START_PROCESSING(SSobj, src)
- occupant_message(message)
- occupant_message("Reagent processing started.")
- mecha_log_message("Reagent processing started.")
+ to_chat(usr, message)
+ to_chat(usr, "[icon2html(src, usr)]Reagent processing started.")
+ log_message("Reagent processing started.", LOG_MECHA)
return
if (href_list["show_reagents"])
- chassis.occupant << browse(get_reagents_page(),"window=msyringegun")
+ if(!(usr in chassis.occupants))
+ return
+ usr << browse(get_reagents_page(),"window=msyringegun")
if (href_list["purge_reagent"])
var/reagent = href_list["purge_reagent"]
if(reagent)
@@ -445,74 +447,72 @@
var/output
for(var/datum/reagent/R in reagents.reagent_list)
if(R.volume > 0)
- output += "[R]: [round(R.volume,0.001)] - Purge Reagent
"
+ 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/reagent_containers/syringe/S)
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/load_syringe(obj/item/reagent_containers/syringe/S, mob/user)
if(syringes.len= 2)
- occupant_message("The syringe is too far away.")
+ to_chat(user, "[icon2html(src, user)]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.")
+ to_chat(user, "[icon2html(src, user)]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.")
+ to_chat(user, "[icon2html(src, user)]Unable to load syringe!")
return 0
S.reagents.trans_to(src, S.reagents.total_volume)
S.forceMove(src)
syringes += S
- occupant_message("Syringe loaded.")
+ to_chat(user, "[icon2html(src, user)]Syringe loaded.")
update_equip_info()
return 1
- occupant_message("[src]'s syringe chamber is full.")
+ to_chat(user, "[icon2html(src, user)][src]'s syringe chamber is full!")
return 0
-/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/analyze_reagents(atom/A)
+/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/analyze_reagents(atom/A, mob/user)
if(get_dist(src,A) >= 4)
- occupant_message("The object is too far away.")
- return 0
+ to_chat(user, "[icon2html(src, user)]The object is too far away!")
+ return FALSE
if(!A.reagents || ismob(A))
- occupant_message("No reagent info gained from [A].")
- return 0
- occupant_message("Analyzing reagents...")
+ to_chat(user, "[icon2html(src, user)]No reagent info gained from [A].")
+ return FALSE
+ to_chat(user, "[icon2html(src, user)]Analyzing reagents...")
for(var/datum/reagent/R in A.reagents.reagent_list)
if(R.can_synth && add_known_reagent(R.type,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
+ to_chat(user, "[icon2html(src, user)]Reagent analyzed, identified as [R.name] and added to database.")
+ send_byjax(chassis.occupants,"msyringegun.browser","reagents_form",get_reagents_form())
+ to_chat(user, "[icon2html(src, user)]Analysis complete.")
+ return TRUE
/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
+ return TRUE
+ return FALSE
/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
+ send_byjax(chassis.occupants,"msyringegun.browser","reagents",get_current_reagents())
+ send_byjax(chassis.occupants,"msyringegun.browser","reagents_form",get_reagents_form())
+ return TRUE
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/on_reagent_change(changetype)
..()
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.")
- mecha_log_message("Reagent processing stopped.")
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]Reagent processing stopped.")
+ log_message("Reagent processing stopped.", LOG_MECHA)
STOP_PROCESSING(SSobj, src)
return
var/amount = synth_speed / processed_reagents.len
@@ -527,7 +527,7 @@
desc = "Equipment for medical exosuits. Generates a focused beam of medical nanites."
icon_state = "mecha_medigun"
energy_drain = 10
- range = MELEE|RANGED
+ range = MECHA_MELEE|MECHA_RANGED
equip_cooldown = 0
var/obj/item/gun/medbeam/mech/medigun
custom_materials = list(/datum/material/iron = 15000, /datum/material/glass = 8000, /datum/material/plasma = 3000, /datum/material/gold = 8000, /datum/material/diamond = 2000)
@@ -546,7 +546,7 @@
return
medigun.process()
-/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/action(atom/target)
+/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/action(mob/source, atom/movable/target, params)
medigun.process_fire(target, loc)
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm
similarity index 70%
rename from code/game/mecha/equipment/tools/mining_tools.dm
rename to code/modules/vehicles/mecha/equipment/tools/mining_tools.dm
index 47820d1e27..80a3c050a5 100644
--- a/code/game/mecha/equipment/tools/mining_tools.dm
+++ b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm
@@ -13,6 +13,7 @@
energy_drain = 10
force = 15
harmful = TRUE
+ range = MECHA_MELEE
tool_behaviour = TOOL_DRILL
toolspeed = 0.9
var/drill_delay = 7
@@ -23,7 +24,7 @@
. = ..()
AddComponent(/datum/component/butchering, 50, 100, null, null, TRUE)
-/obj/item/mecha_parts/mecha_equipment/drill/action(atom/target)
+/obj/item/mecha_parts/mecha_equipment/drill/action(mob/source, atom/target, params)
if(!action_checks(target))
return
if(isspaceturf(target))
@@ -34,72 +35,69 @@
return
target.visible_message("[chassis] starts to drill [target].", \
"[chassis] starts to drill [target]...", \
- "You hear drilling.")
+ "You hear drilling.")
- if(do_after_cooldown(target))
- set_ready_state(FALSE)
- mecha_log_message("Started drilling [target]")
+ if(do_after_cooldown(target, source))
+ log_message("Started drilling [target]", LOG_MECHA)
if(isturf(target))
var/turf/T = target
- T.drill_act(src)
- set_ready_state(TRUE)
+ T.drill_act(src, source)
return
- while(do_after_mecha(target, drill_delay))
+ while(do_after_mecha(target, source, drill_delay))
if(isliving(target))
- drill_mob(target, chassis.occupant)
- playsound(src,'sound/weapons/drill.ogg',40,1)
+ drill_mob(target, source)
+ playsound(src,'sound/weapons/drill.ogg',40,TRUE)
else if(isobj(target))
var/obj/O = target
O.take_damage(15, BRUTE, 0, FALSE, get_dir(chassis, target))
- playsound(src,'sound/weapons/drill.ogg',40,1)
+ playsound(src,'sound/weapons/drill.ogg',40,TRUE)
else
- set_ready_state(TRUE)
return
- set_ready_state(TRUE)
+ return ..()
-/turf/proc/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+/turf/proc/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill, mob/user)
return
-/turf/closed/wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
- if(drill.do_after_mecha(src, 60 / drill.drill_level))
- drill.mecha_log_message("Drilled through [src]")
+/turf/closed/wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill, mob/user)
+ if(drill.do_after_mecha(src, user, 60 / drill.drill_level))
+ drill.log_message("Drilled through [src]", LOG_MECHA)
dismantle_wall(TRUE, FALSE)
-/turf/closed/wall/r_wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+/turf/closed/wall/r_wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill, mob/user)
if(drill.drill_level >= DRILL_HARDENED)
- if(drill.do_after_mecha(src, 120 / drill.drill_level))
- drill.mecha_log_message("Drilled through [src]")
+ if(drill.do_after_mecha(src, user, 120 / drill.drill_level))
+ drill.log_message("Drilled through [src]", LOG_MECHA)
dismantle_wall(TRUE, FALSE)
else
- drill.occupant_message("[src] is too durable to drill through.")
+ to_chat(user, "[icon2html(src, user)][src] is too durable to drill through.")
-/turf/closed/mineral/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
+/turf/closed/mineral/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill, mob/user)
for(var/turf/closed/mineral/M in range(drill.chassis,1))
if(get_dir(drill.chassis,M)&drill.chassis.dir)
M.gets_drilled()
- drill.mecha_log_message("Drilled through [src]")
+ drill.log_message("[user] drilled through [src]", LOG_MECHA)
drill.move_ores()
/turf/open/floor/plating/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
for(var/turf/open/floor/plating/asteroid/M in range(1, drill.chassis))
if((get_dir(drill.chassis,M)&drill.chassis.dir) && !M.dug)
M.getDug()
- drill.mecha_log_message("Drilled through [src]")
+ drill.log_message("Drilled through [src]", LOG_MECHA)
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 && istype(chassis, /obj/mecha/working/ripley))
- var/obj/mecha/working/ripley/R = chassis //we could assume that it's a ripley because it has a clamp, but that's ~unsafe~ and ~bad practice~
+ if(locate(/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) in chassis.equipment && istype(chassis, /obj/vehicle/sealed/mecha/working/ripley))
+ var/obj/vehicle/sealed/mecha/working/ripley/R = chassis //we could assume that it's a ripley because it has a clamp, but that's ~unsafe~ and ~bad practice~
R.collect_ore()
-/obj/item/mecha_parts/mecha_equipment/drill/can_attach(obj/mecha/M as obj)
+/obj/item/mecha_parts/mecha_equipment/drill/can_attach(obj/vehicle/sealed/mecha/M as obj)
if(..())
- if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat))
- return 1
- return 0
+ if(istype(M, /obj/vehicle/sealed/mecha/working) || istype(M, /obj/vehicle/sealed/mecha/combat))
+ return TRUE
+ return FALSE
-/obj/item/mecha_parts/mecha_equipment/drill/attach(obj/mecha/M)
+/obj/item/mecha_parts/mecha_equipment/drill/attach(obj/vehicle/sealed/mecha/M)
..()
var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = TRUE
@@ -123,7 +121,7 @@
else
//drill makes a hole
var/obj/item/bodypart/target_part = target.get_bodypart(ran_zone(BODY_ZONE_CHEST))
- target.apply_damage(10, BRUTE, BODY_ZONE_CHEST, target.run_armor_check(target_part, "melee"))
+ target.apply_damage(10, BRUTE, BODY_ZONE_CHEST, target.run_armor_check(target_part, MELEE))
//blood splatters
var/splatter_dir = get_dir(chassis, target)
@@ -153,7 +151,7 @@
/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."
+ desc = "Equipment for working exosuits. It will automatically check surrounding rock for useful minerals."
icon_state = "mecha_analyzer"
selectable = 0
equip_cooldown = 15
@@ -164,13 +162,19 @@
. = ..()
START_PROCESSING(SSfastprocess, src)
+/obj/item/mecha_parts/mecha_equipment/mining_scanner/can_attach(obj/vehicle/sealed/mecha/M as obj)
+ if(..())
+ if(istype(M, /obj/vehicle/sealed/mecha/working))
+ return TRUE
+ return FALSE
+
/obj/item/mecha_parts/mecha_equipment/mining_scanner/process()
if(!loc)
STOP_PROCESSING(SSfastprocess, src)
qdel(src)
- if(istype(loc, /obj/mecha/working) && scanning_time <= world.time)
- var/obj/mecha/working/mecha = loc
- if(!mecha.occupant)
+ if(istype(loc, /obj/vehicle/sealed/mecha/working) && scanning_time <= world.time)
+ var/obj/vehicle/sealed/mecha/working/mecha = loc
+ if(!mecha.occupants)
return
scanning_time = world.time + equip_cooldown
mineral_scan_pulse(get_turf(src))
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
similarity index 58%
rename from code/game/mecha/equipment/tools/other_tools.dm
rename to code/modules/vehicles/mecha/equipment/tools/other_tools.dm
index e1861232f4..30642db926 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm
@@ -10,15 +10,16 @@
icon_state = "mecha_teleport"
equip_cooldown = 150
energy_drain = 1000
- range = RANGED
+ range = MECHA_RANGED
+ var/teleport_range = 7
-/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target)
+/obj/item/mecha_parts/mecha_equipment/teleporter/action(mob/source, atom/target, params)
if(!action_checks(target) || is_centcom_level(loc.z))
return
var/turf/T = get_turf(target)
- if(T)
+ if(T && (loc.z == T.z) && (get_dist(loc, T) <= teleport_range))
do_teleport(chassis, T, 4, channel = TELEPORT_CHANNEL_BLUESPACE)
- return 1
+ return ..()
@@ -30,10 +31,10 @@
icon_state = "mecha_wholegen"
equip_cooldown = 50
energy_drain = 300
- range = RANGED
+ range = MECHA_RANGED
-/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target)
+/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(mob/source, atom/target, params)
if(!action_checks(target) || is_centcom_level(loc.z))
return
var/list/theareas = get_areas_in_range(100, chassis)
@@ -44,10 +45,10 @@
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
+ var/clear = TRUE
for(var/obj/O in T)
if(O.density)
- clear = 0
+ clear = FALSE
break
if(clear)
L+=T
@@ -58,11 +59,11 @@
return
var/list/obj/effect/portal/created = create_portal_pair(get_turf(src), target_turf, 300, 1, /obj/effect/portal/anom)
var/turf/T = get_turf(target)
- message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] used a Wormhole Generator in [ADMIN_VERBOSEJMP(T)]")
- log_game("[key_name(chassis.occupant)] used a Wormhole Generator in [AREACOORD(T)]")
+ message_admins("[ADMIN_LOOKUPFLW(source)] used a Wormhole Generator in [ADMIN_VERBOSEJMP(T)]")
+ log_game("[key_name(source)] used a Wormhole Generator in [AREACOORD(T)]")
src = null
QDEL_LIST_IN(created, rand(150,300))
- return 1
+ return ..()
/////////////////////////////////////// GRAVITATIONAL CATAPULT ///////////////////////////////////////////
@@ -73,36 +74,41 @@
icon_state = "mecha_teleport"
equip_cooldown = 10
energy_drain = 100
- range = MELEE|RANGED
+ range = MECHA_MELEE|MECHA_RANGED
var/atom/movable/locked
var/mode = 1 //1 - gravsling 2 - gravpush
-/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target)
+/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(mob/source, atom/movable/target, params)
if(!action_checks(target))
return
switch(mode)
if(1)
if(!locked)
if(!istype(target) || target.anchored || target.move_resist >= MOVE_FORCE_EXTREMELY_STRONG)
- occupant_message("Unable to lock on [target]")
+ to_chat(source, "[icon2html(src, source)]Unable to lock on [target]!")
return
+ if(ismob(target))
+ var/mob/M = target
+ if(M.mob_negates_gravity())
+ to_chat(source, "[icon2html(src, source)]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())
+ to_chat(source, "[icon2html(src, source)]Locked on [target].")
+ send_byjax(source,"exosuit.browser","[REF(src)]",src.get_equip_info())
else if(target!=locked)
if(locked in view(chassis))
var/turf/targ = get_turf(target)
var/turf/orig = get_turf(locked)
locked.throw_at(target, 14, 1.5)
locked = null
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
- log_game("[key_name(chassis.occupant)] used a Gravitational Catapult to throw [locked] (From [AREACOORD(orig)]) at [target] ([AREACOORD(targ)]).")
- return TRUE
+ send_byjax(source,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ log_game("[key_name(source)] used a Gravitational Catapult to throw [locked] (From [AREACOORD(orig)]) at [target] ([AREACOORD(targ)]).")
+ return ..()
else
locked = null
- occupant_message("Lock on [locked] disengaged.")
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ to_chat(source, "[icon2html(src, source)]Lock on [locked] disengaged.")
+ send_byjax(source,"exosuit.browser","[REF(src)]",src.get_equip_info())
if(2)
var/list/atoms = list()
if(isturf(target))
@@ -112,15 +118,21 @@
for(var/atom/movable/A in atoms)
if(A.anchored || A.move_resist >= MOVE_FORCE_EXTREMELY_STRONG)
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("[key_name(chassis.occupant)] used a Gravitational Catapult repulse wave on [AREACOORD(T)]")
- return TRUE
+ if(ismob(A))
+ var/mob/M = A
+ if(M.mob_negates_gravity())
+ continue
+ INVOKE_ASYNC(src, .proc/do_scatter, A, target)
+ var/turf/T = get_turf(target)
+ log_game("[key_name(source)] used a Gravitational Catapult repulse wave on [AREACOORD(T)]")
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/gravcatapult/proc/do_scatter(atom/movable/A, atom/movable/target)
+ var/iter = 5-get_dist(A,target)
+ for(var/i in 0 to iter)
+ step_away(A,target)
+ sleep(2)
/obj/item/mecha_parts/mecha_equipment/gravcatapult/get_equip_info()
return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]"
@@ -129,7 +141,7 @@
..()
if(href_list["mode"])
mode = text2num(href_list["mode"])
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ send_byjax(chassis.occupants,"exosuit.browser","[REF(src)]",src.get_equip_info())
return
@@ -150,9 +162,10 @@
selectable = 0
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/proc/attack_react()
- if(action_checks(src))
- start_cooldown()
- return 1
+ if(energy_drain && !chassis.has_charge(energy_drain))
+ return FALSE
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_ARMOR, equip_cooldown)
+ return TRUE
@@ -168,9 +181,10 @@
selectable = 0
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/projectile_react()
- if(action_checks(src))
- start_cooldown()
- return 1
+ if(energy_drain && !chassis.has_charge(energy_drain))
+ return FALSE
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_ARMOR, equip_cooldown)
+ return TRUE
////////////////////////////////// REPAIR DROID //////////////////////////////////////////////////
@@ -193,7 +207,7 @@
chassis.cut_overlay(droid_overlay)
return ..()
-/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M as obj)
+/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/vehicle/sealed/mecha/M)
..()
droid_overlay = new(src.icon, icon_state = "repair_droid")
M.add_overlay(droid_overlay)
@@ -216,21 +230,18 @@
if(equip_ready)
START_PROCESSING(SSobj, src)
droid_overlay = new(src.icon, icon_state = "repair_droid_a")
- mecha_log_message("Activated.")
- set_ready_state(0)
+ log_message("Activated.", LOG_MECHA)
else
STOP_PROCESSING(SSobj, src)
droid_overlay = new(src.icon, icon_state = "repair_droid")
- mecha_log_message("Deactivated.")
- set_ready_state(1)
+ log_message("Deactivated.", LOG_MECHA)
chassis.add_overlay(droid_overlay)
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ send_byjax(chassis.occupants,"exosuit.browser", "[REF(src)]", get_equip_info())
/obj/item/mecha_parts/mecha_equipment/repair_droid/process()
if(!chassis)
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
return
var/h_boost = health_boost
var/repaired = 0
@@ -242,16 +253,14 @@
chassis.clearInternalDamage(int_dam_flag)
repaired = 1
break
- if(health_boost<0 || chassis.obj_integrity < chassis.max_integrity)
- chassis.obj_integrity += min(health_boost, chassis.max_integrity-chassis.obj_integrity)
+ if(h_boost<0 || chassis.obj_integrity < chassis.max_integrity)
+ chassis.obj_integrity += min(h_boost, chassis.max_integrity-chassis.obj_integrity)
repaired = 1
if(repaired)
if(!chassis.use_power(energy_drain))
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
else //no repair needed, we turn off
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
chassis.cut_overlay(droid_overlay)
droid_overlay = new(src.icon, icon_state = "repair_droid")
chassis.add_overlay(droid_overlay)
@@ -284,12 +293,12 @@
if(equip_ready) //disabled
return
var/area/A = get_area(chassis)
- var/pow_chan = get_MUTATION_POWER_channel(A)
+ var/pow_chan = GET_MUTATION_POWER_channel(A)
if(pow_chan)
return 1000 //making magic
-/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_MUTATION_POWER_channel(var/area/A)
+/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/GET_MUTATION_POWER_channel(area/A)
var/pow_chan
if(A)
for(var/c in use_channels)
@@ -303,12 +312,10 @@
if(href_list["toggle_relay"])
if(equip_ready) //inactive
START_PROCESSING(SSobj, src)
- set_ready_state(0)
- mecha_log_message("Activated.")
+ log_message("Activated.", LOG_MECHA)
else
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
- mecha_log_message("Deactivated.")
+ log_message("Deactivated.", LOG_MECHA)
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info()
if(!chassis)
@@ -319,19 +326,17 @@
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/process()
if(!chassis || chassis.internal_damage & MECHA_INT_SHORT_CIRCUIT)
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
return
var/cur_charge = chassis.get_charge()
if(isnull(cur_charge) || !chassis.cell)
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
- occupant_message("No powercell detected.")
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]No power cell detected.")
return
if(cur_charge < chassis.cell.maxcharge)
- var/area/A = get_base_area(chassis)
+ var/area/A = get_area(chassis)
if(A)
var/pow_chan
- for(var/c in list(EQUIP,ENVIRON,LIGHT))
+ for(var/c in use_channels)
if(A.powered(c))
pow_chan = c
break
@@ -350,7 +355,7 @@
name = "exosuit plasma converter"
desc = "An exosuit module that generates power using solid plasma as fuel. Pollutes the environment."
icon_state = "tesla"
- range = MELEE
+ range = MECHA_MELEE
var/coeff = 100
var/obj/item/stack/sheet/fuel
var/max_fuel = 150000
@@ -377,77 +382,54 @@
..()
if(href_list["toggle"])
if(equip_ready) //inactive
- set_ready_state(0)
START_PROCESSING(SSobj, src)
- mecha_log_message("Activated.")
+ log_message("Activated.", LOG_MECHA)
else
- set_ready_state(1)
STOP_PROCESSING(SSobj, src)
- mecha_log_message("Deactivated.")
+ log_message("Deactivated.", LOG_MECHA)
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
var/output = ..()
if(output)
return "[output] \[[fuel]: [round(fuel.amount*MINERAL_MATERIAL_AMOUNT,0.1)] cm3\] - [equip_ready?"A":"Dea"]ctivate"
-/obj/item/mecha_parts/mecha_equipment/generator/action(target)
+/obj/item/mecha_parts/mecha_equipment/generator/action(mob/source, atom/movable/target, params)
if(chassis)
- var/result = load_fuel(target)
- if(result)
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ if(load_fuel(target, source))
+ send_byjax(chassis.occupants,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ return ..()
-/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P)
+/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(obj/item/stack/sheet/P, mob/user)
if(P.type == fuel.type && P.amount > 0)
var/to_load = max(max_fuel - fuel.amount*MINERAL_MATERIAL_AMOUNT,0)
if(to_load)
var/units = min(max(round(to_load / MINERAL_MATERIAL_AMOUNT),1),P.amount)
fuel.amount += units
P.use(units)
- occupant_message("[units] unit\s of [fuel] successfully loaded.")
+ to_chat(user, "[icon2html(src, user)][units] unit\s of [fuel] successfully loaded.")
return units
else
- occupant_message("Unit is full.")
+ to_chat(user, "[icon2html(src, user)]Unit is full.")
return 0
else
- occupant_message("[fuel] traces in target minimal! [P] cannot be used as fuel.")
+ to_chat(user, "[icon2html(src, user)][fuel] traces in target minimal! [P] cannot be used as fuel.")
return
/obj/item/mecha_parts/mecha_equipment/generator/attackby(weapon,mob/user, params)
load_fuel(weapon)
-/obj/item/mecha_parts/mecha_equipment/generator/critfail()
- ..()
- var/turf/open/T = get_turf(src)
- if(!istype(T))
- return
- var/datum/gas_mixture/GM = new
- if(prob(10))
- GM.adjust_moles(GAS_PLASMA,100)
- GM.set_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.adjust_moles(GAS_PLASMA,5)
- GM.set_temperature(istype(T) ? T.air.return_temperature() : T20C)
- T.visible_message("[src] suddenly disgorges a cloud of plasma.")
- T.assume_air(GM)
- return
-
/obj/item/mecha_parts/mecha_equipment/generator/process()
if(!chassis)
STOP_PROCESSING(SSobj, src)
- set_ready_state(1)
return
if(fuel.amount<=0)
STOP_PROCESSING(SSobj, src)
- mecha_log_message("Deactivated - no fuel.")
- set_ready_state(1)
+ log_message("Deactivated - no fuel.", LOG_MECHA)
return
var/cur_charge = chassis.get_charge()
if(isnull(cur_charge))
- set_ready_state(1)
- occupant_message("No powercell detected.")
- mecha_log_message("Deactivated.")
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]No power cell detected.")
+ log_message("Deactivated.", LOG_MECHA)
STOP_PROCESSING(SSobj, src)
return
var/use_fuel = fuel_per_cycle_idle
@@ -456,7 +438,7 @@
chassis.give_power(power_per_cycle)
fuel.amount -= min(use_fuel/MINERAL_MATERIAL_AMOUNT,fuel.amount)
update_equip_info()
- return 1
+ return TRUE
/obj/item/mecha_parts/mecha_equipment/generator/nuclear
@@ -472,9 +454,118 @@
/obj/item/mecha_parts/mecha_equipment/generator/nuclear/generator_init()
fuel = new /obj/item/stack/sheet/mineral/uranium(src, 0)
-/obj/item/mecha_parts/mecha_equipment/generator/nuclear/critfail()
- return
-
/obj/item/mecha_parts/mecha_equipment/generator/nuclear/process()
if(..())
radiation_pulse(get_turf(src), rad_per_cycle)
+
+
+/////////////////////////////////////////// THRUSTERS /////////////////////////////////////////////
+
+/obj/item/mecha_parts/mecha_equipment/thrusters
+ name = "generic exosuit thrusters" //parent object, in-game sources will be a child object
+ desc = "A generic set of thrusters, from an unknown source. Uses not-understood methods to propel exosuits seemingly for free."
+ icon_state = "thrusters"
+ selectable = FALSE
+ var/effect_type = /obj/effect/particle_effect/sparks
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
+ for(var/obj/item/I in M.equipment)
+ if(istype(I, src))
+ to_chat(user, "[M] already has this thruster package!")
+ return FALSE
+ . = ..()
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/attach(obj/vehicle/sealed/mecha/M)
+ M.active_thrusters = src //Enable by default
+ . = ..()
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/detach()
+ if(chassis?.active_thrusters == src)
+ chassis.active_thrusters = null
+ . = ..()
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/Destroy()
+ if(chassis?.active_thrusters == src)
+ chassis.active_thrusters = null
+ . = ..()
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/Topic(href,href_list)
+ ..()
+ if(!chassis)
+ return
+ if(href_list["mode"])
+ var/mode = text2num(href_list["mode"])
+ switch(mode)
+ if(0)
+ enable()
+ if(1)
+ disable()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/proc/enable()
+ if (chassis.active_thrusters == src)
+ return
+ chassis.active_thrusters = src
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][src] enabled.")
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/proc/disable()
+ if(chassis.active_thrusters != src)
+ return
+ chassis.active_thrusters = null
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][src] disabled.")
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/get_equip_info()
+ return "[..()] \[Enable|Disable\]"
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/proc/thrust(movement_dir)
+ if(!chassis)
+ return FALSE
+ generate_effect(movement_dir)
+ return TRUE //This parent should never exist in-game outside admeme use, so why not let it be a creative thruster?
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/proc/generate_effect(movement_dir)
+ var/obj/effect/particle_effect/E = new effect_type(get_turf(chassis))
+ E.dir = turn(movement_dir, 180)
+ step(E, turn(movement_dir, 180))
+ QDEL_IN(E, 5)
+
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/gas
+ name = "RCS thruster package"
+ desc = "A set of thrusters that allow for exosuit movement in zero-gravity environments, by expelling gas from the internal life support tank."
+ effect_type = /obj/effect/particle_effect/smoke
+ var/move_cost = 20 //moles per step
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/gas/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
+ if(!M.internal_tank)
+ to_chat(user, "[M] does not have an internal tank and cannot support this upgrade!")
+ return FALSE
+ . = ..()
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/gas/thrust(movement_dir)
+ if(!chassis || !chassis.internal_tank)
+ return FALSE
+ var/moles = chassis.internal_tank.air_contents.total_moles()
+ if(moles < move_cost)
+ chassis.internal_tank.air_contents.remove(moles)
+ return FALSE
+ chassis.internal_tank.air_contents.remove(move_cost)
+ generate_effect(movement_dir)
+ return TRUE
+
+
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/ion //for mechs with built-in thrusters, should never really exist un-attached to a mech
+ name = "Ion thruster package"
+ desc = "A set of thrusters that allow for exosuit movement in zero-gravity environments."
+ detachable = FALSE
+ salvageable = FALSE
+ effect_type = /obj/effect/particle_effect/ion_trails
+
+/obj/item/mecha_parts/mecha_equipment/thrusters/ion/thrust(movement_dir)
+ if(!chassis)
+ return FALSE
+ if(chassis.use_power(chassis.step_energy_drain))
+ generate_effect(movement_dir)
+ return TRUE
+ return FALSE
diff --git a/code/modules/vehicles/mecha/equipment/tools/weapon_bay.dm b/code/modules/vehicles/mecha/equipment/tools/weapon_bay.dm
new file mode 100644
index 0000000000..469d430328
--- /dev/null
+++ b/code/modules/vehicles/mecha/equipment/tools/weapon_bay.dm
@@ -0,0 +1,14 @@
+/obj/item/mecha_parts/concealed_weapon_bay
+ name = "concealed weapon bay"
+ desc = "A compartment that allows a non-combat mecha to equip one weapon while hiding the weapon from plain sight."
+ icon = 'icons/mecha/mecha_equipment.dmi'
+ icon_state = "mecha_weapon_bay"
+
+/obj/item/mecha_parts/concealed_weapon_bay/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
+ if(istype(M, /obj/vehicle/sealed/mecha/combat))
+ to_chat(user, "[M] can already hold weapons!")
+ return
+ if(locate(/obj/item/mecha_parts/concealed_weapon_bay) in M.contents)
+ to_chat(user, "[M] already has a concealed weapon bay!")
+ return
+ ..()
diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm
new file mode 100644
index 0000000000..d3d4c8addc
--- /dev/null
+++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm
@@ -0,0 +1,410 @@
+
+//Hydraulic clamp, Kill clamp, Extinguisher, RCD, Cable layer.
+
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp
+ name = "hydraulic clamp"
+ desc = "Equipment for engineering exosuits. Lifts objects and loads them into cargo."
+ icon_state = "mecha_clamp"
+ equip_cooldown = 15
+ energy_drain = 10
+ tool_behaviour = TOOL_RETRACTOR
+ range = MECHA_MELEE
+ toolspeed = 0.8
+ var/dam_force = 20
+ var/obj/vehicle/sealed/mecha/working/ripley/cargo_holder
+ harmful = TRUE
+ mech_flags = EXOSUIT_MODULE_RIPLEY
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/vehicle/sealed/mecha/working/ripley/M)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/attach(obj/vehicle/sealed/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(mob/source, atom/target, params)
+ if(!action_checks(target))
+ return
+ if(!cargo_holder)
+ return
+ if(ismecha(target))
+ var/obj/vehicle/sealed/mecha/M = target
+ var/have_ammo
+ for(var/obj/item/mecha_ammo/box in cargo_holder.cargo)
+ if(istype(box, /obj/item/mecha_ammo) && box.rounds)
+ have_ammo = TRUE
+ if(M.ammo_resupply(box, source, TRUE))
+ return
+ if(have_ammo)
+ to_chat(source, "No further supplies can be provided to [M].")
+ else
+ to_chat(source, "No providable supplies found in cargo hold")
+ return
+ if(isobj(target))
+ var/obj/O = target
+ if(istype(O, /obj/machinery/door/firedoor))
+ var/obj/machinery/door/firedoor/D = O
+ D.try_to_crowbar(src, source)
+ return
+ if(istype(O, /obj/machinery/door/airlock/))
+ var/obj/machinery/door/airlock/D = O
+ D.try_to_crowbar(src, source)
+ return
+ 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.set_anchored(TRUE)
+ if(do_after_cooldown(target, source))
+ cargo_holder.cargo += O
+ O.forceMove(chassis)
+ O.set_anchored(FALSE)
+ to_chat(source, "[icon2html(src, source)][target] successfully loaded.")
+ log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]", LOG_MECHA)
+ else
+ O.set_anchored(initial(O.anchored))
+ else
+ to_chat(source, "[icon2html(src, source)]Not enough room in cargo compartment!")
+ else
+ to_chat(source, "[icon2html(src, source)][target] is firmly secured!")
+
+ else if(isliving(target))
+ var/mob/living/M = target
+ if(M.stat == DEAD)
+ return
+ if(source.a_intent == INTENT_HARM)
+ M.take_overall_damage(dam_force)
+ if(!M)
+ return
+ M.adjustOxyLoss(round(dam_force/2))
+ M.updatehealth()
+ target.visible_message("[chassis] squeezes [target]!", \
+ "[chassis] squeezes you!",\
+ "You hear something crack.")
+ log_combat(source, M, "attacked", "[name]", "(INTENT: [uppertext(source.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
+ else
+ step_away(M,chassis)
+ to_chat(source, "[icon2html(src, source)]You push [target] out of the way.")
+ chassis.visible_message("[chassis] pushes [target] out of the way.")
+ return ..()
+
+
+
+//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
+ dam_force = 0
+ var/real_clamp = FALSE
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill/real
+ desc = "They won't know what clamped them! This time for real!"
+ energy_drain = 10
+ dam_force = 20
+ real_clamp = TRUE
+
+/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill/action(mob/source, atom/target, params)
+ if(!action_checks(target))
+ return
+ if(!cargo_holder)
+ return
+ if(isobj(target))
+ 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.set_anchored(TRUE)
+ if(do_after_cooldown(target, source))
+ cargo_holder.cargo += O
+ O.forceMove(chassis)
+ O.set_anchored(FALSE)
+ to_chat(source, "[icon2html(src, source)][target] successfully loaded.")
+ log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]", LOG_MECHA)
+ else
+ O.set_anchored(initial(O.anchored))
+ else
+ to_chat(source, "[icon2html(src, source)]Not enough room in cargo compartment!")
+ else
+ to_chat(source, "[icon2html(src, source)][target] is firmly secured!")
+
+ else if(isliving(target))
+ var/mob/living/M = target
+ if(M.stat == DEAD)
+ return
+ if(source.a_intent == INTENT_HARM)
+ if(real_clamp)
+ M.take_overall_damage(dam_force)
+ if(!M)
+ return
+ M.adjustOxyLoss(round(dam_force/2))
+ M.updatehealth()
+ target.visible_message("[chassis] destroys [target] in an unholy fury!", \
+ "[chassis] destroys you in an unholy fury!")
+ log_combat(source, M, "attacked", "[name]", "(INTENT: [uppertext(source.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
+ else
+ target.visible_message("[chassis] destroys [target] in an unholy fury!", \
+ "[chassis] destroys you in an unholy fury!")
+ else if(source.a_intent == INTENT_DISARM)
+ if(real_clamp)
+ var/mob/living/carbon/C = target
+ var/play_sound = FALSE
+ var/limbs_gone = ""
+ var/obj/item/bodypart/affected = C.get_bodypart(BODY_ZONE_L_ARM)
+ if(affected != null)
+ affected.dismember(damtype)
+ play_sound = TRUE
+ limbs_gone = ", [affected]"
+ affected = C.get_bodypart(BODY_ZONE_R_ARM)
+ if(affected != null)
+ affected.dismember(damtype)
+ play_sound = TRUE
+ limbs_gone = "[limbs_gone], [affected]"
+ if(play_sound)
+ playsound(src, get_dismember_sound(), 80, TRUE)
+ target.visible_message("[chassis] rips [target]'s arms off!", \
+ "[chassis] rips your arms off!")
+ log_combat(source, M, "dismembered of[limbs_gone],", "[name]", "(INTENT: [uppertext(source.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
+ else
+ target.visible_message("[chassis] rips [target]'s arms off!", \
+ "[chassis] rips your arms off!")
+ else
+ step_away(M,chassis)
+ target.visible_message("[chassis] tosses [target] like a piece of paper!", \
+ "[chassis] tosses you like a piece of paper!")
+ return ..()
+
+
+
+/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 = MECHA_MELEE|MECHA_RANGED
+ mech_flags = EXOSUIT_MODULE_WORKING
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize()
+ . = ..()
+ create_reagents(1000)
+ reagents.add_reagent(/datum/reagent/water, 1000)
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/action(mob/source, atom/target, params) //copypasted from extinguisher. TODO: Rewrite from scratch.//Still todo
+ 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)
+ to_chat(chassis.occupants,"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/particle_effect/water/W = new /obj/effect/particle_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/can_attach(obj/vehicle/sealed/mecha/working/M as obj)
+ if(..())
+ if(istype(M))
+ return 1
+ return 0
+
+
+
+/obj/item/mecha_parts/mecha_equipment/rcd
+ name = "mounted RCD"
+ desc = "An exosuit-mounted Rapid Construction Device."
+ icon_state = "mecha_rcd"
+ equip_cooldown = 10
+ energy_drain = 250
+ range = MECHA_MELEE|MECHA_RANGED
+ item_flags = NO_MAT_REDEMPTION
+ var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
+
+/obj/item/mecha_parts/mecha_equipment/rcd/Initialize()
+ . = ..()
+ GLOB.rcd_list += src
+
+/obj/item/mecha_parts/mecha_equipment/rcd/Destroy()
+ GLOB.rcd_list -= src
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/rcd/action(mob/source, atom/target, params)
+ if(istype(target, /turf/open/space/transit))//>implying these are ever made -Sieve
+ return
+
+ if(!isturf(target) && !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, TRUE)
+
+ switch(mode)
+ if(0)
+ if(iswallturf(target))
+ var/turf/closed/wall/W = target
+ to_chat(source, "[icon2html(src, source)]Deconstructing [W]...")
+ if(do_after_cooldown(W, source))
+ chassis.spark_system.start()
+ W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
+ playsound(W, 'sound/items/deconstruct.ogg', 50, TRUE)
+ else if(isfloorturf(target))
+ var/turf/open/floor/F = target
+ to_chat(source, "[icon2html(src, source)]Deconstructing [F]...")
+ if(do_after_cooldown(target, source))
+ chassis.spark_system.start()
+ F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
+ playsound(F, 'sound/items/deconstruct.ogg', 50, TRUE)
+ else if (istype(target, /obj/machinery/door/airlock))
+ to_chat(source, "[icon2html(src, source)]Deconstructing [target]...")
+ if(do_after_cooldown(target, source))
+ chassis.spark_system.start()
+ qdel(target)
+ playsound(target, 'sound/items/deconstruct.ogg', 50, TRUE)
+ if(1)
+ if(isspaceturf(target))
+ var/turf/open/space/S = target
+ to_chat(source, "[icon2html(src, source)]Building Floor...")
+ if(do_after_cooldown(S, source))
+ S.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
+ playsound(S, 'sound/items/deconstruct.ogg', 50, TRUE)
+ chassis.spark_system.start()
+ else if(isfloorturf(target))
+ var/turf/open/floor/F = target
+ to_chat(source, "[icon2html(src, source)]Building Wall...")
+ if(do_after_cooldown(F, source))
+ F.PlaceOnTop(/turf/closed/wall)
+ playsound(F, 'sound/items/deconstruct.ogg', 50, TRUE)
+ chassis.spark_system.start()
+ if(2)
+ if(isfloorturf(target))
+ to_chat(source, "[icon2html(src, source)]Building Airlock...")
+ if(do_after_cooldown(target, source))
+ chassis.spark_system.start()
+ var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target)
+ T.autoclose = TRUE
+ playsound(target, 'sound/items/deconstruct.ogg', 50, TRUE)
+ playsound(target, 'sound/effects/sparks2.ogg', 50, TRUE)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/rcd/Topic(href,href_list)
+ ..()
+ if(href_list["mode"])
+ mode = text2num(href_list["mode"])
+ switch(mode)
+ if(0)
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]Switched RCD to Deconstruct.")
+ energy_drain = initial(energy_drain)
+ if(1)
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]Switched RCD to Construct.")
+ energy_drain = 2*initial(energy_drain)
+ if(2)
+ to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)]Switched RCD to Construct Airlock.")
+ energy_drain = 2*initial(energy_drain)
+ return
+
+/obj/item/mecha_parts/mecha_equipment/rcd/get_equip_info()
+ return "[..()] \[D|C|A\]"
+
+//Dunno where else to put this so shrug
+/obj/item/mecha_parts/mecha_equipment/ripleyupgrade
+ name = "Ripley MK-II Conversion Kit"
+ desc = "A pressurized canopy attachment kit for an Autonomous Power Loader Unit \"Ripley\" MK-I mecha, to convert it to the slower, but space-worthy MK-II design. This kit cannot be removed, once applied."
+ icon_state = "tesla"
+ mech_flags = EXOSUIT_MODULE_RIPLEY
+
+/obj/item/mecha_parts/mecha_equipment/ripleyupgrade/can_attach(obj/vehicle/sealed/mecha/working/ripley/M)
+ if(M.type != /obj/vehicle/sealed/mecha/working/ripley)
+ to_chat(loc, "This conversion kit can only be applied to APLU MK-I models.")
+ return FALSE
+ if(M.cargo.len)
+ to_chat(loc, "[M]'s cargo hold must be empty before this conversion kit can be applied.")
+ return FALSE
+ if(!(M.mecha_flags & ADDING_MAINT_ACCESS_POSSIBLE)) //non-removable upgrade, so lets make sure the pilot or owner has their say.
+ to_chat(loc, "[M] must have maintenance protocols active in order to allow this conversion kit.")
+ return FALSE
+ if(LAZYLEN(M.occupants)) //We're actualy making a new mech and swapping things over, it might get weird if players are involved
+ to_chat(loc, "[M] must be unoccupied before this conversion kit can be applied.")
+ return FALSE
+ if(!M.cell) //Turns out things break if the cell is missing
+ to_chat(loc, "The conversion process requires a cell installed.")
+ return FALSE
+ return TRUE
+
+/obj/item/mecha_parts/mecha_equipment/ripleyupgrade/attach(obj/vehicle/sealed/mecha/M)
+ var/obj/vehicle/sealed/mecha/working/ripley/mkii/N = new /obj/vehicle/sealed/mecha/working/ripley/mkii(get_turf(M),1)
+ if(!N)
+ return
+ QDEL_NULL(N.cell)
+ if (M.cell)
+ N.cell = M.cell
+ M.cell.forceMove(N)
+ M.cell = null
+ QDEL_NULL(N.scanmod)
+ if (M.scanmod)
+ N.scanmod = M.scanmod
+ M.scanmod.forceMove(N)
+ M.scanmod = null
+ QDEL_NULL(N.capacitor)
+ if (M.capacitor)
+ N.capacitor = M.capacitor
+ M.capacitor.forceMove(N)
+ M.capacitor = null
+ N.update_part_values()
+ for(var/obj/item/mecha_parts/E in M.contents)
+ if(istype(E, /obj/item/mecha_parts/concealed_weapon_bay)) //why is the bay not just a variable change who did this
+ E.forceMove(N)
+ for(var/obj/item/mecha_parts/mecha_equipment/E in M.equipment) //Move the equipment over...
+ E.detach(M)
+ E.attach(N)
+ N.dna_lock = M.dna_lock
+ N.mecha_flags = M.mecha_flags
+ N.strafe = M.strafe
+ N.obj_integrity = M.obj_integrity //This is not a repair tool
+ if (M.name != "\improper APLU MK-I \"Ripley\"")
+ N.name = M.name
+ M.wreckage = 0
+ qdel(M)
+ playsound(get_turf(N),'sound/items/ratchet.ogg',50,TRUE)
+ return
diff --git a/code/game/mecha/equipment/weapons/mecha_ammo.dm b/code/modules/vehicles/mecha/equipment/weapons/mecha_ammo.dm
similarity index 94%
rename from code/game/mecha/equipment/weapons/mecha_ammo.dm
rename to code/modules/vehicles/mecha/equipment/weapons/mecha_ammo.dm
index 3253e6cbd6..edc2b4716e 100644
--- a/code/game/mecha/equipment/weapons/mecha_ammo.dm
+++ b/code/modules/vehicles/mecha/equipment/weapons/mecha_ammo.dm
@@ -9,7 +9,7 @@
var/rounds = 0
var/round_term = "round"
var/direct_load //For weapons where we re-load the weapon itself rather than adding to the ammo storage.
- var/load_audio = "sound/weapons/gun_magazine_insert_empty_1.ogg"
+ var/load_audio = 'sound/weapons/bulletinsert.ogg'
var/ammo_type
/obj/item/mecha_ammo/update_name()
@@ -62,7 +62,7 @@
rounds = 6
round_term = "missile"
direct_load = TRUE
- load_audio = "sound/weapons/bulletinsert.ogg"
+ load_audio = 'sound/weapons/bulletinsert.ogg'
ammo_type = "missiles_br"
/obj/item/mecha_ammo/missiles_he
@@ -72,7 +72,7 @@
rounds = 8
round_term = "missile"
direct_load = TRUE
- load_audio = "sound/weapons/bulletinsert.ogg"
+ load_audio = 'sound/weapons/bulletinsert.ogg'
ammo_type = "missiles_he"
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
similarity index 70%
rename from code/game/mecha/equipment/weapons/weapons.dm
rename to code/modules/vehicles/mecha/equipment/weapons/weapons.dm
index a9d7853187..1f1211a3a4 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
@@ -1,76 +1,61 @@
/obj/item/mecha_parts/mecha_equipment/weapon
name = "mecha weapon"
- range = RANGED
+ range = MECHA_RANGED
+ destroy_sound = 'sound/mecha/weapdestr.ogg'
var/projectile
var/fire_sound
var/projectiles_per_shot = 1
var/variance = 0
- var/randomspread = 0 //use random spread for machineguns, instead of shotgun scatter
+ var/randomspread = FALSE //use random spread for machineguns, instead of shotgun scatter
var/projectile_delay = 0
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired.
var/kickback = TRUE //Will using this weapon in no grav push mecha back.
mech_flags = EXOSUIT_MODULE_COMBAT
-/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M)
- if(..())
- if(istype(M))
- return 1
- return 0
+/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/vehicle/sealed/mecha/M)
+ if(!..())
+ return FALSE
+ if(istype(M, /obj/vehicle/sealed/mecha/combat))
+ return TRUE
+ if((locate(/obj/item/mecha_parts/concealed_weapon_bay) in M.contents) && !(locate(/obj/item/mecha_parts/mecha_equipment/weapon) in M.equipment))
+ return TRUE
+ return FALSE
-/obj/item/mecha_parts/mecha_equipment/weapon/proc/get_shot_amount()
- return projectiles_per_shot
-
-/obj/item/mecha_parts/mecha_equipment/weapon/action(atom/target, params)
+/obj/item/mecha_parts/mecha_equipment/weapon/action(mob/source, atom/target, params)
if(!action_checks(target))
- return 0
-
- var/turf/curloc = get_turf(chassis)
- var/turf/targloc = get_turf(target)
- if (!targloc || !istype(targloc) || !curloc)
- return 0
- if (targloc == curloc)
- return 0
-
- set_ready_state(0)
- for(var/i=1 to get_shot_amount())
- var/obj/item/projectile/A = new projectile(curloc)
- A.firer = chassis.occupant
- A.original = target
- if(!A.suppressed && firing_effect_type)
- new firing_effect_type(get_turf(src), chassis.dir)
-
+ return FALSE
+ var/newtonian_target = turn(chassis.dir,180)
+ . = ..()//start the cooldown early because of sleeps
+ for(var/i in 1 to projectiles_per_shot)
+ if(energy_drain && !chassis.has_charge(energy_drain))//in case we run out of energy mid-burst, such as emp
+ break
var/spread = 0
if(variance)
if(randomspread)
spread = round((rand() - 0.5) * variance)
else
spread = round((i / projectiles_per_shot - 0.5) * variance)
- A.preparePixelProjectile(target, chassis.occupant, params, spread)
+
+ var/obj/item/projectile/A = new projectile(get_turf(src))
+ A.preparePixelProjectile(target, source, params, spread)
A.fire()
- playsound(chassis, fire_sound, 50, 1)
+ if(!A.suppressed && firing_effect_type)
+ new firing_effect_type(get_turf(src), chassis.dir)
+ playsound(chassis, fire_sound, 50, TRUE)
sleep(max(0, projectile_delay))
- if(kickback)
- chassis.newtonian_move(turn(chassis.dir,180))
- chassis.mecha_log_message("Fired from [src.name], targeting [target].")
- return 1
-
+ if(kickback)
+ chassis.newtonian_move(newtonian_target)
+ chassis.log_message("Fired from [src.name], targeting [target].", LOG_MECHA)
+ return ..()
//Base energy weapon type
/obj/item/mecha_parts/mecha_equipment/weapon/energy
name = "general energy weapon"
firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect/energy
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/get_shot_amount()
- return min(round(chassis.cell.charge / energy_drain), projectiles_per_shot)
-
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/start_cooldown()
- set_ready_state(0)
- chassis.use_power(energy_drain*get_shot_amount())
- addtimer(CALLBACK(src, .proc/set_ready_state, 1), equip_cooldown)
-
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
equip_cooldown = 8
name = "\improper CH-PS \"Immolator\" laser"
@@ -81,6 +66,15 @@
fire_sound = 'sound/weapons/laser.ogg'
harmful = TRUE
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/disabler
+ equip_cooldown = 8
+ name = "\improper CH-DS \"Peacemaker\" disabler"
+ desc = "A weapon for combat exosuits. Shoots basic disablers."
+ icon_state = "mecha_disabler"
+ energy_drain = 30
+ projectile = /obj/item/projectile/beam/disabler
+ fire_sound = 'sound/weapons/taser2.ogg'
+
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy
equip_cooldown = 15
name = "\improper CH-LC \"Solaris\" laser cannon"
@@ -97,7 +91,7 @@
icon_state = "mecha_ion"
energy_drain = 120
projectile = /obj/item/projectile/ion
- fire_sound = 'sound/weapons/IonRifle.ogg'
+ fire_sound = 'sound/weapons/laser.ogg'
/obj/item/mecha_parts/mecha_equipment/weapon/energy/tesla
equip_cooldown = 35
@@ -124,7 +118,6 @@
name = "217-D Heavy Plasma Cutter"
desc = "A device that shoots resonant plasma bursts at extreme velocity. The blasts are capable of crushing rock and demolishing solid obstacles."
icon_state = "mecha_plasmacutter"
- item_state = "plasmacutter"
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
energy_drain = 30
@@ -132,12 +125,12 @@
fire_sound = 'sound/weapons/plasma_cutter.ogg'
harmful = TRUE
-/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/mecha/working/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/vehicle/sealed/mecha/M)
if(..()) //combat mech
- return 1
- else if(M.equipment.len < M.max_equip && istype(M))
- return 1
- return 0
+ return TRUE
+ else if(LAZYLEN(M.equipment) < M.max_equip)
+ return TRUE
+ return FALSE
/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser
name = "\improper PBT \"Pacifier\" mounted taser"
@@ -155,47 +148,53 @@
icon_state = "mecha_honker"
energy_drain = 200
equip_cooldown = 150
- range = MELEE|RANGED
+ range = MECHA_MELEE|MECHA_RANGED
kickback = FALSE
+ mech_flags = EXOSUIT_MODULE_HONK
-/obj/item/mecha_parts/mecha_equipment/weapon/honker/can_attach(obj/mecha/combat/honker/M)
- if(..())
- if(istype(M))
- return 1
- return 0
+/obj/item/mecha_parts/mecha_equipment/weapon/honker/can_attach(obj/vehicle/sealed/mecha/mecha)
+ . = ..()
+ if(!.)
+ return
+ if(!istype(mecha, /obj/vehicle/sealed/mecha/combat/honker))
+ return FALSE
-/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target, params)
+
+/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(mob/source, atom/target, params)
if(!action_checks(target))
return
- playsound(chassis, 'sound/items/airhorn.ogg', 100, 1)
- chassis.occupant_message("HONK")
+ playsound(chassis, 'sound/items/airhorn.ogg', 100, TRUE)
+ to_chat(source, "[icon2html(src, source)]HONK")
for(var/mob/living/carbon/M in ohearers(6, chassis))
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(istype(H.ears, /obj/item/clothing/ears/earmuffs))
- continue
+ if(!M.can_hear())
+ continue
+ var/turf/turf_check = get_turf(M)
+ if(isspaceturf(turf_check) && !turf_check.Adjacent(src)) //in space nobody can hear you honk.
+ continue
to_chat(M, "HONK")
M.SetSleeping(0)
M.stuttering += 20
- M.adjustEarDamage(0, 30)
- M.DefaultCombatKnockdown(60)
+ var/obj/item/organ/ears/ears = M.getorganslot(ORGAN_SLOT_EARS)
+ if(ears)
+ ears.adjustEarDamage(0, 30)
+ M.Paralyze(60)
if(prob(30))
M.Stun(200)
M.Unconscious(80)
else
M.Jitter(500)
- mecha_log_message("Honked from [src.name]. HONK!")
+ log_message("Honked from [src.name]. HONK!", LOG_MECHA)
var/turf/T = get_turf(src)
- message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] used a Mecha Honker in [ADMIN_VERBOSEJMP(T)]")
- log_game("[key_name(chassis.occupant)] used a Mecha Honker in [AREACOORD(T)]")
- return 1
+ message_admins("[ADMIN_LOOKUPFLW(source)] used a Mecha Honker in [ADMIN_VERBOSEJMP(T)]")
+ log_game("[key_name(source)] used a Mecha Honker in [AREACOORD(T)]")
+ return ..()
//Base ballistic weapon type
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic
name = "general ballistic weapon"
- fire_sound = 'sound/weapons/lmgshot.ogg'
+ fire_sound = 'sound/weapons/shot.ogg'
var/projectiles
var/projectiles_cache //ammo to be loaded in, if possible.
var/projectiles_cache_max
@@ -203,15 +202,12 @@
var/disabledreload //For weapons with no cache (like the rockets) which are reloaded by hand
var/ammo_type
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_shot_amount()
- return min(projectiles, projectiles_per_shot)
-
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action_checks(target)
if(!..())
- return 0
+ return FALSE
if(projectiles <= 0)
- return 0
- return 1
+ return FALSE
+ return TRUE
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info()
return "[..()] \[[src.projectiles][projectiles_cache_max &&!projectile_energy_cost?"/[projectiles_cache]":""]\][!disabledreload &&(src.projectiles < initial(src.projectiles))?" - Rearm":null]"
@@ -237,7 +233,8 @@
projectiles = projectiles + projectiles_cache
projectiles_cache = 0
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ send_byjax(chassis.occupants,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ log_message("Rearmed [src.name].", LOG_MECHA)
return TRUE
@@ -252,11 +249,11 @@
src.rearm()
return
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action(atom/target)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action(mob/source, atom/target, params)
if(..())
- projectiles -= get_shot_amount()
- send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
- return 1
+ projectiles -= projectiles_per_shot
+ send_byjax(chassis.occupants,"exosuit.browser","[REF(src)]",src.get_equip_info())
+ return ..()
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
@@ -274,7 +271,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced
name = "\improper S.H.H. \"Quietus\" Carbine"
desc = "A weapon for combat exosuits. A mime invention, field tests have shown that targets cannot even scream before going down."
- fire_sound = 'sound/weapons/gunshot_silenced.ogg'
+ fire_sound = 'sound/weapons/Gunshot_silenced.ogg'
icon_state = "mecha_mime"
equip_cooldown = 30
projectile = /obj/item/projectile/bullet/mime
@@ -285,7 +282,6 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
name = "\improper LBX AC 10 \"Scattershot\""
desc = "A weapon for combat exosuits. Shoots a spread of pellets."
- fire_sound = 'sound/weapons/gunshotshotgunshot.ogg'
icon_state = "mecha_scatter"
equip_cooldown = 20
projectile = /obj/item/projectile/bullet/scattershot
@@ -347,7 +343,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/breaching
name = "\improper BRM-6 missile rack"
- desc = "A weapon for combat exosuits. Launches low-explosive breaching missiles designed to explode only when striking a sturdy target."
+ desc = "A weapon for combat exosuits. Launches high-explosive breaching missiles with a safety fuze designed to explode only when striking a sturdy target."
icon_state = "mecha_missilerack_six"
projectile = /obj/item/projectile/bullet/a84mm_br
fire_sound = 'sound/weapons/rocketlaunch.ogg'
@@ -365,19 +361,19 @@
var/missile_range = 30
var/diags_first = FALSE
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/action(target)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/action(mob/source, atom/target, params)
if(!action_checks(target))
return
var/obj/O = new projectile(chassis.loc)
- playsound(chassis, fire_sound, 50, 1)
- mecha_log_message("Launched a [O.name] from [name], targeting [target].")
+ playsound(chassis, fire_sound, 50, TRUE)
+ log_message("Launched a [O.name] from [name], targeting [target].", LOG_MECHA)
projectiles--
- proj_init(O)
- O.throw_at(target, missile_range, missile_speed, chassis.occupant, FALSE, diagonals_first = diags_first)
- return 1
+ proj_init(O, source)
+ O.throw_at(target, missile_range, missile_speed, source, FALSE, diagonals_first = diags_first)
+ return TRUE
//used for projectile initilisation (priming flashbang) and additional logging
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/proc/proj_init(var/obj/O)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/proc/proj_init(obj/O, mob/user)
return
@@ -395,10 +391,10 @@
var/det_time = 20
ammo_type = "flashbang"
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/proj_init(var/obj/item/grenade/flashbang/F)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/proj_init(obj/item/grenade/flashbang/F, mob/user)
var/turf/T = get_turf(src)
- message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] fired a [src] in [ADMIN_VERBOSEJMP(T)]")
- log_game("[key_name(chassis.occupant)] fired a [src] in [AREACOORD(T)]")
+ message_admins("[ADMIN_LOOKUPFLW(user)] fired a [F] in [ADMIN_VERBOSEJMP(T)]")
+ log_game("[key_name(user)] fired a [F] in [AREACOORD(T)]")
addtimer(CALLBACK(F, /obj/item/grenade/flashbang.proc/prime), det_time)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/clusterbang //Because I am a heartless bastard -Sieve //Heartless? for making the poor man's honkblast? - Kaze
@@ -422,8 +418,9 @@
missile_speed = 1.5
projectile_energy_cost = 100
equip_cooldown = 20
+ mech_flags = EXOSUIT_MODULE_HONK
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/can_attach(obj/mecha/combat/honker/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/can_attach(obj/vehicle/sealed/mecha/combat/honker/M)
if(..())
if(istype(M))
return 1
@@ -439,14 +436,15 @@
missile_speed = 1.5
projectile_energy_cost = 100
equip_cooldown = 10
+ mech_flags = EXOSUIT_MODULE_HONK
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/can_attach(obj/vehicle/sealed/mecha/combat/honker/M)
if(..())
if(istype(M))
return 1
return 0
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/proj_init(var/obj/item/assembly/mousetrap/armed/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/proj_init(obj/item/assembly/mousetrap/armed/M)
M.secured = 1
@@ -457,28 +455,58 @@
icon_state = "mecha_punching_glove"
energy_drain = 250
equip_cooldown = 20
- range = MELEE|RANGED
+ range = MECHA_MELEE|MECHA_RANGED
missile_range = 5
projectile = /obj/item/punching_glove
fire_sound = 'sound/items/bikehorn.ogg'
projectiles = 10
projectile_energy_cost = 500
+ harmful = TRUE
diags_first = TRUE
+ /// Damage done by the glove on contact. Also used to determine throw distance (damage / 5)
+ var/punch_damage = 35
+ /// TRUE - Can toggle between lethal and non-lethal || FALSE - Cannot toggle
+ var/can_toggle_lethal = TRUE
+ mech_flags = EXOSUIT_MODULE_HONK
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/can_attach(obj/mecha/combat/honker/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/can_attach(obj/vehicle/sealed/mecha/combat/honker/M)
if(..())
if(istype(M))
return 1
return 0
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/action(target)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/get_equip_info()
+ if(!chassis)
+ return
+
+ if(can_toggle_lethal)
+ return "[..()] [harmful?"Punch":"Pat"] mode"
+ else
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/Topic(href, href_list)
+ ..()
+ if(href_list["lethalPunch"])
+ harmful = !harmful
+ if(harmful)
+ to_chat(usr, "[icon2html(src, usr)]Lethal Fisting Enabled.")
+ else
+ to_chat(usr, "[icon2html(src, usr)]Lethal Fisting Disabled.")
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/action(mob/source, atom/target, params)
. = ..()
if(.)
- chassis.occupant_message("HONK")
+ to_chat(usr, "[icon2html(src, usr)]HONK")
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/proj_init(obj/item/punching_glove/PG)
if(!istype(PG))
return
+
+ if(harmful)
+ PG.throwforce = punch_damage
+ else
+ PG.throwforce = 0
+
//has to be low sleep or it looks weird, the beam doesn't exist for very long so it's a non-issue
chassis.Beam(PG, icon_state = "chain", time = missile_range * 20, maxdistance = missile_range + 2, beam_sleep_time = 1)
@@ -492,5 +520,5 @@
if(!..())
if(ismovable(hit_atom))
var/atom/movable/AM = hit_atom
- AM.safe_throw_at(get_edge_target_turf(AM,get_dir(src, AM)), 7, 2)
+ AM.safe_throw_at(get_edge_target_turf(AM,get_dir(src, AM)), clamp(round(throwforce/5), 2, 20), 2) //Throws them equal to damage/5, with a min range of 2 and max range of 20
qdel(src)
diff --git a/code/game/mecha/mech_bay.dm b/code/modules/vehicles/mecha/mech_bay.dm
similarity index 89%
rename from code/game/mecha/mech_bay.dm
rename to code/modules/vehicles/mecha/mech_bay.dm
index e9f682e929..18149401de 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/modules/vehicles/mecha/mech_bay.dm
@@ -5,7 +5,7 @@
icon_state = "recharge_floor" // Some people just want to watch the world burn i guess
/turf/open/floor/mech_bay_recharge_floor/break_tile()
- ScrapeAway()
+ ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
/turf/open/floor/mech_bay_recharge_floor/airless
icon_state = "recharge_floor_asteroid"
@@ -19,17 +19,25 @@
icon = 'icons/mecha/mech_bay.dmi'
icon_state = "recharge_port"
circuit = /obj/item/circuitboard/machine/mech_recharger
- var/obj/mecha/recharging_mech
+ var/obj/vehicle/sealed/mecha/recharging_mech
var/obj/machinery/computer/mech_bay_power_console/recharge_console
var/max_charge = 50
var/on = FALSE
- var/repairability = 0
var/turf/recharging_turf = null
/obj/machinery/mech_bay_recharge_port/Initialize()
. = ..()
recharging_turf = get_step(loc, dir)
+/obj/machinery/mech_bay_recharge_port/Destroy()
+ if (recharge_console && recharge_console.recharge_port == src)
+ recharge_console.recharge_port = null
+ return ..()
+
+/obj/machinery/mech_bay_recharge_port/setDir(new_dir)
+ . = ..()
+ recharging_turf = get_step(loc, dir)
+
/obj/machinery/mech_bay_recharge_port/RefreshParts()
var/MC
for(var/obj/item/stock_parts/capacitor/C in component_parts)
@@ -45,7 +53,7 @@
if(stat & NOPOWER || !recharge_console)
return
if(!recharging_mech)
- recharging_mech = locate(/obj/mecha) in recharging_turf
+ recharging_mech = locate(/obj/vehicle/sealed/mecha) in recharging_turf
if(recharging_mech)
recharge_console.update_icon()
if(recharging_mech && recharging_mech.cell)
@@ -78,8 +86,8 @@
icon_screen = "recharge_comp"
icon_keyboard = "rd_key"
circuit = /obj/item/circuitboard/computer/mech_bay_power_console
- var/obj/machinery/mech_bay_recharge_port/recharge_port
light_color = LIGHT_COLOR_PINK
+ var/obj/machinery/mech_bay_recharge_port/recharge_port
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -136,3 +144,8 @@
/obj/machinery/computer/mech_bay_power_console/Initialize()
. = ..()
reconnect()
+
+/obj/machinery/computer/mech_bay_power_console/Destroy()
+ if (recharge_port && recharge_port.recharge_console == src)
+ recharge_port.recharge_console = null
+ return ..()
diff --git a/code/game/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm
similarity index 100%
rename from code/game/mecha/mech_fabricator.dm
rename to code/modules/vehicles/mecha/mech_fabricator.dm
diff --git a/code/modules/vehicles/mecha/mech_melee_attack.dm b/code/modules/vehicles/mecha/mech_melee_attack.dm
new file mode 100644
index 0000000000..2f5faea172
--- /dev/null
+++ b/code/modules/vehicles/mecha/mech_melee_attack.dm
@@ -0,0 +1,117 @@
+///Called when a mech melee attacks an atom
+/atom/proc/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker)
+ return
+
+/turf/closed/wall/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker)
+ mecha_attacker.do_attack_animation(src)
+ switch(mecha_attacker.damtype)
+ if(BRUTE)
+ playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
+ mecha_attacker.visible_message("[mecha_attacker.name] hits [src]!", \
+ "You hit [src]!", null, COMBAT_MESSAGE_RANGE)
+ if(prob(hardness + mecha_attacker.force) && mecha_attacker.force > 20)
+ dismantle_wall(1)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
+ else
+ add_dent(WALL_DENT_HIT)
+ if(BURN)
+ playsound(src, 'sound/items/welder.ogg', 100, TRUE)
+ if(TOX)
+ playsound(src, 'sound/effects/spray2.ogg', 100, TRUE)
+ return FALSE
+
+/obj/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker)
+ mecha_attacker.do_attack_animation(src)
+ var/play_soundeffect = 0
+ var/mech_damtype = mecha_attacker.damtype
+ if(mecha_attacker.selected)
+ mech_damtype = mecha_attacker.selected.damtype
+ play_soundeffect = 1
+ else
+ switch(mecha_attacker.damtype)
+ if(BRUTE)
+ playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
+ if(BURN)
+ playsound(src, 'sound/items/welder.ogg', 50, TRUE)
+ if(TOX)
+ playsound(src, 'sound/effects/spray2.ogg', 50, TRUE)
+ return 0
+ else
+ return 0
+ mecha_attacker.visible_message("[mecha_attacker.name] hits [src]!", "You hit [src]!", null, COMBAT_MESSAGE_RANGE)
+ return take_damage(mecha_attacker.force * 3, mech_damtype, MELEE, play_soundeffect, get_dir(src, mecha_attacker)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
+
+/obj/structure/window/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker)
+ if(!can_be_reached())
+ return
+ return ..()
+
+/mob/living/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/user)
+ if(user.a_intent == INTENT_HARM)
+ if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ to_chat(user, "You don't want to harm other living beings!")
+ return
+ mecha_attacker.do_attack_animation(src)
+ if(mecha_attacker.damtype == "brute")
+ step_away(src, mecha_attacker, 15)
+ switch(mecha_attacker.damtype)
+ if(BRUTE)
+ Unconscious(20)
+ take_overall_damage(rand(mecha_attacker.force/2, mecha_attacker.force))
+ playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
+ if(BURN)
+ take_overall_damage(0, rand(mecha_attacker.force * 0.5, mecha_attacker.force))
+ playsound(src, 'sound/items/welder.ogg', 50, TRUE)
+ if(TOX)
+ mecha_attacker.mech_toxin_damage(src)
+ else
+ return
+ updatehealth()
+ visible_message("[mecha_attacker.name] hits [src]!", \
+ "[mecha_attacker.name] hits you!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, mecha_attacker)
+ to_chat(mecha_attacker, "You hit [src]!")
+ log_combat(user, src, "attacked", mecha_attacker, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(mecha_attacker.damtype)])")
+ else
+ step_away(src, mecha_attacker)
+ log_combat(user, src, "pushed", mecha_attacker)
+ visible_message("[mecha_attacker] pushes [src] out of the way.", \
+ "[mecha_attacker] pushes you out of the way.", "You hear aggressive shuffling!", 5, list(mecha_attacker))
+ to_chat(mecha_attacker, "You push [src] out of the way.")
+
+/mob/living/carbon/human/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/user)
+ if(user.a_intent == INTENT_HARM)
+ if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ to_chat(user, "You don't want to harm other living beings!")
+ return
+ mecha_attacker.do_attack_animation(src)
+ if(mecha_attacker.damtype == BRUTE)
+ step_away(src, mecha_attacker, 15)
+ var/obj/item/bodypart/temp = get_bodypart(pick(BODY_ZONE_CHEST, BODY_ZONE_CHEST, BODY_ZONE_CHEST, BODY_ZONE_HEAD))
+ if(temp)
+ var/update = 0
+ var/dmg = rand(mecha_attacker.force * 0.5, mecha_attacker.force)
+ switch(mecha_attacker.damtype)
+ if(BRUTE)
+ if(mecha_attacker.force > 35) // durand and other heavy mechas
+ Unconscious(20)
+ else if(mecha_attacker.force > 20 && !IsKnockdown()) // lightweight mechas like gygax
+ Knockdown(40)
+ update |= temp.receive_damage(dmg, 0)
+ playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
+ if(BURN)
+ update |= temp.receive_damage(0, dmg)
+ playsound(src, 'sound/items/welder.ogg', 50, TRUE)
+ if(TOX)
+ mecha_attacker.mech_toxin_damage(src)
+ else
+ return
+ if(update)
+ update_damage_overlays()
+ updatehealth()
+
+ visible_message("[mecha_attacker.name] hits [src]!", \
+ "[mecha_attacker.name] hits you!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, list(mecha_attacker))
+ to_chat(mecha_attacker, "You hit [src]!")
+ log_combat(user, src, "attacked", mecha_attacker, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(mecha_attacker.damtype)])")
+ else
+ return ..()
diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm
new file mode 100644
index 0000000000..070a3158b0
--- /dev/null
+++ b/code/modules/vehicles/mecha/mecha_actions.dm
@@ -0,0 +1,279 @@
+/***************** MECHA ACTIONS *****************/
+
+/obj/vehicle/sealed/mecha/generate_action_type()
+ . = ..()
+ if(istype(., /datum/action/vehicle/sealed/mecha))
+ var/datum/action/vehicle/sealed/mecha/mecha = .
+ mecha.chassis = src
+
+
+/datum/action/vehicle/sealed/mecha
+ icon_icon = 'icons/mob/actions/actions_mecha.dmi'
+ var/obj/vehicle/sealed/mecha/chassis
+
+/datum/action/vehicle/sealed/mecha/Destroy()
+ chassis = null
+ return ..()
+
+/datum/action/vehicle/sealed/mecha/mech_eject
+ name = "Eject From Mech"
+ button_icon_state = "mech_eject"
+
+/datum/action/vehicle/sealed/mecha/mech_eject/Trigger()
+ if(!owner)
+ return
+ if(!chassis || !(owner in chassis.occupants))
+ return
+ chassis.container_resist(owner)
+
+/datum/action/vehicle/sealed/mecha/mech_toggle_internals
+ name = "Toggle Internal Airtank Usage"
+ button_icon_state = "mech_internals_off"
+
+/datum/action/vehicle/sealed/mecha/mech_toggle_internals/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ chassis.use_internal_tank = !chassis.use_internal_tank
+ button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]"
+ to_chat(chassis.occupants, "[icon2html(chassis, owner)]Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
+ chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].", LOG_MECHA)
+ UpdateButtonIcon()
+
+/datum/action/vehicle/sealed/mecha/mech_cycle_equip
+ name = "Cycle Equipment"
+ button_icon_state = "mech_cycle_equip_off"
+
+/datum/action/vehicle/sealed/mecha/mech_cycle_equip/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+
+ var/list/available_equipment = list()
+ for(var/e in chassis.equipment)
+ var/obj/item/mecha_parts/mecha_equipment/equipment = e
+ if(equipment.selectable)
+ available_equipment += equipment
+
+ if(available_equipment.len == 0)
+ to_chat(owner, "[icon2html(chassis, owner)]No equipment available!")
+ return
+ if(!chassis.selected)
+ chassis.selected = available_equipment[1]
+ to_chat(owner, "[icon2html(chassis, owner)]You select [chassis.selected].")
+ send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
+ button_icon_state = "mech_cycle_equip_on"
+ UpdateButtonIcon()
+ return
+ var/number = 0
+ for(var/equipment in available_equipment)
+ number++
+ if(equipment != chassis.selected)
+ continue
+ if(available_equipment.len == number)
+ chassis.selected = null
+ to_chat(owner, "[icon2html(chassis, owner)]You switch to no equipment.")
+ button_icon_state = "mech_cycle_equip_off"
+ else
+ chassis.selected = available_equipment[number+1]
+ to_chat(owner, "[icon2html(chassis, owner)]You switch to [chassis.selected].")
+ button_icon_state = "mech_cycle_equip_on"
+ send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
+ UpdateButtonIcon()
+ return
+
+
+/datum/action/vehicle/sealed/mecha/mech_toggle_lights
+ name = "Toggle Lights"
+ button_icon_state = "mech_lights_off"
+
+/datum/action/vehicle/sealed/mecha/mech_toggle_lights/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ if(!(chassis.mecha_flags & HAS_LIGHTS))
+ to_chat(owner, "This mechs lights are destroyed!")
+ return
+ chassis.mecha_flags ^= LIGHTS_ON
+ if(chassis.mecha_flags & LIGHTS_ON)
+ button_icon_state = "mech_lights_on"
+ chassis.set_light(5, 5)
+ else
+ button_icon_state = "mech_lights_off"
+ chassis.set_light(0)
+ to_chat(owner, "[icon2html(chassis, owner)]Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].")
+ chassis.log_message("Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].", LOG_MECHA)
+ UpdateButtonIcon()
+
+/datum/action/vehicle/sealed/mecha/mech_view_stats
+ name = "View Stats"
+ button_icon_state = "mech_view_stats"
+
+/datum/action/vehicle/sealed/mecha/mech_view_stats/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ var/datum/browser/popup = new(owner , "exosuit")
+ popup.set_content(chassis.get_stats_html(owner))
+ popup.open()
+
+
+/datum/action/vehicle/sealed/mecha/strafe
+ name = "Toggle Strafing. Disabled when Alt is held."
+ button_icon_state = "strafe"
+
+/datum/action/vehicle/sealed/mecha/strafe/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ chassis.toggle_strafe()
+
+/obj/vehicle/sealed/mecha/AltClick(mob/living/user)
+ if(!(user in occupants) || !user.canUseTopic(src))
+ return
+ if(!(user in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE)))
+ to_chat(user, "You're in the wrong seat to control movement.")
+ return
+
+ toggle_strafe()
+
+/obj/vehicle/sealed/mecha/proc/toggle_strafe()
+ strafe = !strafe
+
+ to_chat(occupants, "[icon2html(src, occupants)]Toggled strafing mode [strafe?"on":"off"].")
+ log_message("Toggled strafing mode [strafe?"on":"off"].", LOG_MECHA)
+
+ for(var/occupant in occupants)
+ var/datum/action/action = LAZYACCESSASSOC(occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/strafe)
+ action?.UpdateButtonIcon()
+
+//////////////////////////////////////// Specific Ability Actions ///////////////////////////////////////////////
+//Need to be granted by the mech type, Not default abilities.
+
+/datum/action/vehicle/sealed/mecha/mech_defense_mode
+ name = "Toggle an energy shield that blocks all attacks from the faced direction at a heavy power cost."
+ button_icon_state = "mech_defense_mode_off"
+
+/datum/action/vehicle/sealed/mecha/mech_defense_mode/Trigger(forced_state = FALSE)
+ SEND_SIGNAL(chassis, COMSIG_MECHA_ACTION_TRIGGER, owner, args) //Signal sent to the mech, to be handed to the shield. See durand.dm for more details
+
+/datum/action/vehicle/sealed/mecha/mech_overload_mode
+ name = "Toggle leg actuators overload"
+ button_icon_state = "mech_overload_off"
+
+/datum/action/vehicle/sealed/mecha/mech_overload_mode/Trigger(forced_state = null)
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ if(!isnull(forced_state))
+ chassis.leg_overload_mode = forced_state
+ else
+ chassis.leg_overload_mode = !chassis.leg_overload_mode
+ chassis.log_message("Toggled leg actuators overload.", LOG_MECHA)
+ if(!chassis.leg_overload_mode)
+ button_icon_state = "mech_overload_on"
+ chassis.bumpsmash = TRUE
+ chassis.movedelay = min(1, round(chassis.movedelay * 0.5))
+ chassis.step_energy_drain = max(chassis.overload_step_energy_drain_min,chassis.step_energy_drain*chassis.leg_overload_coeff)
+ to_chat(owner, "[icon2html(chassis, owner)]You enable leg actuators overload.")
+ else
+ button_icon_state = "mech_overload_off"
+ chassis.bumpsmash = FALSE
+ chassis.movedelay = initial(chassis.movedelay)
+ chassis.step_energy_drain = chassis.normal_step_energy_drain
+ to_chat(owner, "[icon2html(chassis, owner)]You disable leg actuators overload.")
+ UpdateButtonIcon()
+
+/datum/action/vehicle/sealed/mecha/mech_smoke
+ name = "Smoke"
+ button_icon_state = "mech_smoke"
+
+/datum/action/vehicle/sealed/mecha/mech_smoke/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ if(!TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_SMOKE) && chassis.smoke_charges>0)
+ chassis.smoke_system.start()
+ chassis.smoke_charges--
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_SMOKE, chassis.smoke_cooldown)
+
+
+/datum/action/vehicle/sealed/mecha/mech_zoom
+ name = "Zoom"
+ button_icon_state = "mech_zoom_off"
+
+/datum/action/vehicle/sealed/mecha/mech_zoom/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ if(owner.client)
+ chassis.zoom_mode = !chassis.zoom_mode
+ button_icon_state = "mech_zoom_[chassis.zoom_mode ? "on" : "off"]"
+ chassis.log_message("Toggled zoom mode.", LOG_MECHA)
+ to_chat(owner, "[icon2html(chassis, owner)]Zoom mode [chassis.zoom_mode?"en":"dis"]abled.")
+ if(chassis.zoom_mode)
+ owner.client.view_size.setTo(4.5)
+ SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50))
+ else
+ owner.client.view_size.resetToDefault() //Let's not let this stack shall we?
+ UpdateButtonIcon()
+
+/datum/action/vehicle/sealed/mecha/mech_switch_damtype
+ name = "Reconfigure arm microtool arrays"
+ button_icon_state = "mech_damtype_brute"
+
+/datum/action/vehicle/sealed/mecha/mech_switch_damtype/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ var/new_damtype
+ switch(chassis.damtype)
+ if("tox")
+ new_damtype = "brute"
+ to_chat(owner, "[icon2html(chassis, owner)]Your exosuit's hands form into fists.")
+ if("brute")
+ new_damtype = "fire"
+ to_chat(owner, "[icon2html(chassis, owner)]A torch tip extends from your exosuit's hand, glowing red.")
+ if("fire")
+ new_damtype = "tox"
+ to_chat(owner, "[icon2html(chassis, owner)]A bone-chillingly thick plasteel needle protracts from the exosuit's palm.")
+ chassis.damtype = new_damtype
+ button_icon_state = "mech_damtype_[new_damtype]"
+ playsound(chassis, 'sound/mecha/mechmove01.ogg', 50, TRUE)
+ UpdateButtonIcon()
+
+///swap seats, for two person mecha
+/datum/action/vehicle/sealed/mecha/swap_seat
+ name = "Switch Seats"
+ button_icon_state = "mech_seat_swap"
+
+/datum/action/vehicle/sealed/mecha/swap_seat/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+
+ if(chassis.occupants.len == chassis.max_occupants)
+ to_chat(owner, "The other seat is occupied!")
+ return
+ var/list/drivers = chassis.return_drivers()
+ to_chat(owner, "Switching seats...")
+ chassis.is_currently_ejecting = TRUE
+ if(!do_after(owner, chassis.has_gravity() ? chassis.exit_delay : 0 , target = chassis))
+ chassis.is_currently_ejecting = FALSE
+ return
+ chassis.is_currently_ejecting = FALSE
+ if(owner in drivers)
+ to_chat(owner, "You shift to the gunner seat!")
+ chassis.remove_control_flags(owner, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS)
+ chassis.add_control_flags(owner, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
+ else
+ to_chat(owner, "You shift to the pilot seat!")
+ chassis.remove_control_flags(owner, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
+ chassis.add_control_flags(owner, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS)
+ chassis.update_icon_state()
+
+/datum/action/vehicle/sealed/mecha/mech_toggle_phasing
+ name = "Toggle Phasing"
+ button_icon_state = "mech_phasing_off"
+
+/datum/action/vehicle/sealed/mecha/mech_toggle_phasing/Trigger()
+ if(!owner || !chassis || !(owner in chassis.occupants))
+ return
+ chassis.phasing = !chassis.phasing
+ button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]"
+ to_chat(owner, "[icon2html(chassis, owner)]En":"#f00\">Dis"]abled phasing.")
+ UpdateButtonIcon()
+
+/datum/action/vehicle/sealed/mecha/climb_out
+ name = "Eject From Mech"
+ button_icon_state = "mech_eject"
diff --git a/code/modules/vehicles/mecha/mecha_construction_paths.dm b/code/modules/vehicles/mecha/mecha_construction_paths.dm
new file mode 100644
index 0000000000..d0fa7aca0b
--- /dev/null
+++ b/code/modules/vehicles/mecha/mecha_construction_paths.dm
@@ -0,0 +1,1608 @@
+////////////////////////////////
+///// Construction datums //////
+////////////////////////////////
+/datum/component/construction/mecha
+ var/base_icon
+
+ // Component typepaths.
+ // most must be defined unless
+ // get_steps is overriden.
+
+ // Circuit board typepaths.
+ // circuit_control and circuit_periph must be defined
+ // unless get_circuit_steps is overriden.
+ var/circuit_control
+ var/circuit_periph
+ var/circuit_weapon
+
+ // Armor plating typepaths. both must be defined
+ // unless relevant step procs are overriden. amounts
+ // must be defined if using /obj/item/stack/sheet types
+ var/inner_plating
+ var/inner_plating_amount
+
+ var/outer_plating
+ var/outer_plating_amount
+
+/datum/component/construction/mecha/spawn_result()
+ if(!result)
+ return
+ // Remove default mech power cell, as we replace it with a new one.
+ var/obj/vehicle/sealed/mecha/M = new result(drop_location())
+ QDEL_NULL(M.cell)
+ QDEL_NULL(M.scanmod)
+ QDEL_NULL(M.capacitor)
+
+ var/obj/item/mecha_parts/chassis/parent_chassis = parent
+ M.CheckParts(parent_chassis.contents)
+
+ SSblackbox.record_feedback("tally", "mechas_created", 1, M.name)
+ QDEL_NULL(parent)
+
+// Default proc to generate mech steps.
+// Override if the mech needs an entirely custom process (See HONK mech)
+// Otherwise override specific steps as needed (Ripley, Clarke, Phazon)
+/datum/component/construction/mecha/proc/get_steps()
+ return get_frame_steps() + get_circuit_steps() + (circuit_weapon ? get_circuit_weapon_steps() : list()) + get_stockpart_steps() + get_inner_plating_steps() + get_outer_plating_steps()
+
+/datum/component/construction/mecha/update_parent(step_index)
+ steps = get_steps()
+ ..()
+ // By default, each step in mech construction has a single icon_state:
+ // "[base_icon][index - 1]"
+ // For example, Ripley's step 1 icon_state is "ripley0".
+ var/atom/parent_atom = parent
+ if(!steps[index]["icon_state"] && base_icon)
+ parent_atom.icon_state = "[base_icon][index - 1]"
+
+/datum/component/construction/unordered/mecha_chassis/custom_action(obj/item/I, mob/living/user, typepath)
+ . = user.transferItemToLoc(I, parent)
+ if(.)
+ var/atom/parent_atom = parent
+ user.visible_message("[user] connects [I] to [parent].", "You connect [I] to [parent].")
+ parent_atom.add_overlay(I.icon_state+"+o")
+ qdel(I)
+
+/datum/component/construction/unordered/mecha_chassis/spawn_result()
+ var/atom/parent_atom = parent
+ parent_atom.icon = 'icons/mecha/mech_construction.dmi'
+ parent_atom.density = TRUE
+ parent_atom.cut_overlays()
+ ..()
+
+// Default proc for the first steps of mech construction.
+/datum/component/construction/mecha/proc/get_frame_steps()
+ return list(
+ list(
+ "key" = TOOL_WRENCH,
+ "desc" = "The hydraulic systems are disconnected."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "The hydraulic systems are connected."
+ ),
+ list(
+ "key" = /obj/item/stack/cable_coil,
+ "amount" = 5,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The hydraulic systems are active."
+ ),
+ list(
+ "key" = TOOL_WIRECUTTER,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The wiring is added."
+ )
+ )
+
+// Default proc for the circuit board steps of a mech.
+// Second set of steps by default.
+/datum/component/construction/mecha/proc/get_circuit_steps()
+ return list(
+ list(
+ "key" = circuit_control,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The wiring is adjusted."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Central control module is installed."
+ ),
+ list(
+ "key" = circuit_periph,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Central control module is secured."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Peripherals control module is installed."
+ )
+ )
+
+// Default proc for weapon circuitboard steps
+// Used by combat mechs
+/datum/component/construction/mecha/proc/get_circuit_weapon_steps()
+ return list(
+ list(
+ "key" = circuit_weapon,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Peripherals control module is secured."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Weapons control module is installed."
+ )
+ )
+
+// Default proc for stock part installation
+// Third set of steps by default
+/datum/component/construction/mecha/proc/get_stockpart_steps()
+ var/prevstep_text = circuit_weapon ? "Weapons control module is secured." : "Peripherals control module is secured."
+ return list(
+ list(
+ "key" = /obj/item/stock_parts/scanning_module,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = prevstep_text
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Scanner module is installed."
+ ),
+ list(
+ "key" = /obj/item/stock_parts/capacitor,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Scanner module is secured."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Capacitor is installed."
+ ),
+ list(
+ "key" = /obj/item/stock_parts/cell,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Capacitor is secured."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "The power cell is installed."
+ )
+ )
+
+// Default proc for inner armor plating
+// Fourth set of steps by default
+/datum/component/construction/mecha/proc/get_inner_plating_steps()
+ var/list/first_step
+ if(ispath(inner_plating, /obj/item/stack/sheet))
+ first_step = list(
+ list(
+ "key" = inner_plating,
+ "amount" = inner_plating_amount,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The power cell is secured."
+ )
+ )
+ else
+ first_step = list(
+ list(
+ "key" = inner_plating,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The power cell is secured."
+ )
+ )
+
+ return first_step + list(
+ list(
+ "key" = TOOL_WRENCH,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Inner plating is installed."
+ ),
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "Inner Plating is wrenched."
+ )
+ )
+
+// Default proc for outer armor plating
+// Fifth set of steps by default
+/datum/component/construction/mecha/proc/get_outer_plating_steps()
+ var/list/first_step
+ if(ispath(outer_plating, /obj/item/stack/sheet))
+ first_step = list(
+ list(
+ "key" = outer_plating,
+ "amount" = outer_plating_amount,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Inner plating is welded."
+ )
+ )
+ else
+ first_step = list(
+ list(
+ "key" = outer_plating,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Inner plating is welded."
+ )
+ )
+
+ return first_step + list(
+ list(
+ "key" = TOOL_WRENCH,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "External armor is installed."
+ ),
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "External armor is wrenched."
+ )
+ )
+
+
+/datum/component/construction/unordered/mecha_chassis/ripley
+ result = /datum/component/construction/mecha/ripley
+ steps = list(
+ /obj/item/mecha_parts/part/ripley_torso,
+ /obj/item/mecha_parts/part/ripley_left_arm,
+ /obj/item/mecha_parts/part/ripley_right_arm,
+ /obj/item/mecha_parts/part/ripley_left_leg,
+ /obj/item/mecha_parts/part/ripley_right_leg
+ )
+
+/datum/component/construction/mecha/ripley
+ result = /obj/vehicle/sealed/mecha/working/ripley
+ base_icon = "ripley"
+
+ circuit_control = /obj/item/circuitboard/mecha/ripley/main
+ circuit_periph = /obj/item/circuitboard/mecha/ripley/peripherals
+
+ inner_plating=/obj/item/stack/sheet/metal
+ inner_plating_amount = 5
+
+ outer_plating=/obj/item/stack/rods
+ outer_plating_amount = 10
+
+/datum/component/construction/mecha/ripley/get_outer_plating_steps()
+ return list(
+ list(
+ "key" = /obj/item/stack/rods,
+ "amount" = 10,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Outer Plating is welded."
+ ),
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WIRECUTTER,
+ "desc" = "Cockpit wire screen is installed."
+ ),
+ )
+
+/datum/component/construction/mecha/ripley/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems.", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems.", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures [I].", "You secure [I].")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I].", "You install [I].")
+ else
+ user.visible_message("[user] unsecures the capacitor from [parent].", "You unsecure the capacitor from [parent].")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.")
+ else
+ user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the external reinforced armor layer to [parent].", "You install the external reinforced armor layer to [parent].")
+ else
+ user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the external armor layer.", "You secure the external reinforced armor layer.")
+ else
+ user.visible_message("[user] pries external armor layer from [parent].", "You pry external armor layer from [parent].")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the external armor layer to [parent].", "You weld the external armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.")
+ return TRUE
+
+/datum/component/construction/unordered/mecha_chassis/gygax
+ result = /datum/component/construction/mecha/gygax
+ steps = list(
+ /obj/item/mecha_parts/part/gygax_torso,
+ /obj/item/mecha_parts/part/gygax_left_arm,
+ /obj/item/mecha_parts/part/gygax_right_arm,
+ /obj/item/mecha_parts/part/gygax_left_leg,
+ /obj/item/mecha_parts/part/gygax_right_leg,
+ /obj/item/mecha_parts/part/gygax_head
+ )
+
+/datum/component/construction/mecha/gygax
+ result = /obj/vehicle/sealed/mecha/combat/gygax
+ base_icon = "gygax"
+
+ circuit_control = /obj/item/circuitboard/mecha/gygax/main
+ circuit_periph = /obj/item/circuitboard/mecha/gygax/peripherals
+ circuit_weapon = /obj/item/circuitboard/mecha/gygax/targeting
+
+ inner_plating = /obj/item/stack/sheet/metal
+ inner_plating_amount = 5
+
+ outer_plating=/obj/item/mecha_parts/part/gygax_armor
+ outer_plating_amount=1
+
+/datum/component/construction/mecha/gygax/action(datum/source, atom/used_atom, mob/user)
+ return check_step(used_atom,user)
+
+/datum/component/construction/mecha/gygax/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems.", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems.", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.")
+ else
+ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the capacitor.", "You secure the capacitor.")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.")
+ else
+ user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].")
+ if(21)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures Gygax Armor Plates.", "You secure Gygax Armor Plates.")
+ else
+ user.visible_message("[user] pries Gygax Armor Plates from [parent].", "You pry Gygax Armor Plates from [parent].")
+ if(22)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds Gygax Armor Plates to [parent].", "You weld Gygax Armor Plates to [parent].")
+ else
+ user.visible_message("[user] unfastens Gygax Armor Plates.", "You unfasten Gygax Armor Plates.")
+ return TRUE
+
+//Begin Medigax
+/datum/component/construction/unordered/mecha_chassis/medigax
+ result = /datum/component/construction/mecha/medigax
+ steps = list(
+ /obj/item/mecha_parts/part/medigax_torso,
+ /obj/item/mecha_parts/part/medigax_left_arm,
+ /obj/item/mecha_parts/part/medigax_right_arm,
+ /obj/item/mecha_parts/part/medigax_left_leg,
+ /obj/item/mecha_parts/part/medigax_right_leg,
+ /obj/item/mecha_parts/part/medigax_head
+ )
+
+/datum/component/construction/mecha/medigax
+ result = /obj/vehicle/sealed/mecha/medical/medigax
+ base_icon = "medigax"
+ steps = list(
+ //1
+ list(
+ "key" = TOOL_WRENCH,
+ "desc" = "The hydraulic systems are disconnected."
+ ),
+
+ //2
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "The hydraulic systems are connected."
+ ),
+
+ //3
+ list(
+ "key" = /obj/item/stack/cable_coil,
+ "amount" = 5,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The hydraulic systems are active."
+ ),
+
+ //4
+ list(
+ "key" = TOOL_WIRECUTTER,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The wiring is added."
+ ),
+
+ //5
+ list(
+ "key" = /obj/item/circuitboard/mecha/gygax/main,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The wiring is adjusted."
+ ),
+
+ //6
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Central control module is installed."
+ ),
+
+ //7
+ list(
+ "key" = /obj/item/circuitboard/mecha/gygax/peripherals,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Central control module is secured."
+ ),
+
+ //8
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Peripherals control module is installed."
+ ),
+
+ //9
+ list(
+ "key" = /obj/item/circuitboard/mecha/gygax/targeting,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Peripherals control module is secured."
+ ),
+
+ //10
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Weapon control module is installed."
+ ),
+
+ //11
+ list(
+ "key" = /obj/item/stock_parts/scanning_module,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Weapon control module is secured."
+ ),
+
+ //12
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Scanner module is installed."
+ ),
+
+ //13
+ list(
+ "key" = /obj/item/stock_parts/capacitor,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Scanner module is secured."
+ ),
+
+ //14
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Capacitor is installed."
+ ),
+
+ //15
+ list(
+ "key" = /obj/item/stock_parts/cell,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Capacitor is secured."
+ ),
+
+ //16
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "The power cell is installed."
+ ),
+
+ //17
+ list(
+ "key" = /obj/item/stack/sheet/metal,
+ "amount" = 5,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The power cell is secured."
+ ),
+
+ //18
+ list(
+ "key" = TOOL_WRENCH,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Internal armor is installed."
+ ),
+
+ //19
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "Internal armor is wrenched."
+ ),
+
+ //20
+ list(
+ "key" = /obj/item/mecha_parts/part/medigax_armor,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Internal armor is welded."
+ ),
+
+ //21
+ list(
+ "key" = TOOL_WRENCH,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "External armor is installed."
+ ),
+
+ //22
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "External armor is wrenched."
+ ),
+
+ )
+
+/datum/component/construction/mecha/medigax/action(datum/source, atom/used_atom, mob/user)
+ return check_step(used_atom,user)
+
+/datum/component/construction/mecha/medigax/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.")
+ else
+ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the capacitor.", "You secure the capacitor.")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.")
+ else
+ user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].")
+ if(21)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures Gygax Armor Plates.", "You secure Medical Gygax Armor Plates.")
+ else
+ user.visible_message("[user] pries Gygax Armor Plates from [parent].", "You pry Medical Gygax Armor Plates from [parent].")
+ if(22)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds Gygax Armor Plates to [parent].", "You weld Medical Gygax Armor Plates to [parent].")
+ else
+ user.visible_message("[user] unfastens Gygax Armor Plates.", "You unfasten Medical Gygax Armor Plates.")
+ return TRUE
+// End Medigax
+
+/datum/component/construction/unordered/mecha_chassis/firefighter
+ result = /datum/component/construction/mecha/firefighter
+ steps = list(
+ /obj/item/mecha_parts/part/ripley_torso,
+ /obj/item/mecha_parts/part/ripley_left_arm,
+ /obj/item/mecha_parts/part/ripley_right_arm,
+ /obj/item/mecha_parts/part/ripley_left_leg,
+ /obj/item/mecha_parts/part/ripley_right_leg
+ )
+
+/datum/component/construction/mecha/firefighter
+ result = /obj/vehicle/sealed/mecha/working/ripley/firefighter
+ base_icon = "firefighter"
+
+ circuit_control = /obj/item/circuitboard/mecha/ripley/main
+ circuit_periph = /obj/item/circuitboard/mecha/ripley/peripherals
+
+ inner_plating= /obj/item/clothing/suit/fire
+ inner_plating_amount = 1
+
+ outer_plating=/obj/item/stack/sheet/plasteel
+ outer_plating_amount = 10
+
+/datum/component/construction/mecha/firefighter/get_outer_plating_steps()
+ return list(
+ list(
+ "key" = /obj/item/stack/sheet/plasteel,
+ "amount" = 10,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Outer plating is welded."
+ ),
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "Outer plating is complete."
+ ),
+ )
+
+/datum/component/construction/mecha/firefighter/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems.", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems.", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures [I].", "You secure [I].")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I].", "You install [I].")
+ else
+ user.visible_message("[user] unsecures the capacitor from [parent].", "You unsecure the capacitor from [parent].")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.")
+ else
+ user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the external reinforced armor layer to [parent].", "You install the external reinforced armor layer to [parent].")
+ else
+ user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the external armor layer.", "You secure the external reinforced armor layer.")
+ else
+ user.visible_message("[user] pries external armor layer from [parent].", "You pry external armor layer from [parent].")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the external armor layer to [parent].", "You weld the external armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.")
+ return TRUE
+
+/datum/component/construction/unordered/mecha_chassis/honker
+ result = /datum/component/construction/mecha/honker
+ steps = list(
+ /obj/item/mecha_parts/part/honker_torso,
+ /obj/item/mecha_parts/part/honker_left_arm,
+ /obj/item/mecha_parts/part/honker_right_arm,
+ /obj/item/mecha_parts/part/honker_left_leg,
+ /obj/item/mecha_parts/part/honker_right_leg,
+ /obj/item/mecha_parts/part/honker_head
+ )
+
+/datum/component/construction/mecha/honker
+ result = /obj/vehicle/sealed/mecha/combat/honker
+ steps = list(
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/circuitboard/mecha/honker/main,
+ "action" = ITEM_DELETE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/circuitboard/mecha/honker/peripherals,
+ "action" = ITEM_DELETE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/circuitboard/mecha/honker/targeting,
+ "action" = ITEM_DELETE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/stock_parts/scanning_module,
+ "action" = ITEM_MOVE_INSIDE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/stock_parts/capacitor,
+ "action" = ITEM_MOVE_INSIDE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/stock_parts/cell,
+ "action" = ITEM_MOVE_INSIDE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/clothing/mask/gas/clown_hat,
+ "action" = ITEM_DELETE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ list(
+ "key" = /obj/item/clothing/shoes/clown_shoes,
+ "action" = ITEM_DELETE
+ ),
+ list(
+ "key" = /obj/item/bikehorn
+ ),
+ )
+
+/datum/component/construction/mecha/honker/get_steps()
+ return steps
+
+// HONK doesn't have any construction step icons, so we just set an icon once.
+/datum/component/construction/mecha/honker/update_parent(step_index)
+ if(step_index == 1)
+ var/atom/parent_atom = parent
+ parent_atom.icon = 'icons/mecha/mech_construct.dmi'
+ parent_atom.icon_state = "honker_chassis"
+ ..()
+
+/datum/component/construction/mecha/honker/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ if(istype(I, /obj/item/bikehorn))
+ playsound(parent, 'sound/items/bikehorn.ogg', 50, TRUE)
+ user.visible_message("HONK!")
+
+ //TODO: better messages.
+ switch(index)
+ if(2)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ if(4)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ if(6)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ if(8)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ if(10)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ if(12)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ if(14)
+ user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].")
+ if(16)
+ user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].")
+ return TRUE
+
+/datum/component/construction/unordered/mecha_chassis/durand
+ result = /datum/component/construction/mecha/durand
+ steps = list(
+ /obj/item/mecha_parts/part/durand_torso,
+ /obj/item/mecha_parts/part/durand_left_arm,
+ /obj/item/mecha_parts/part/durand_right_arm,
+ /obj/item/mecha_parts/part/durand_left_leg,
+ /obj/item/mecha_parts/part/durand_right_leg,
+ /obj/item/mecha_parts/part/durand_head
+ )
+
+/datum/component/construction/mecha/durand
+ result = /obj/vehicle/sealed/mecha/combat/durand
+ base_icon = "durand"
+
+ circuit_control = /obj/item/circuitboard/mecha/durand/main
+ circuit_periph = /obj/item/circuitboard/mecha/durand/peripherals
+ circuit_weapon = /obj/item/circuitboard/mecha/durand/targeting
+
+ inner_plating = /obj/item/stack/sheet/metal
+ inner_plating_amount = 5
+
+ outer_plating = /obj/item/mecha_parts/part/durand_armor
+ outer_plating_amount = 1
+
+/datum/component/construction/mecha/durand/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ //TODO: better messages.
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems.", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems.", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.")
+ else
+ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the capacitor.", "You secure the capacitor.")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.")
+ else
+ user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].")
+ if(21)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures Durand Armor Plates.", "You secure Durand Armor Plates.")
+ else
+ user.visible_message("[user] pries Durand Armor Plates from [parent].", "You pry Durand Armor Plates from [parent].")
+ if(22)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds Durand Armor Plates to [parent].", "You weld Durand Armor Plates to [parent].")
+ else
+ user.visible_message("[user] unfastens Durand Armor Plates.", "You unfasten Durand Armor Plates.")
+ return TRUE
+
+//PHAZON
+
+/datum/component/construction/unordered/mecha_chassis/phazon
+ result = /datum/component/construction/mecha/phazon
+ steps = list(
+ /obj/item/mecha_parts/part/phazon_torso,
+ /obj/item/mecha_parts/part/phazon_left_arm,
+ /obj/item/mecha_parts/part/phazon_right_arm,
+ /obj/item/mecha_parts/part/phazon_left_leg,
+ /obj/item/mecha_parts/part/phazon_right_leg,
+ /obj/item/mecha_parts/part/phazon_head
+ )
+
+/datum/component/construction/mecha/phazon
+ result = /obj/vehicle/sealed/mecha/combat/phazon
+ base_icon = "phazon"
+
+ circuit_control = /obj/item/circuitboard/mecha/phazon/main
+ circuit_periph = /obj/item/circuitboard/mecha/phazon/peripherals
+ circuit_weapon = /obj/item/circuitboard/mecha/phazon/targeting
+
+ inner_plating = /obj/item/stack/sheet/plasteel
+ inner_plating_amount = 5
+
+ outer_plating = /obj/item/mecha_parts/part/phazon_armor
+ outer_plating_amount = 1
+
+/datum/component/construction/mecha/phazon/get_stockpart_steps()
+ return list(
+ list(
+ "key" = /obj/item/stock_parts/scanning_module,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Weapon control module is secured."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Scanner module is installed."
+ ),
+ list(
+ "key" = /obj/item/stock_parts/capacitor,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Scanner module is secured."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "Capacitor is installed."
+ ),
+ list(
+ "key" = /obj/item/stack/ore/bluespace_crystal,
+ "amount" = 1,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "Capacitor is secured."
+ ),
+ list(
+ "key" = /obj/item/stack/cable_coil,
+ "amount" = 5,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "The bluespace crystal is installed."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_WIRECUTTER,
+ "desc" = "The bluespace crystal is connected."
+ ),
+ list(
+ "key" = /obj/item/stock_parts/cell,
+ "action" = ITEM_MOVE_INSIDE,
+ "back_key" = TOOL_SCREWDRIVER,
+ "desc" = "The bluespace crystal is engaged."
+ ),
+ list(
+ "key" = TOOL_SCREWDRIVER,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "The power cell is installed.",
+ "icon_state" = "phazon17"
+ // This is the point where a step icon is skipped, so "icon_state" had to be set manually starting from here.
+ )
+ )
+
+/datum/component/construction/mecha/phazon/get_outer_plating_steps()
+ return list(
+ list(
+ "key" = outer_plating,
+ "amount" = 1,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Internal armor is welded."
+ ),
+ list(
+ "key" = TOOL_WRENCH,
+ "back_key" = TOOL_CROWBAR,
+ "desc" = "External armor is installed."
+ ),
+ list(
+ "key" = TOOL_WELDER,
+ "back_key" = TOOL_WRENCH,
+ "desc" = "External armor is wrenched."
+ ),
+ list(
+ "key" = /obj/item/assembly/signaler/anomaly/bluespace,
+ "action" = ITEM_DELETE,
+ "back_key" = TOOL_WELDER,
+ "desc" = "Bluespace anomaly core socket is open.",
+ "icon_state" = "phazon24"
+ )
+ )
+
+/datum/component/construction/mecha/phazon/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ //TODO: better messages.
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems.", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems.", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.")
+ else
+ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the capacitor.", "You secure the capacitor.")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I].", "You install [I].")
+ else
+ user.visible_message("[user] unsecures the capacitor from [parent].", "You unsecure the capacitor from [parent].")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] connects the bluespace crystal.", "You connect the bluespace crystal.")
+ else
+ user.visible_message("[user] removes the bluespace crystal from [parent].", "You remove the bluespace crystal from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] engages the bluespace crystal.", "You engage the bluespace crystal.")
+ else
+ user.visible_message("[user] disconnects the bluespace crystal from [parent].", "You disconnect the bluespace crystal from [parent].")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disengages the bluespace crystal.", "You disengage the bluespace crystal.")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the phase armor layer to [parent].", "You install the phase armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(21)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the phase armor layer.", "You secure the phase armor layer.")
+ else
+ user.visible_message("[user] pries the phase armor layer from [parent].", "You pry the phase armor layer from [parent].")
+ if(22)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the phase armor layer to [parent].", "You weld the phase armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the phase armor layer.", "You unfasten the phase armor layer.")
+ if(23)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] cuts phase armor layer from [parent].", "You cut the phase armor layer from [parent].")
+ if(24)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures Phazon Armor Plates.", "You secure Phazon Armor Plates.")
+ else
+ user.visible_message("[user] pries Phazon Armor Plates from [parent].", "You pry Phazon Armor Plates from [parent].")
+ if(25)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds Phazon Armor Plates to [parent].", "You weld Phazon Armor Plates to [parent].")
+ else
+ user.visible_message("[user] unfastens Phazon Armor Plates.", "You unfasten Phazon Armor Plates.")
+ if(26)
+ if(diff==FORWARD)
+ user.visible_message("[user] carefully inserts the bluespace anomaly core into [parent] and secures it.",
+ "You slowly place the bluespace anomaly core into its socket and close its chamber.")
+ return TRUE
+
+//ODYSSEUS
+
+/datum/component/construction/unordered/mecha_chassis/odysseus
+ result = /datum/component/construction/mecha/odysseus
+ steps = list(
+ /obj/item/mecha_parts/part/odysseus_torso,
+ /obj/item/mecha_parts/part/odysseus_head,
+ /obj/item/mecha_parts/part/odysseus_left_arm,
+ /obj/item/mecha_parts/part/odysseus_right_arm,
+ /obj/item/mecha_parts/part/odysseus_left_leg,
+ /obj/item/mecha_parts/part/odysseus_right_leg
+ )
+
+/datum/component/construction/mecha/odysseus
+ result = /obj/vehicle/sealed/mecha/medical/odysseus
+ base_icon = "odysseus"
+
+ circuit_control = /obj/item/circuitboard/mecha/odysseus/main
+ circuit_periph = /obj/item/circuitboard/mecha/odysseus/peripherals
+
+ inner_plating = /obj/item/stack/sheet/metal
+ inner_plating_amount = 5
+
+ outer_plating = /obj/item/stack/sheet/plasteel
+ outer_plating_amount = 5
+
+/datum/component/construction/mecha/odysseus/custom_action(obj/item/I, mob/living/user, diff)
+ if(!..())
+ return FALSE
+
+ //TODO: better messages.
+ switch(index)
+ if(1)
+ user.visible_message("[user] connects [parent] hydraulic systems.", "You connect [parent] hydraulic systems.")
+ if(2)
+ if(diff==FORWARD)
+ user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.")
+ else
+ user.visible_message("[user] disconnects [parent] hydraulic systems.", "You disconnect [parent] hydraulic systems.")
+ if(3)
+ if(diff==FORWARD)
+ user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].")
+ else
+ user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.")
+ if(4)
+ if(diff==FORWARD)
+ user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].")
+ else
+ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].")
+ if(5)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].")
+ if(6)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the mainboard.", "You secure the mainboard.")
+ else
+ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].")
+ if(7)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.")
+ if(8)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.")
+ else
+ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].")
+ if(9)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.")
+ if(10)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the scanner module.", "You secure the scanner module.")
+ else
+ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].")
+ if(11)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].")
+ else
+ user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.")
+ if(12)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the capacitor.", "You secure the capacitor.")
+ else
+ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].")
+ if(13)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].")
+ else
+ user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.")
+ if(14)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the power cell.", "You secure the power cell.")
+ else
+ user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].")
+ if(15)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.")
+ if(16)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.")
+ else
+ user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].")
+ if(17)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.")
+ if(18)
+ if(diff==FORWARD)
+ user.visible_message("[user] installs the external armor layer to [parent].", "You install the external reinforced armor layer to [parent].")
+ else
+ user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].")
+ if(19)
+ if(diff==FORWARD)
+ user.visible_message("[user] secures the external armor layer.", "You secure the external reinforced armor layer.")
+ else
+ user.visible_message("[user] pries the external armor layer from [parent].", "You pry the external armor layer from [parent].")
+ if(20)
+ if(diff==FORWARD)
+ user.visible_message("[user] welds the external armor layer to [parent].", "You weld the external armor layer to [parent].")
+ else
+ user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.")
+ return TRUE
diff --git a/code/game/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm
similarity index 77%
rename from code/game/mecha/mecha_control_console.dm
rename to code/modules/vehicles/mecha/mecha_control_console.dm
index ab547f4ccd..38224fbbdd 100644
--- a/code/game/mecha/mecha_control_console.dm
+++ b/code/modules/vehicles/mecha/mecha_control_console.dm
@@ -16,29 +16,29 @@
var/list/data = list()
var/list/trackerlist = list()
- for(var/obj/mecha/MC in GLOB.mechas_list)
+ for(var/obj/vehicle/sealed/mecha/MC in GLOB.mechas_list)
trackerlist += MC.trackers
data["mechs"] = list()
for(var/obj/item/mecha_parts/mecha_tracking/MT in trackerlist)
if(!MT.chassis)
continue
- var/obj/mecha/M = MT.chassis
+ var/obj/vehicle/sealed/mecha/M = MT.chassis
var/list/mech_data = list(
name = M.name,
integrity = round((M.obj_integrity / M.max_integrity) * 100),
charge = M.cell ? round(M.cell.percent()) : null,
airtank = M.internal_tank ? M.return_pressure() : null,
- pilot = list(M.occupant),
+ pilot = M.return_drivers(),
location = get_area_name(M, TRUE),
active_equipment = M.selected,
emp_recharging = MT.recharging,
tracker_ref = REF(MT)
)
- if(istype(M, /obj/mecha/working/ripley))
- var/obj/mecha/working/ripley/RM = M
+ if(istype(M, /obj/vehicle/sealed/mecha/working/ripley))
+ var/obj/vehicle/sealed/mecha/working/ripley/RM = M
mech_data += list(
- cargo_space = round((LAZYLEN(RM.cargo) / RM.cargo_capacity) * 100)
+ cargo_space = round((RM.cargo.len / RM.cargo_capacity) * 100)
)
data["mechs"] += list(mech_data)
@@ -46,8 +46,7 @@
return data
/obj/machinery/computer/mecha/ui_act(action, params)
- . = ..()
- if(.)
+ if(..())
return
switch(action)
@@ -56,20 +55,20 @@
if(!istype(MT))
return
var/message = stripped_input(usr, "Input message", "Transmit message")
- var/obj/mecha/M = MT.chassis
+ var/obj/vehicle/sealed/mecha/M = MT.chassis
if(trim(message) && M)
- to_chat(M.occupant, message)
+ to_chat(M.occupants, message)
to_chat(usr, "Message sent.")
. = TRUE
if("shock")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"])
if(!istype(MT))
return
- var/obj/mecha/M = MT.chassis
+ var/obj/vehicle/sealed/mecha/M = MT.chassis
if(M)
MT.shock()
- log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which [M.occupant ? "has the occupants [M.occupant]." : "without a pilot."] ")
- message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "occupied by [M.occupant][ADMIN_FLW(M)]." : "without a pilot."] ")
+ log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which [M.occupants ? "has the occupants [M.occupants]." : "without a pilot."] ")
+ message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupants ? "occupied by [M.occupants][ADMIN_FLW(M)]." : "without a pilot."] ")
. = TRUE
/obj/item/mecha_parts/mecha_tracking
@@ -83,11 +82,11 @@
/// Cooldown variable for EMP pulsing
var/recharging = FALSE
/// The Mecha that this tracking beacon is attached to
- var/obj/mecha/chassis
+ var/obj/vehicle/sealed/mecha/chassis
/**
- * Returns a html formatted string describing attached mech status
- */
+ * Returns a html formatted string describing attached mech status
+ */
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
if(!chassis)
return FALSE
@@ -97,12 +96,12 @@
Integrity: [round((chassis.obj_integrity/chassis.max_integrity * 100), 0.01)]%
Cell Charge: [isnull(cell_charge) ? "Not Found":"[chassis.cell.percent()]%"]
Airtank: [chassis.internal_tank ? "[round(chassis.return_pressure(), 0.01)]" : "Not Equipped"] kPa
- Pilot: [chassis.occupant || "None"]
+ Pilot: [chassis.return_drivers() || "None"]
Location: [get_area_name(chassis, TRUE) || "Unknown"]
Active Equipment: [chassis.selected || "None"]"}
- if(istype(chassis, /obj/mecha/working/ripley))
- var/obj/mecha/working/ripley/RM = chassis
- answer += "
Used Cargo Space: [round((LAZYLEN(RM.cargo) / RM.cargo_capacity * 100), 0.01)]%"
+ if(istype(chassis, /obj/vehicle/sealed/mecha/working/ripley))
+ var/obj/vehicle/sealed/mecha/working/ripley/RM = chassis
+ answer += "
Used Cargo Space: [round((RM.cargo.len / RM.cargo_capacity * 100), 0.01)]%"
return answer
@@ -118,7 +117,7 @@
chassis = null
return ..()
-/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/mecha/M)
+/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
if(!..())
return
M.trackers += src
@@ -126,8 +125,8 @@
chassis = M
/**
- * Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
- */
+ * Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
+ */
/obj/item/mecha_parts/mecha_tracking/proc/shock()
if(recharging)
return
@@ -137,8 +136,8 @@
recharging = TRUE
/**
- * Resets recharge variable, allowing tracker to be EMP pulsed again
- */
+ * Resets recharge variable, allowing tracker to be EMP pulsed again
+ */
/obj/item/mecha_parts/mecha_tracking/proc/recharge()
recharging = FALSE
diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm
new file mode 100644
index 0000000000..78b4c7b441
--- /dev/null
+++ b/code/modules/vehicles/mecha/mecha_defense.dm
@@ -0,0 +1,390 @@
+/obj/vehicle/sealed/mecha/proc/get_armour_facing(relative_dir)
+ switch(relative_dir)
+ if(180) // BACKSTAB!
+ return facing_modifiers[MECHA_BACK_ARMOUR]
+ if(0, 45) // direct or 45 degrees off
+ return facing_modifiers[MECHA_FRONT_ARMOUR]
+ return facing_modifiers[MECHA_SIDE_ARMOUR] //if its not a front hit or back hit then assume its from the side
+
+/obj/vehicle/sealed/mecha/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
+ . = ..()
+ if(. && obj_integrity > 0)
+ spark_system.start()
+ switch(damage_flag)
+ if(FIRE)
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL))
+ if(MELEE)
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ else
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT))
+ if(. >= 5 || prob(33))
+ to_chat(occupants, "[icon2html(src, occupants)]Taking damage!")
+ log_message("Took [damage_amount] points of damage. Damage type: [damage_type]", LOG_MECHA)
+
+/obj/vehicle/sealed/mecha/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
+ . = ..()
+ if(!damage_amount)
+ return 0
+ var/booster_deflection_modifier = 1
+ var/booster_damage_modifier = 1
+ if(damage_flag == BULLET || damage_flag == LASER || damage_flag == ENERGY)
+ for(var/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/B in equipment)
+ if(B.projectile_react())
+ booster_deflection_modifier = B.deflect_coeff
+ booster_damage_modifier = B.damage_coeff
+ break
+ else if(damage_flag == MELEE)
+ for(var/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/B in equipment)
+ if(B.attack_react())
+ booster_deflection_modifier *= B.deflect_coeff
+ booster_damage_modifier *= B.damage_coeff
+ break
+
+ if(attack_dir)
+ var/facing_modifier = get_armour_facing(abs(dir2angle(dir) - dir2angle(attack_dir)))
+ booster_damage_modifier /= facing_modifier
+ booster_deflection_modifier *= facing_modifier
+ if(prob(deflect_chance * booster_deflection_modifier))
+ visible_message("[src]'s armour deflects the attack!")
+ log_message("Armor saved.", LOG_MECHA)
+ return 0
+ if(.)
+ . *= booster_damage_modifier
+
+/obj/vehicle/sealed/mecha/attack_hand(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
+ playsound(loc, 'sound/weapons/tap.ogg', 40, TRUE, -1)
+ user.visible_message("[user] hits [name]. Nothing happens.", null, null, COMBAT_MESSAGE_RANGE)
+ log_message("Attack by hand/paw. Attacker - [user].", LOG_MECHA, color="red")
+
+/obj/vehicle/sealed/mecha/attack_paw(mob/user as mob)
+ return attack_hand(user)
+
+/obj/vehicle/sealed/mecha/attack_alien(mob/living/user)
+ log_message("Attack by alien. Attacker - [user].", LOG_MECHA, color="red")
+ playsound(src.loc, 'sound/weapons/slash.ogg', 100, TRUE)
+ attack_generic(user, 15, BRUTE, MELEE, 0)
+
+/obj/vehicle/sealed/mecha/attack_animal(mob/living/simple_animal/user)
+ log_message("Attack by simple animal. Attacker - [user].", LOG_MECHA, color="red")
+ if(!user.melee_damage_upper && !user.obj_damage)
+ user.emote("custom", message = "[user.friendly_verb_continuous] [src].")
+ return 0
+ else
+ var/play_soundeffect = 1
+ if(user.environment_smash)
+ play_soundeffect = 0
+ playsound(src, 'sound/effects/bang.ogg', 50, TRUE)
+ var/animal_damage = rand(user.melee_damage_lower,user.melee_damage_upper)
+ if(user.obj_damage)
+ animal_damage = user.obj_damage
+ animal_damage = min(animal_damage, 20*user.environment_smash)
+ log_combat(user, src, "attacked")
+ attack_generic(user, animal_damage, user.melee_damage_type, MELEE, play_soundeffect)
+ return 1
+
+
+/obj/vehicle/sealed/mecha/hulk_damage()
+ return 15
+
+/obj/vehicle/sealed/mecha/attack_hulk(mob/living/carbon/human/user)
+ . = ..()
+ if(.)
+ log_message("Attack by hulk. Attacker - [user].", LOG_MECHA, color="red")
+ log_combat(user, src, "punched", "hulk powers")
+
+/obj/vehicle/sealed/mecha/blob_act(obj/structure/blob/B)
+ log_message("Attack by blob. Attacker - [B].", LOG_MECHA, color="red")
+ take_damage(30, BRUTE, MELEE, 0, get_dir(src, B))
+
+/obj/vehicle/sealed/mecha/attack_tk()
+ return
+
+/obj/vehicle/sealed/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper
+ log_message("Hit by [AM].", LOG_MECHA, color="red")
+ . = ..()
+
+/obj/vehicle/sealed/mecha/bullet_act(obj/item/projectile/Proj) //wrapper
+ if(!enclosed && LAZYLEN(occupants) && !(mecha_flags & SILICON_PILOT) && !Proj.force_hit && (Proj.def_zone == BODY_ZONE_HEAD || Proj.def_zone == BODY_ZONE_CHEST)) //allows bullets to hit the pilot of open-canopy mechs
+ for(var/m in occupants)
+ var/mob/living/hitmob = m
+ hitmob.bullet_act(Proj) //If the sides are open, the occupant can be hit
+ return BULLET_ACT_HIT
+ log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).", LOG_MECHA, color="red")
+ . = ..()
+
+/obj/vehicle/sealed/mecha/ex_act(severity, target)
+ log_message("Affected by explosion of severity: [severity].", LOG_MECHA, color="red")
+ if(prob(deflect_chance))
+ severity++
+ log_message("Armor saved, changing severity to [severity]", LOG_MECHA)
+ . = ..()
+
+
+/obj/vehicle/sealed/mecha/contents_explosion(severity, target, origin)
+ severity++
+ for(var/X in equipment)
+ var/obj/item/mecha_parts/mecha_equipment/ME = X
+ ME.ex_act(severity, target, origin)
+ for(var/Y in trackers)
+ var/obj/item/mecha_parts/mecha_tracking/MT = Y
+ MT.ex_act(severity, target, origin)
+ for(var/Z in occupants)
+ var/mob/living/occupant = Z
+ occupant.ex_act(severity, target, origin)
+
+/obj/vehicle/sealed/mecha/handle_atom_del(atom/A)
+ if(A in occupants)
+ LAZYREMOVE(occupants, A)
+ icon_state = initial(icon_state)+"-open"
+ setDir(dir_in)
+
+/obj/vehicle/sealed/mecha/emp_act(severity)
+ . = ..()
+ if (. & EMP_PROTECT_SELF)
+ return
+ if(get_charge())
+ use_power((cell.charge/3)*(severity*0.005))
+ take_damage(severity/3, BURN, ENERGY, 1)
+ log_message("EMP detected", LOG_MECHA, color="red")
+
+ if(istype(src, /obj/vehicle/sealed/mecha/combat))
+ mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse-disable.dmi'
+ for(var/occus in occupants)
+ var/mob/living/occupant = occus
+ occupant.update_mouse_pointer()
+ if(!equipment_disabled && occupants) //prevent spamming this message with back-to-back EMPs
+ to_chat(occupants, "Error -- Connection to equipment control unit has been lost.")
+ addtimer(CALLBACK(src, /obj/vehicle/sealed/mecha/proc/restore_equipment), 3 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
+ equipment_disabled = 1
+
+/obj/vehicle/sealed/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature>max_temperature)
+ log_message("Exposed to dangerous temperature.", LOG_MECHA, color="red")
+ take_damage(5, BURN, 0, 1)
+
+/obj/vehicle/sealed/mecha/attackby(obj/item/W, mob/user, params)
+
+ if(istype(W, /obj/item/mmi))
+ if(mmi_move_inside(W,user))
+ to_chat(user, "[src]-[W] interface initialized successfully.")
+ else
+ to_chat(user, "[src]-[W] interface initialization failed.")
+ return
+
+ if(istype(W, /obj/item/mecha_ammo))
+ ammo_resupply(W, user)
+ return
+
+ if(W.GetID())
+ if((mecha_flags & ADDING_ACCESS_POSSIBLE) || (mecha_flags & ADDING_MAINT_ACCESS_POSSIBLE))
+ if(internals_access_allowed(user))
+ var/obj/item/card/id/id_card
+ if(istype(W, /obj/item/card/id))
+ id_card = W
+ else
+ var/obj/item/pda/pda = W
+ id_card = pda.id
+ output_maintenance_dialog(id_card, user)
+ return
+ to_chat(user, "Invalid ID: Access denied.")
+ return
+ to_chat(user, "Maintenance protocols disabled by operator.")
+ return
+
+ if(istype(W, /obj/item/stock_parts/cell))
+ if(construction_state == MECHA_OPEN_HATCH)
+ if(!cell)
+ if(!user.transferItemToLoc(W, src, silent = FALSE))
+ return
+ var/obj/item/stock_parts/cell/C = W
+ to_chat(user, "You install the power cell.")
+ playsound(src, 'sound/items/screwdriver2.ogg', 50, FALSE)
+ cell = C
+ log_message("Power cell installed", LOG_MECHA)
+ else
+ to_chat(user, "There's already a power cell installed!")
+ return
+
+ if(istype(W, /obj/item/stock_parts/scanning_module))
+ if(construction_state == MECHA_OPEN_HATCH)
+ if(!scanmod)
+ if(!user.transferItemToLoc(W, src))
+ return
+ to_chat(user, "You install the scanning module.")
+ playsound(src, 'sound/items/screwdriver2.ogg', 50, FALSE)
+ scanmod = W
+ log_message("[W] installed", LOG_MECHA)
+ update_part_values()
+ else
+ to_chat(user, "There's already a scanning module installed!")
+ return
+
+ if(istype(W, /obj/item/stock_parts/capacitor))
+ if(construction_state == MECHA_OPEN_HATCH)
+ if(!capacitor)
+ if(!user.transferItemToLoc(W, src))
+ return
+ to_chat(user, "You install the capacitor.")
+ playsound(src, 'sound/items/screwdriver2.ogg', 50, FALSE)
+ capacitor = W
+ log_message("[W] installed", LOG_MECHA)
+ update_part_values()
+ else
+ to_chat(user, "There's already a capacitor installed!")
+ return
+
+ if(istype(W, /obj/item/stack/cable_coil))
+ if(construction_state == MECHA_OPEN_HATCH && (internal_damage & MECHA_INT_SHORT_CIRCUIT))
+ var/obj/item/stack/cable_coil/CC = W
+ if(CC.use(2))
+ clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
+ to_chat(user, "You replace the fused wires.")
+ else
+ to_chat(user, "You need two lengths of cable to fix this mech!")
+ return
+
+ if(istype(W, /obj/item/mecha_parts))
+ var/obj/item/mecha_parts/P = W
+ P.try_attach_part(user, src)
+ return
+ if(istype(W, /obj/item/analyzer))
+ if(construction_state)
+ var/datum/gas_mixture/GasNux = internal_tank.return_air()
+ atmosanalyzer_scan(GasNux,user,src,TRUE)
+ else
+ atmosanalyzer_scan(cabin_air,user,src,TRUE)
+ return
+ log_message("Attacked by [W]. Attacker - [user]", LOG_MECHA)
+ return ..()
+
+/obj/vehicle/sealed/mecha/wrench_act(mob/living/user, obj/item/I)
+ ..()
+ . = TRUE
+ if(construction_state == MECHA_SECURE_BOLTS)
+ construction_state = MECHA_LOOSE_BOLTS
+ to_chat(user, "You undo the securing bolts.")
+ return
+ if(construction_state == MECHA_LOOSE_BOLTS)
+ construction_state = MECHA_SECURE_BOLTS
+ to_chat(user, "You tighten the securing bolts.")
+
+/obj/vehicle/sealed/mecha/crowbar_act(mob/living/user, obj/item/I)
+ ..()
+ . = TRUE
+ if(construction_state == MECHA_LOOSE_BOLTS)
+ construction_state = MECHA_OPEN_HATCH
+ to_chat(user, "You open the hatch to the power unit.")
+ return
+ if(construction_state == MECHA_OPEN_HATCH)
+ construction_state = MECHA_LOOSE_BOLTS
+ to_chat(user, "You close the hatch to the power unit.")
+
+/obj/vehicle/sealed/mecha/screwdriver_act(mob/living/user, obj/item/I)
+ ..()
+ . = TRUE
+ if(internal_damage & MECHA_INT_TEMP_CONTROL)
+ clearInternalDamage(MECHA_INT_TEMP_CONTROL)
+ to_chat(user, "You repair the damaged temperature controller.")
+ return
+
+/obj/vehicle/sealed/mecha/welder_act(mob/living/user, obj/item/W)
+ . = ..()
+ if(user.a_intent == INTENT_HARM)
+ return
+ . = TRUE
+ if(internal_damage & MECHA_INT_TANK_BREACH)
+ if(!W.use_tool(src, user, 0, volume=50, amount=1))
+ return
+ clearInternalDamage(MECHA_INT_TANK_BREACH)
+ to_chat(user, "You repair the damaged gas tank.")
+ return
+ if(obj_integrity < max_integrity)
+ if(!W.use_tool(src, user, 0, volume=50, amount=1))
+ return
+ user.visible_message("[user] repairs some damage to [name].", "You repair some damage to [src].")
+ obj_integrity += min(10, max_integrity-obj_integrity)
+ if(obj_integrity == max_integrity)
+ to_chat(user, "It looks to be fully repaired now.")
+ return
+ to_chat(user, "The [name] is at full integrity!")
+
+/obj/vehicle/sealed/mecha/proc/mech_toxin_damage(mob/living/target)
+ playsound(src, 'sound/effects/spray2.ogg', 50, TRUE)
+ if(target.reagents)
+ if(target.reagents.get_reagent_amount(/datum/reagent/cryptobiolin) + force < force*2)
+ target.reagents.add_reagent(/datum/reagent/cryptobiolin, force/2)
+ if(target.reagents.get_reagent_amount(/datum/reagent/toxin) + force < force*2)
+ target.reagents.add_reagent(/datum/reagent/toxin, force/2.5)
+
+
+/obj/vehicle/sealed/mecha/mech_melee_attack(obj/vehicle/sealed/mecha/M, mob/user)
+ if(!has_charge(melee_energy_drain))
+ return NONE
+ use_power(melee_energy_drain)
+ if(M.damtype == BRUTE || M.damtype == BURN)
+ log_combat(user, src, "attacked", M, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
+ . = ..()
+
+/obj/vehicle/sealed/mecha/proc/full_repair(charge_cell)
+ obj_integrity = max_integrity
+ if(cell && charge_cell)
+ cell.charge = cell.maxcharge
+ if(internal_damage & MECHA_INT_FIRE)
+ clearInternalDamage(MECHA_INT_FIRE)
+ if(internal_damage & MECHA_INT_TEMP_CONTROL)
+ clearInternalDamage(MECHA_INT_TEMP_CONTROL)
+ if(internal_damage & MECHA_INT_SHORT_CIRCUIT)
+ clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
+ if(internal_damage & MECHA_INT_TANK_BREACH)
+ clearInternalDamage(MECHA_INT_TANK_BREACH)
+ if(internal_damage & MECHA_INT_CONTROL_LOST)
+ clearInternalDamage(MECHA_INT_CONTROL_LOST)
+
+/obj/vehicle/sealed/mecha/narsie_act()
+ emp_act(80)
+
+/obj/vehicle/sealed/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+ if(!no_effect)
+ if(selected)
+ used_item = selected
+ else if(!visual_effect_icon)
+ visual_effect_icon = ATTACK_EFFECT_SMASH
+ if(damtype == BURN)
+ visual_effect_icon = ATTACK_EFFECT_MECHFIRE
+ else if(damtype == TOX)
+ visual_effect_icon = ATTACK_EFFECT_MECHTOXIN
+ ..()
+
+/obj/vehicle/sealed/mecha/obj_destruction()
+ if(wreckage)
+ var/mob/living/silicon/ai/AI
+ for(var/crew in occupants)
+ if(isAI(crew))
+ if(AI)
+ var/mob/living/silicon/ai/unlucky_ais = crew
+ unlucky_ais.gib()
+ continue
+ AI = crew
+ var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI)
+ for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
+ if(E.salvageable && prob(30))
+ WR.crowbar_salvage += E
+ E.detach(WR) //detaches from src into WR
+ E.equip_ready = 1
+ else
+ E.detach(loc)
+ qdel(E)
+ if(cell)
+ WR.crowbar_salvage += cell
+ cell.forceMove(WR)
+ cell.charge = rand(0, cell.charge)
+ cell = null
+ if(internal_tank)
+ WR.crowbar_salvage += internal_tank
+ internal_tank.forceMove(WR)
+ cell = null
+ . = ..()
diff --git a/code/game/mecha/mecha_parts.dm b/code/modules/vehicles/mecha/mecha_parts.dm
similarity index 95%
rename from code/game/mecha/mecha_parts.dm
rename to code/modules/vehicles/mecha/mecha_parts.dm
index 8a9e4e641f..31c4c72a2b 100644
--- a/code/game/mecha/mecha_parts.dm
+++ b/code/modules/vehicles/mecha/mecha_parts.dm
@@ -9,13 +9,16 @@
w_class = WEIGHT_CLASS_GIGANTIC
flags_1 = CONDUCT_1
-/obj/item/mecha_parts/proc/try_attach_part(mob/user, obj/mecha/M) //For attaching parts to a finished mech
+/obj/item/mecha_parts/proc/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M) //For attaching parts to a finished mech
if(!user.transferItemToLoc(src, M))
to_chat(user, "\The [src] is stuck to your hand, you cannot put it in \the [M]!")
return FALSE
user.visible_message("[user] attaches [src] to [M].", "You attach [src] to [M].")
return TRUE
-
+
+/obj/item/mecha_parts/part/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
+ return
+
/obj/item/mecha_parts/chassis
name = "Mecha Chassis"
icon_state = "backbone"
@@ -58,6 +61,12 @@
desc = "A Ripley APLU right leg. Contains somewhat complex servodrives and balance maintaining systems."
icon_state = "ripley_r_leg"
+
+//Firefighter
+/obj/item/mecha_parts/chassis/firefighter
+ name = "\improper Firefighter chassis"
+ construct_type = /datum/component/construction/unordered/mecha_chassis/firefighter
+
///////// Odysseus
/obj/item/mecha_parts/chassis/odysseus
@@ -220,12 +229,6 @@
desc = "A set of armor plates for the Durand. Built heavy to resist an incredible amount of brute force."
icon_state = "durand_armor"
-////////// Firefighter
-
-/obj/item/mecha_parts/chassis/firefighter
- name = "\improper Firefighter chassis"
- construct_type = /datum/component/construction/unordered/mecha_chassis/firefighter
-
////////// HONK
@@ -270,6 +273,11 @@
name = "\improper Phazon chassis"
construct_type = /datum/component/construction/unordered/mecha_chassis/phazon
+/obj/item/mecha_parts/chassis/phazon/attackby(obj/item/I, mob/user, params)
+ . = ..()
+ if(istype(I, /obj/item/assembly/signaler/anomaly) && !istype(I, /obj/item/assembly/signaler/anomaly/bluespace))
+ to_chat(user, "The anomaly core socket only accepts bluespace anomaly cores!")
+
/obj/item/mecha_parts/part/phazon_torso
name="\improper Phazon torso"
desc="A Phazon torso part. The socket for the bluespace core that powers the exosuit's unique phase drives is located in the middle."
@@ -312,7 +320,6 @@
name = "exosuit circuit board"
icon = 'icons/obj/module.dmi'
icon_state = "std_mod"
- item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
@@ -385,3 +392,11 @@
/obj/item/circuitboard/mecha/phazon/main
name = "Phazon Central Control module (Exosuit Board)"
+
+/obj/item/circuitboard/mecha/clarke/peripherals
+ name = "Clarke Peripherals Control module (Exosuit Board)"
+ icon_state = "mcontroller"
+
+/obj/item/circuitboard/mecha/clarke/main
+ name = "Clarke Central Control module (Exosuit Board)"
+ icon_state = "mainboard"
diff --git a/code/modules/vehicles/mecha/mecha_topic.dm b/code/modules/vehicles/mecha/mecha_topic.dm
new file mode 100644
index 0000000000..eb7dcd01db
--- /dev/null
+++ b/code/modules/vehicles/mecha/mecha_topic.dm
@@ -0,0 +1,421 @@
+
+////////////////////////////////////
+///// Rendering stats window ///////
+////////////////////////////////////
+
+/obj/vehicle/sealed/mecha/proc/get_stats_html(mob/user)
+ . = {"
+
+
+ [name] data
+
+
+
+
+
+ [get_stats_part(user)]
+
+