diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm
index 546ddcff7e4..a4485e0b8c5 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm
@@ -9,9 +9,7 @@
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"d" = (
-/obj/mecha/working/ripley/mining{
- ruin_mecha = 1
- },
+/obj/vehicle/sealed/mecha/working/ripley/mining,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"e" = (
diff --git a/_maps/RandomRuins/SpaceRuins/mechtransport.dmm b/_maps/RandomRuins/SpaceRuins/mechtransport.dmm
index 778809373dc..e715917000a 100644
--- a/_maps/RandomRuins/SpaceRuins/mechtransport.dmm
+++ b/_maps/RandomRuins/SpaceRuins/mechtransport.dmm
@@ -101,9 +101,7 @@
/turf/open/floor/mineral/titanium/yellow/airless,
/area/ruin/space/has_grav/powered/mechtransport)
"A" = (
-/obj/mecha/working/ripley{
- ruin_mecha = 1
- },
+/obj/vehicle/sealed/mecha/working/ripley,
/turf/open/floor/mineral/titanium/yellow/airless,
/area/ruin/space/has_grav/powered/mechtransport)
"B" = (
diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm
index 955f16277f2..1a86b6b07e0 100644
--- a/_maps/RandomZLevels/caves.dmm
+++ b/_maps/RandomZLevels/caves.dmm
@@ -2018,9 +2018,7 @@
},
/area/awaymission/caves/bmp_asteroid)
"gC" = (
-/obj/mecha/working/ripley/mining{
- ruin_mecha = 1
- },
+/obj/vehicle/sealed/mecha/working/ripley/mining,
/turf/open/floor/plasteel/recharge_floor,
/area/awaymission/caves/bmp_asteroid)
"gD" = (
diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm
index 58ee677789f..1ba6334ed50 100644
--- a/_maps/RandomZLevels/snowdin.dmm
+++ b/_maps/RandomZLevels/snowdin.dmm
@@ -13637,10 +13637,7 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/snowdin/post/mining_main/mechbay)
"In" = (
-/obj/mecha/working/ripley/mining{
- dir = 1;
- ruin_mecha = 1
- },
+/obj/vehicle/sealed/mecha/working/ripley/mining,
/obj/effect/turf_decal/bot,
/turf/open/floor/mech_bay_recharge_floor,
/area/awaymission/snowdin/post/mining_main/mechbay)
diff --git a/_maps/RandomZLevels/spacebattle.dmm b/_maps/RandomZLevels/spacebattle.dmm
index 17826ee8e9f..8105a180f17 100644
--- a/_maps/RandomZLevels/spacebattle.dmm
+++ b/_maps/RandomZLevels/spacebattle.dmm
@@ -815,13 +815,11 @@
/turf/open/floor/plasteel,
/area/awaymission/spacebattle/cruiser)
"dK" = (
-/obj/mecha/medical/odysseus,
+/obj/vehicle/sealed/mecha/medical/odysseus,
/turf/open/floor/plating,
/area/awaymission/spacebattle/cruiser)
"dL" = (
-/obj/mecha/working/clarke{
- ruin_mecha = 1
- },
+/obj/vehicle/sealed/mecha/working/clarke,
/turf/open/floor/plating,
/area/awaymission/spacebattle/cruiser)
"dM" = (
@@ -2366,7 +2364,7 @@
/turf/open/floor/plasteel/rockvault/alien,
/area/awaymission/spacebattle/secret)
"jp" = (
-/obj/mecha/combat/gygax,
+/obj/vehicle/sealed/mecha/combat/gygax,
/turf/open/floor/plating,
/area/awaymission/spacebattle/cruiser)
"jq" = (
@@ -2444,7 +2442,7 @@
/area/awaymission/spacebattle/cruiser)
"jz" = (
/mob/living/simple_animal/hostile/syndicate/mecha_pilot{
- spawn_mecha_type = /obj/mecha/combat/gygax/dark/loaded
+ spawn_mecha_type = /obj/vehicle/sealed/mecha/combat/gygax/dark/loaded
},
/turf/open/floor/plasteel,
/area/awaymission/spacebattle/cruiser)
@@ -2581,13 +2579,13 @@
/area/awaymission/spacebattle/cruiser)
"jV" = (
/mob/living/simple_animal/hostile/syndicate/mecha_pilot{
- spawn_mecha_type = /obj/mecha/combat/gygax/dark/loaded
+ spawn_mecha_type = /obj/vehicle/sealed/mecha/combat/gygax/dark/loaded
},
/turf/open/floor/plating/airless,
/area/awaymission/spacebattle/cruiser)
"jW" = (
/mob/living/simple_animal/hostile/syndicate/mecha_pilot{
- spawn_mecha_type = /obj/mecha/combat/gygax/dark/loaded
+ spawn_mecha_type = /obj/vehicle/sealed/mecha/combat/gygax/dark/loaded
},
/turf/open/floor/plasteel/airless,
/area/awaymission/spacebattle/cruiser)
diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm
index a6bceddbd73..adc4109a2be 100644
--- a/code/__DEFINES/cooldowns.dm
+++ b/code/__DEFINES/cooldowns.dm
@@ -29,6 +29,12 @@
#define COOLDOWN_BORG_SELF_REPAIR "borg_self_repair"
#define COOLDOWN_EXPRESSPOD_CONSOLE "expresspod_console"
+//Mecha cooldowns
+#define COOLDOWN_MECHA_MESSAGE "mecha_message"
+#define COOLDOWN_MECHA_EQUIPMENT "mecha_equipment"
+#define COOLDOWN_MECHA_ARMOR "mecha_armor"
+#define COOLDOWN_MECHA_MELEE_ATTACK "mecha_melee"
+#define COOLDOWN_MECHA_SMOKE "mecha_smoke"
//TIMER COOLDOWN MACROS
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index c64fcdefaca..658d1082b8b 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -608,11 +608,11 @@
///sent to targets during the process_hit proc of projectiles
#define COMSIG_PELLET_CLOUD_INIT "pellet_cloud_init"
-
-// /obj/mecha signals
+// /obj/vehicle/sealed/mecha signals
///sent from mecha action buttons to the mecha they're linked to
-#define COMSIG_MECHA_ACTION_ACTIVATE "mecha_action_activate"
+#define COMSIG_MECHA_ACTION_TRIGGER "mecha_action_activate"
+
// /mob/living/carbon/human signals
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 9ff6c8e84d2..1a0d829993c 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismachinery(A) (istype(A, /obj/machinery))
-#define ismecha(A) (istype(A, /obj/mecha))
+#define ismecha(A) (istype(A, /obj/vehicle/sealed/mecha))
#define ismopable(A) (A && (A.layer <= HIGH_SIGIL_LAYER)) //If something can be cleaned by floor-cleaning devices such as mops or clean bots
diff --git a/code/__DEFINES/vehicles.dm b/code/__DEFINES/vehicles.dm
index 48383546b9d..4b59e585aa3 100644
--- a/code/__DEFINES/vehicles.dm
+++ b/code/__DEFINES/vehicles.dm
@@ -4,6 +4,15 @@
#define VEHICLE_CONTROL_DRIVE 2
#define VEHICLE_CONTROL_KIDNAPPED 4 //Can't leave vehicle voluntarily, has to resist.
+//Mech flags
+#define ADDING_ACCESS_POSSIBLE (1<<0)
+#define ADDING_MAINT_ACCESS_POSSIBLE (1<<1)
+#define CANSTRAFE (1<<2)
+#define LIGHTS_ON (1<<3)
+#define SILICON_PILOT (1<<4)
+#define IS_ENCLOSED (1<<5)
+#define HAS_LIGHTS (1<<6)
+
//Car trait flags
#define CAN_KIDNAP 1
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index aaf004cc1a9..156432f74dc 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -24,6 +24,7 @@
#define reverseList(L) reverseRange(L.Copy())
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V);
#define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; }
+#define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null
/// Passed into BINARY_INSERT to compare keys
#define COMPARE_KEY __BIN_LIST[__BIN_MID]
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index ce5f6b451b0..14733e1881c 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -58,10 +58,6 @@
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
- if(modifiers["middle"])
- if(controlled_mech) //Are we piloting a mech? Placed here so the modifiers are not overridden.
- controlled_mech.click_action(A, src, params) //Override AI normal click behavior.
- return
if(modifiers["shift"])
ShiftClickOn(A)
return
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 1a6820170b9..28841f3d5ba 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -109,10 +109,6 @@
if(!modifiers["catcher"] && A.IsObscured())
return
- if(ismecha(loc))
- var/obj/mecha/M = loc
- return M.click_action(A,src,params)
-
if(restrained())
changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow
RestrainedClickOn(A)
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 5570b64d541..aabe5bf2e3f 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -29,7 +29,7 @@
/obj/screen/human/equip/Click()
if(ismecha(usr.loc)) // stops inventory actions in a mech
- return 1
+ return TRUE
var/mob/living/carbon/human/H = usr
H.quick_equip()
diff --git a/code/datums/components/armor_plate.dm b/code/datums/components/armor_plate.dm
index 25a886a3c92..41f127c9aab 100644
--- a/code/datums/components/armor_plate.dm
+++ b/code/datums/components/armor_plate.dm
@@ -12,7 +12,7 @@
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/applyplate)
RegisterSignal(parent, COMSIG_PARENT_PREQDELETED, .proc/dropplates)
- if(istype(parent, /obj/mecha/working/ripley))
+ if(istype(parent, /obj/vehicle/sealed/mecha/working/ripley))
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_mech_overlays)
if(_maxamount)
@@ -71,7 +71,7 @@
O.armor = O.armor.attachArmor(added_armor)
if(ismecha(O))
- var/obj/mecha/R = O
+ var/obj/vehicle/sealed/mecha/R = O
R.update_icon()
to_chat(user, "You strengthen [R], improving its resistance against melee, bullet and laser damage.")
else
@@ -85,13 +85,13 @@
for(var/i in 1 to amount)
new upgrade_item(get_turf(parent))
-/datum/component/armor_plate/proc/apply_mech_overlays(obj/mecha/mech, list/overlays)
+/datum/component/armor_plate/proc/apply_mech_overlays(obj/vehicle/sealed/mecha/mech, list/overlays)
SIGNAL_HANDLER
if(amount)
var/overlay_string = "ripley-g"
if(amount >= 3)
overlay_string += "-full"
- if(!mech.occupant)
+ if(LAZYLEN(mech.occupants))
overlay_string += "-open"
overlays += overlay_string
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 354f9b6d098..325901f99c8 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -921,10 +921,6 @@
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
-///Handle melee attack by a mech
-/atom/proc/mech_melee_attack(obj/mecha/M)
- return
-
/**
* Called when the atom log's in or out
*
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 3a93d6c5c20..9704fbb28da 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -998,7 +998,7 @@
if(!anchored && has_gravity())
step(src, movedir)
-//Returns an atom's power cell, if it has one. Overload for individual items.
+///Returns an atom's power cell, if it has one. Overload for individual items.
/atom/movable/proc/get_cell()
return
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 8b582dd6478..de24e9e5199 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -379,14 +379,14 @@
/*~~~~~~~~~~~~~~~~~~~~
BIG STOMPY MECHS
~~~~~~~~~~~~~~~~~~~~~*/
-/obj/mecha/proc/diag_hud_set_mechhealth()
+/obj/vehicle/sealed/mecha/proc/diag_hud_set_mechhealth()
var/image/holder = hud_list[DIAG_MECH_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = "huddiag[RoundDiagBar(obj_integrity/max_integrity)]"
-/obj/mecha/proc/diag_hud_set_mechcell()
+/obj/vehicle/sealed/mecha/proc/diag_hud_set_mechcell()
var/image/holder = hud_list[DIAG_BATT_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
@@ -397,7 +397,7 @@
holder.icon_state = "hudnobatt"
-/obj/mecha/proc/diag_hud_set_mechstat()
+/obj/vehicle/sealed/mecha/proc/diag_hud_set_mechstat()
var/image/holder = hud_list[DIAG_STAT_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
@@ -405,7 +405,7 @@
if(internal_damage)
holder.icon_state = "hudwarn"
-/obj/mecha/proc/diag_hud_set_mechtracking() //Shows tracking beacons on the mech
+/obj/vehicle/sealed/mecha/proc/diag_hud_set_mechtracking() //Shows tracking beacons on the mech
var/image/holder = hud_list[DIAG_TRACK_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm
index a7798e99e3e..058da3c061a 100644
--- a/code/game/gamemodes/clown_ops/clown_weapons.dm
+++ b/code/game/gamemodes/clown_ops/clown_weapons.dm
@@ -236,7 +236,7 @@
projectiles = 8
projectile_energy_cost = 1000
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/bombanana/can_attach(obj/mecha/combat/honker/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/bombanana/can_attach(obj/vehicle/sealed/mecha/combat/honker/M)
if(..())
if(istype(M))
return TRUE
@@ -254,13 +254,13 @@
equip_cooldown = 60
det_time = 20
-/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/tearstache/can_attach(obj/mecha/combat/honker/M)
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/tearstache/can_attach(obj/vehicle/sealed/mecha/combat/honker/M)
if(..())
if(istype(M))
return TRUE
return FALSE
-/obj/mecha/combat/honker/dark
+/obj/vehicle/sealed/mecha/combat/honker/dark
desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. This one has been painted black for maximum fun. HONK!"
name = "\improper Dark H.O.N.K"
icon_state = "darkhonker"
@@ -273,14 +273,14 @@
wreckage = /obj/structure/mecha_wreckage/honker/dark
max_equip = 4
-/obj/mecha/combat/honker/dark/add_cell(obj/item/stock_parts/cell/C)
+/obj/vehicle/sealed/mecha/combat/honker/dark/add_cell(obj/item/stock_parts/cell/C)
if(C)
C.forceMove(src)
cell = C
return
cell = new /obj/item/stock_parts/cell/hyper(src)
-/obj/mecha/combat/honker/dark/loaded/Initialize()
+/obj/vehicle/sealed/mecha/combat/honker/dark/loaded/Initialize()
. = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src)
ME.attach(src)
diff --git a/code/game/machinery/computer/mechlaunchpad.dm b/code/game/machinery/computer/mechlaunchpad.dm
index 26fa79e6524..88d3c765cbf 100644
--- a/code/game/machinery/computer/mechlaunchpad.dm
+++ b/code/game/machinery/computer/mechlaunchpad.dm
@@ -90,7 +90,7 @@
if(connected_mechpad.panel_open)
to_chat(user, "[src]'s pad has its' panel open! It won't work!")
return
- if(!(locate(/obj/mecha) in get_turf(connected_mechpad)))
+ if(!(locate(/obj/vehicle/sealed/mecha) in get_turf(connected_mechpad)))
to_chat(user, "[src] detects no mecha on the pad!")
return
connected_mechpad.launch(where)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index b88aa3438e9..d581ca1de3a 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -116,18 +116,6 @@
return
bumpopen(M)
return
-
- if(ismecha(AM))
- var/obj/mecha/mecha = AM
- if(density)
- if(mecha.occupant)
- if(world.time - mecha.occupant.last_bumped <= 10)
- return
- mecha.occupant.last_bumped = world.time
- if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
- open()
- else
- do_animate("deny")
return
if(isitem(AM))
@@ -370,7 +358,7 @@
//add_blood doesn't work for borgs/xenos, but add_blood_floor does.
L.add_splatter_floor(location)
log_combat(src, L, "crushed")
- for(var/obj/mecha/M in get_turf(src))
+ for(var/obj/vehicle/sealed/mecha/M in get_turf(src))
M.take_damage(DOOR_CRUSH_DAMAGE)
log_combat(src, M, "crushed")
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index bc364f13a0c..013b43be237 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -67,17 +67,19 @@
close()
/obj/machinery/door/window/Bumped(atom/movable/AM)
- if( operating || !density )
+ if(operating || !density)
return
- if (!( ismob(AM) ))
+ if(!ismob(AM))
if(ismecha(AM))
- var/obj/mecha/mecha = AM
- if(mecha.occupant && allowed(mecha.occupant))
- open_and_close()
- else
- do_animate("deny")
+ var/obj/vehicle/sealed/mecha/mecha = AM
+ for(var/O in mecha.occupants)
+ var/mob/living/occupant = O
+ if(allowed(occupant))
+ open_and_close()
+ return
+ do_animate("deny")
return
- if (!( SSticker ))
+ if(!SSticker)
return
var/mob/M = AM
if(M.restrained() || ((isdrone(M) || iscyborg(M)) && M.stat))
@@ -85,7 +87,7 @@
bumpopen(M)
/obj/machinery/door/window/bumpopen(mob/user)
- if( operating || !density )
+ if(operating || !density)
return
add_fingerprint(user)
if(!requiresID())
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 30a78ea4410..0c58653a5ce 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -448,10 +448,12 @@
for(var/A in GLOB.mechas_list)
if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range))
- var/obj/mecha/Mech = A
- if(Mech.occupant && !in_faction(Mech.occupant)) //If there is a user and they're not in our faction
- if(assess_perp(Mech.occupant) >= 4)
- targets += Mech
+ var/obj/vehicle/sealed/mecha/mech = A
+ for(var/O in mech.occupants)
+ var/mob/living/occupant = O
+ if(!in_faction(occupant)) //If there is a user and they're not in our faction
+ if(assess_perp(occupant) >= 4)
+ targets += mech
if((turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) && GLOB.blobs.len && (mode == TURRET_LETHAL))
for(var/obj/structure/blob/B in view(scan_range, base))
diff --git a/code/game/mecha/combat/five_stars.dm b/code/game/mecha/combat/five_stars.dm
deleted file mode 100644
index 82a961e1806..00000000000
--- a/code/game/mecha/combat/five_stars.dm
+++ /dev/null
@@ -1,22 +0,0 @@
-/obj/mecha/combat/five_stars
- desc = "A state of the art tank deployed by the Spinward Stellar Coalition National Guard."
- name = "\improper Tank"
- icon = 'icons/mecha/mecha_96x96.dmi'
- icon_state = "five_stars"
- armor = list(MELEE = 100, BULLET = 50, LASER = 35, ENERGY = 35, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
- exit_delay = 40
- step_in = 4
- dir_in = 1 //Facing North.
- max_integrity = 800
- pixel_x = -32
- pixel_y = -32
-
-/obj/mecha/combat/five_stars/Initialize()
- . = ..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/spacecops(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
- ME.attach(src)
- max_ammo()
diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm
deleted file mode 100644
index 376b8857083..00000000000
--- a/code/game/mecha/mecha_actions.dm
+++ /dev/null
@@ -1,256 +0,0 @@
-//////////////////////////////////////// Action Buttons ///////////////////////////////////////////////
-
-/obj/mecha/proc/GrantActions(mob/living/user, human_occupant = 0)
- if(human_occupant)
- eject_action.Grant(user, src)
- if(enclosed)
- internals_action.Grant(user, src)
- cycle_action.Grant(user, src)
- if(haslights)
- lights_action.Grant(user, src)
- stats_action.Grant(user, src)
- if(canstrafe)
- strafing_action.Grant(user, src)
-
-
-/obj/mecha/proc/RemoveActions(mob/living/user, human_occupant = 0)
- if(human_occupant)
- eject_action.Remove(user)
- internals_action.Remove(user)
- cycle_action.Remove(user)
- if(haslights)
- lights_action.Remove(user)
- stats_action.Remove(user)
- if(canstrafe)
- strafing_action.Remove(user)
-
-
-/datum/action/innate/mecha
- check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS
- icon_icon = 'icons/mob/actions/actions_mecha.dmi'
- var/obj/mecha/chassis
-
-/datum/action/innate/mecha/Grant(mob/living/L, obj/mecha/M)
- if(M)
- chassis = M
- ..()
-
-/datum/action/innate/mecha/Destroy()
- chassis = null
- return ..()
-
-/datum/action/innate/mecha/mech_eject
- name = "Eject From Mech"
- button_icon_state = "mech_eject"
-
-/datum/action/innate/mecha/mech_eject/Activate()
- if(!owner)
- return
- if(!chassis || chassis.occupant != owner)
- return
- chassis.container_resist_act(chassis.occupant)
-
-/datum/action/innate/mecha/mech_toggle_internals
- name = "Toggle Internal Airtank Usage"
- button_icon_state = "mech_internals_off"
-
-/datum/action/innate/mecha/mech_toggle_internals/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
- chassis.use_internal_tank = !chassis.use_internal_tank
- button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]"
- chassis.occupant_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
- chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].", LOG_MECHA)
- UpdateButtonIcon()
-
-/datum/action/innate/mecha/mech_cycle_equip
- name = "Cycle Equipment"
- button_icon_state = "mech_cycle_equip_off"
-
-/datum/action/innate/mecha/mech_cycle_equip/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
-
- var/list/available_equipment = list()
- for(var/obj/item/mecha_parts/mecha_equipment/M in chassis.equipment)
- if(M.selectable)
- available_equipment += M
-
- if(available_equipment.len == 0)
- chassis.occupant_message("No equipment available!")
- return
- if(!chassis.selected)
- chassis.selected = available_equipment[1]
- chassis.occupant_message("You select [chassis.selected].")
- send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list())
- button_icon_state = "mech_cycle_equip_on"
- UpdateButtonIcon()
- return
- var/number = 0
- for(var/A in available_equipment)
- number++
- if(A == chassis.selected)
- if(available_equipment.len == number)
- chassis.selected = null
- chassis.occupant_message("You switch to no equipment.")
- button_icon_state = "mech_cycle_equip_off"
- else
- chassis.selected = available_equipment[number+1]
- chassis.occupant_message("You switch to [chassis.selected].")
- button_icon_state = "mech_cycle_equip_on"
- send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list())
- UpdateButtonIcon()
- return
-
-
-/datum/action/innate/mecha/mech_toggle_lights
- name = "Toggle Lights"
- button_icon_state = "mech_lights_off"
-
-/datum/action/innate/mecha/mech_toggle_lights/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
- chassis.lights = !chassis.lights
- if(chassis.lights)
- button_icon_state = "mech_lights_on"
- else
- button_icon_state = "mech_lights_off"
- chassis.set_light_on(chassis.lights)
- chassis.occupant_message("Toggled lights [chassis.lights?"on":"off"].")
- chassis.log_message("Toggled lights [chassis.lights?"on":"off"].", LOG_MECHA)
- UpdateButtonIcon()
-
-/datum/action/innate/mecha/mech_view_stats
- name = "View Stats"
- button_icon_state = "mech_view_stats"
-
-/datum/action/innate/mecha/mech_view_stats/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
- chassis.occupant << browse(chassis.get_stats_html(), "window=exosuit")
-
-
-/datum/action/innate/mecha/strafe
- name = "Toggle Strafing. Disabled when Alt is held."
- button_icon_state = "strafe"
-
-/datum/action/innate/mecha/strafe/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
-
- chassis.toggle_strafe()
-
-/obj/mecha/AltClick(mob/living/user)
- if((user == occupant) && user.canUseTopic(src))
- toggle_strafe()
-
-/obj/mecha/proc/toggle_strafe()
- strafe = !strafe
-
- occupant_message("Toggled strafing mode [strafe?"on":"off"].")
- log_message("Toggled strafing mode [strafe?"on":"off"].", LOG_MECHA)
- strafing_action.UpdateButtonIcon()
-
-//////////////////////////////////////// Specific Ability Actions ///////////////////////////////////////////////
-//Need to be granted by the mech type, Not default abilities.
-
-/datum/action/innate/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"
- var/image/def_overlay
-
-/datum/action/innate/mecha/mech_defense_mode/Activate(forced_state = FALSE)
- SEND_SIGNAL(chassis, COMSIG_MECHA_ACTION_ACTIVATE, args) ///Signal sent to the mech, to be handed to the shield. See durand.dm for more details
-
-/datum/action/innate/mecha/mech_overload_mode
- name = "Toggle leg actuators overload"
- button_icon_state = "mech_overload_off"
-
-/datum/action/innate/mecha/mech_overload_mode/Activate(forced_state = null)
- if(!owner || !chassis || chassis.occupant != owner)
- return
- if(!isnull(forced_state))
- chassis.leg_overload_mode = forced_state
- else
- chassis.leg_overload_mode = !chassis.leg_overload_mode
- button_icon_state = "mech_overload_[chassis.leg_overload_mode ? "on" : "off"]"
- chassis.log_message("Toggled leg actuators overload.", LOG_MECHA)
- if(chassis.leg_overload_mode)
- chassis.leg_overload_mode = 1
- chassis.step_in = min(1, round(chassis.step_in/2))
- chassis.step_energy_drain = max(chassis.overload_step_energy_drain_min,chassis.step_energy_drain*chassis.leg_overload_coeff)
- chassis.occupant_message("You enable leg actuators overload.")
- else
- chassis.leg_overload_mode = 0
- chassis.step_in = initial(chassis.step_in)
- chassis.step_energy_drain = chassis.normal_step_energy_drain
- chassis.occupant_message("You disable leg actuators overload.")
- UpdateButtonIcon()
-
-/datum/action/innate/mecha/mech_smoke
- name = "Smoke"
- button_icon_state = "mech_smoke"
-
-/datum/action/innate/mecha/mech_smoke/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
- if(chassis.smoke_ready && chassis.smoke>0)
- chassis.smoke_system.start()
- chassis.smoke--
- chassis.smoke_ready = FALSE
- addtimer(VARSET_CALLBACK(chassis, smoke_ready, TRUE), chassis.smoke_cooldown)
-
-
-/datum/action/innate/mecha/mech_zoom
- name = "Zoom"
- button_icon_state = "mech_zoom_off"
-
-/datum/action/innate/mecha/mech_zoom/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- 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)
- chassis.occupant_message("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/innate/mecha/mech_switch_damtype
- name = "Reconfigure arm microtool arrays"
- button_icon_state = "mech_damtype_brute"
-
-/datum/action/innate/mecha/mech_switch_damtype/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
- var/new_damtype
- switch(chassis.damtype)
- if(TOX)
- new_damtype = BRUTE
- chassis.occupant_message("Your exosuit's hands form into fists.")
- if(BRUTE)
- new_damtype = BURN
- chassis.occupant_message("A torch tip extends from your exosuit's hand, glowing red.")
- if(BURN)
- new_damtype = TOX
- chassis.occupant_message("A bone-chillingly thick plasteel needle protracts from the exosuit's palm.")
- chassis.damtype = new_damtype
- button_icon_state = "mech_damtype_[new_damtype]"
- playsound(src, 'sound/mecha/mechmove01.ogg', 50, TRUE)
- UpdateButtonIcon()
-
-/datum/action/innate/mecha/mech_toggle_phasing
- name = "Toggle Phasing"
- button_icon_state = "mech_phasing_off"
-
-/datum/action/innate/mecha/mech_toggle_phasing/Activate()
- if(!owner || !chassis || chassis.occupant != owner)
- return
- chassis.phasing = !chassis.phasing
- button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]"
- chassis.occupant_message("En":"#f00\">Dis"]abled phasing.")
- UpdateButtonIcon()
diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm
deleted file mode 100644
index 1541ff1b7cd..00000000000
--- a/code/game/mecha/medical/medical.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/obj/mecha/medical
- internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_MEDICAL)
-
-/obj/mecha/medical/mechturn(direction)
- . = ..()
- if(!strafe && !occupant.client.keys_held["Alt"])
- mechstep(direction) //agile mechs get to move and turn in the same step
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 23204da7d0b..b6748426de0 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -17,9 +17,6 @@
/obj/effect/acid_act()
return
-/obj/effect/mech_melee_attack(obj/mecha/M)
- return
-
/obj/effect/blob_act(obj/structure/blob/B)
return
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 5d5d560ee2c..1bfdaf105f8 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -758,9 +758,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
return ..()
return 0
-/obj/item/mech_melee_attack(obj/mecha/M)
- return 0
-
/obj/item/burn()
if(!QDELETED(src))
var/turf/T = get_turf(src)
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index 9302e5cb56b..49d1e5fc838 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -163,7 +163,7 @@
dat += " (Stage [stage])"
dat += " \[Track\]
"
- for(var/obj/mecha/M in seen)
+ for(var/obj/vehicle/sealed/mecha/M in seen)
if(M.name in names)
names[M.name]++
dat += "[M.name] ([names[M.name]])"
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 0b97f241df8..9a57ee62856 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -137,26 +137,6 @@
return
attack_generic(user, rand(10, 15), BRUTE, MELEE, 1)
-/obj/mech_melee_attack(obj/mecha/M)
- M.do_attack_animation(src)
- var/play_soundeffect = 0
- var/mech_damtype = M.damtype
- if(M.selected)
- mech_damtype = M.selected.damtype
- play_soundeffect = 1
- else
- switch(M.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
- M.visible_message("[M.name] hits [src]!", "You hit [src]!", null, COMBAT_MESSAGE_RANGE)
- return take_damage(M.force*3, mech_damtype, MELEE, play_soundeffect, get_dir(src, M)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
/obj/singularity_act()
SSexplosions.high_mov_atom += src
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index e7537f526b6..c0d21cb5e3b 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -220,11 +220,6 @@
/obj/structure/window/proc/check_state_and_anchored(checked_state, checked_anchored)
return check_state(checked_state) && check_anchored(checked_anchored)
-/obj/structure/window/mech_melee_attack(obj/mecha/M)
- if(!can_be_reached())
- return
- ..()
-
/obj/structure/window/proc/can_be_reached(mob/user)
if(!fulltile)
if(get_dir(user,src) & dir)
diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm
index 68142b1f50d..9411630a726 100644
--- a/code/game/turfs/closed/walls.dm
+++ b/code/game/turfs/closed/walls.dm
@@ -100,24 +100,6 @@
else
add_dent(WALL_DENT_HIT)
-/turf/closed/wall/mech_melee_attack(obj/mecha/M)
- M.do_attack_animation(src)
- switch(M.damtype)
- if(BRUTE)
- playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
- M.visible_message("[M.name] hits [src]!", \
- "You hit [src]!", null, COMBAT_MESSAGE_RANGE)
- if(prob(hardness + M.force) && M.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
-
/turf/closed/wall/attack_paw(mob/living/user)
user.changeNext_move(CLICK_CD_MELEE)
return attack_hand(user)
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
index ebcd4d8a290..f654cd25aba 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
@@ -354,7 +354,7 @@
new /obj/effect/hotspot(T)
T.hotspot_expose(700,50,1)
// deals damage to mechs
- for(var/obj/mecha/M in T.contents)
+ for(var/obj/vehicle/sealed/mecha/M in T.contents)
if(M in hit_list)
continue
hit_list += M
diff --git a/code/modules/cargo/bounties/mech.dm b/code/modules/cargo/bounties/mech.dm
index 4b73dd51abc..3651be1af4e 100644
--- a/code/modules/cargo/bounties/mech.dm
+++ b/code/modules/cargo/bounties/mech.dm
@@ -5,8 +5,8 @@
/datum/bounty/item/mech/ship(obj/O)
if(!applies_to(O))
return
- if(istype(O, /obj/mecha))
- var/obj/mecha/M = O
+ if(istype(O, /obj/vehicle/sealed/mecha))
+ var/obj/vehicle/sealed/mecha/M = O
M.wreckage = null // So the mech doesn't explode.
..()
@@ -16,24 +16,24 @@
/datum/bounty/item/mech/ripleymkii
name = "APLU MK-II \"Ripley\""
reward = 13000
- wanted_types = list(/obj/mecha/working/ripley/mkii)
+ wanted_types = list(/obj/vehicle/sealed/mecha/working/ripley/mkii)
/datum/bounty/item/mech/clarke
name = "Clarke"
reward = 16000
- wanted_types = list(/obj/mecha/working/clarke)
+ wanted_types = list(/obj/vehicle/sealed/mecha/working/clarke)
/datum/bounty/item/mech/odysseus
name = "Odysseus"
reward = 11000
- wanted_types = list(/obj/mecha/medical/odysseus)
+ wanted_types = list(/obj/vehicle/sealed/mecha/medical/odysseus)
/datum/bounty/item/mech/gygax
name = "Gygax"
reward = 28000
- wanted_types = list(/obj/mecha/combat/gygax)
+ wanted_types = list(/obj/vehicle/sealed/mecha/combat/gygax)
/datum/bounty/item/mech/durand
name = "Durand"
reward = 20000
- wanted_types = list(/obj/mecha/combat/durand)
+ wanted_types = list(/obj/vehicle/sealed/mecha/combat/durand)
diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm
index f6d2133bfaa..9908316020e 100644
--- a/code/modules/fields/timestop.dm
+++ b/code/modules/fields/timestop.dm
@@ -84,7 +84,7 @@
freeze_mob(A)
else if(istype(A, /obj/projectile))
freeze_projectile(A)
- else if(istype(A, /obj/mecha))
+ else if(istype(A, /obj/vehicle/sealed/mecha))
freeze_mecha(A)
else if((ismachinery(A) && !istype(A, /obj/machinery/light)) || isstructure(A)) //Special exception for light fixtures since recoloring causes them to change light
freeze_structure(A)
@@ -120,7 +120,7 @@
unfreeze_mob(A)
else if(istype(A, /obj/projectile))
unfreeze_projectile(A)
- else if(istype(A, /obj/mecha))
+ else if(istype(A, /obj/vehicle/sealed/mecha))
unfreeze_mecha(A)
UnregisterSignal(A, COMSIG_MOVABLE_PRE_MOVE)
@@ -131,10 +131,10 @@
global_frozen_atoms -= A
-/datum/proximity_monitor/advanced/timestop/proc/freeze_mecha(obj/mecha/M)
+/datum/proximity_monitor/advanced/timestop/proc/freeze_mecha(obj/vehicle/sealed/mecha/M)
M.completely_disabled = TRUE
-/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mecha(obj/mecha/M)
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mecha(obj/vehicle/sealed/mecha/M)
M.completely_disabled = FALSE
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 3cad0475c18..4e75220ebcc 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -25,7 +25,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
- //If you died in the game and are a ghsot - this will remain as null.
+ //If you died in the game and are a ghost - this will remain as null.
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
var/atom/movable/following = null
var/fun_verbs = 0
diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm
index 9b3d62f61cd..2f0ea04750b 100644
--- a/code/modules/mob/living/brain/MMI.dm
+++ b/code/modules/mob/living/brain/MMI.dm
@@ -8,7 +8,7 @@
var/obj/item/radio/radio = null //Let's give it a radio.
var/mob/living/brain/brainmob = null //The current occupant.
var/mob/living/silicon/robot = null //Appears unused.
- var/obj/mecha = null //This does not appear to be used outside of reference in mecha.dm.
+ var/obj/vehicle/sealed/mecha = null //This does not appear to be used outside of reference in mecha.dm.
var/obj/item/organ/brain/brain = null //The actual brain
var/datum/ai_laws/laws = new()
var/force_replace_ai_name = FALSE
diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm
index 2faa23b800d..587d28c2513 100644
--- a/code/modules/mob/living/brain/brain.dm
+++ b/code/modules/mob/living/brain/brain.dm
@@ -35,7 +35,7 @@
return ..()
/mob/living/brain/update_mobility()
- if(in_contents_of(/obj/mecha))
+ if(in_contents_of(/obj/vehicle/sealed/mecha))
mobility_flags = MOBILITY_FLAGS_DEFAULT
else
mobility_flags = NONE
@@ -65,13 +65,6 @@
if(stored_dna)
stored_dna.real_name = real_name
-/mob/living/brain/ClickOn(atom/A, params)
- ..()
- if(container)
- var/obj/mecha/M = container.mecha
- if(istype(M))
- return M.click_action(A,src,params)
-
/mob/living/brain/forceMove(atom/destination)
if(container)
return container.forceMove(destination)
@@ -92,7 +85,7 @@
if(!container)
return
if (container.mecha)
- var/obj/mecha/M = container.mecha
+ var/obj/vehicle/sealed/mecha/M = container.mecha
if(M.mouse_pointer)
client.mouse_pointer_icon = M.mouse_pointer
if (client && ranged_ability && ranged_ability.ranged_mousepointer)
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index f4a693d5ade..15423512d89 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -32,10 +32,6 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift)
if(client && !suiciding && !(client in GLOB.dead_players_during_shift))
GLOB.dead_players_during_shift += client
GLOB.deaths_during_shift++
- if(ismecha(loc))
- var/obj/mecha/M = loc
- if(M.occupant == src)
- M.go_out()
if(!QDELETED(dna)) //The gibbed param is bit redundant here since dna won't exist at this point if they got deleted.
dna.species.spec_death(gibbed, src)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index acd8cffddd2..86ac018a071 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -353,46 +353,6 @@
var/armor_block = run_armor_check(affecting, MELEE)
apply_damage(damage, BRUTE, affecting, armor_block, wound_bonus=wound_mod)
-/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
-
- if(M.occupant.a_intent == INTENT_HARM)
- if(HAS_TRAIT(M.occupant, TRAIT_PACIFISM))
- to_chat(M.occupant, "You don't want to harm other living beings!")
- return
- M.do_attack_animation(src)
- if(M.damtype == BRUTE)
- step_away(src,M,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(M.force/2, M.force)
- switch(M.damtype)
- if(BRUTE)
- if(M.force > 35) // durand and other heavy mechas
- Unconscious(20)
- else if(M.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)
- M.mech_toxin_damage(src)
- else
- return
- if(update)
- update_damage_overlays()
- updatehealth()
-
- visible_message("[M.name] hits [src]!", \
- "[M.name] hits you!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, M)
- to_chat(M, "You hit [src]!")
- log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
-
- else
- ..()
-
/mob/living/carbon/human/ex_act(severity, target, origin)
if(TRAIT_BOMBIMMUNE in dna.species.species_traits)
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index e4aacf35790..32eed98edad 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -216,13 +216,13 @@
disintegrate(I, I)
else if(ismecha(AM))
- var/obj/mecha/M = AM
- if(M.haslights)
+ var/obj/vehicle/sealed/mecha/M = AM
+ if(M.mecha_flags & HAS_LIGHTS)
M.visible_message("[M]'s lights burn out!")
- M.haslights = FALSE
- M.set_light(-M.lights_power)
- if(M.occupant)
- M.lights_action.Remove(M.occupant)
+ M.mecha_flags &= ~HAS_LIGHTS
+ M.set_light_on(FALSE)
+ for(var/occupant in M.occupants)
+ M.remove_action_type_from_mob(/datum/action/vehicle/sealed/mecha/mech_toggle_lights, occupant)
for(var/obj/item/O in AM.GetAllContents())
if(O.light_range && O.light_power)
disintegrate(O, M)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index f18eba989b7..528ae40753e 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -98,39 +98,6 @@
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) //Item sounds are handled in the item itself
return ..()
-
-/mob/living/mech_melee_attack(obj/mecha/M)
- if(M.occupant.a_intent == INTENT_HARM)
- if(HAS_TRAIT(M.occupant, TRAIT_PACIFISM))
- to_chat(M.occupant, "You don't want to harm other living beings!")
- return
- M.do_attack_animation(src)
- if(M.damtype == BRUTE)
- step_away(src,M,15)
- switch(M.damtype)
- if(BRUTE)
- Unconscious(20)
- take_overall_damage(rand(M.force/2, M.force))
- playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
- if(BURN)
- take_overall_damage(0, rand(M.force/2, M.force))
- playsound(src, 'sound/items/welder.ogg', 50, TRUE)
- if(TOX)
- M.mech_toxin_damage(src)
- else
- return
- updatehealth()
- visible_message("[M.name] hits [src]!", \
- "[M.name] hits you!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, M)
- to_chat(M, "You hit [src]!")
- log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
- else
- step_away(src,M)
- log_combat(M.occupant, src, "pushed", M)
- visible_message("[M] pushes [src] out of the way.", \
- "[M] pushes you out of the way.", "You hear aggressive shuffling!", 5, M)
- to_chat(M, "You push [src] out of the way.")
-
/mob/living/fire_act()
adjust_fire_stacks(3)
IgniteMob()
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 3f436e36708..28cdee0c2fa 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -40,7 +40,7 @@
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
var/viewalerts = 0
var/icon/holo_icon//Default is assigned when AI is created.
- var/obj/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye.
+ var/obj/vehicle/sealed/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye.
var/radio_enabled = TRUE //Determins if a carded AI can speak with its built in radio or not.
radiomod = ";" //AIs will, by default, state their laws on the internal radio.
var/obj/item/multitool/aiMulti
@@ -422,7 +422,7 @@
to_chat(src, "Target is not on or near any active cameras on the station.")
return
if (href_list["ai_take_control"]) //Mech domination
- var/obj/mecha/M = locate(href_list["ai_take_control"]) in GLOB.mechas_list
+ var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"]) in GLOB.mechas_list
if (!M)
return
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index cf847de7146..c40dfd67fd5 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -57,7 +57,7 @@
if(NONE)
return FALSE
if(POWER_REQ_ALL)
- return !T || !A || ((!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
+ return !T || !A || ((!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/vehicle/sealed/mecha)))
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 06a19789451..5ccaa30e8c8 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -131,7 +131,7 @@
if(!search_objects)
. = hearers(vision_range, targets_from) - src //Remove self, so we don't suicide
- var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha))
+ var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/vehicle/sealed/mecha))
for(var/HM in typecache_filter_list(range(vision_range, targets_from), hostile_machines))
if(can_see(targets_from, HM, vision_range))
@@ -215,9 +215,9 @@
return TRUE
if(ismecha(the_target))
- var/obj/mecha/M = the_target
- if(M.occupant)//Just so we don't attack empty mechs
- if(CanAttack(M.occupant))
+ var/obj/vehicle/sealed/mecha/M = the_target
+ for(var/occupant in M.occupants)
+ if(CanAttack(occupant))
return TRUE
if(istype(the_target, /obj/machinery/porta_turret))
@@ -561,7 +561,7 @@
toggle_ai(AI_ON)
/mob/living/simple_animal/hostile/proc/ListTargetsLazy(_Z)//Step 1, find out what we can see
- var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha))
+ var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/vehicle/sealed/mecha))
. = list()
for (var/I in SSmobs.clients_by_zlevel[_Z])
var/mob/M = I
diff --git a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
index b842bddf20c..f737c7eed4a 100644
--- a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
@@ -25,8 +25,8 @@
search_objects = 0
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
- var/spawn_mecha_type = /obj/mecha/combat/marauder/mauler/loaded
- var/obj/mecha/mecha //Ref to pilot's mecha instance
+ var/spawn_mecha_type = /obj/vehicle/sealed/mecha/combat/marauder/mauler/loaded
+ var/obj/vehicle/sealed/mecha/mecha //Ref to pilot's mecha instance
var/required_mecha_charge = 7500 //If the pilot doesn't have a mecha, what charge does a potential Grand Theft Mecha need? (Defaults to half a battery)
var/mecha_charge_evacuate = 50 //Amount of charge at which the pilot tries to abandon the mecha
@@ -42,7 +42,7 @@
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/no_mech/Initialize()
. = ..()
- wanted_objects = typecacheof(/obj/mecha/combat, TRUE)
+ wanted_objects = typecacheof(/obj/vehicle/sealed/mecha/combat, TRUE)
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/nanotrasen //nanotrasen are syndies! no it's just a weird path.
name = "\improper Nanotrasen Mecha Pilot"
@@ -50,7 +50,7 @@
icon_living = "nanotrasen"
icon_state = "nanotrasen"
faction = list("nanotrasen")
- spawn_mecha_type = /obj/mecha/combat/marauder/loaded
+ spawn_mecha_type = /obj/vehicle/sealed/mecha/combat/marauder/loaded
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/no_mech/nanotrasen
name = "\improper Nanotrasen Mecha Pilot"
@@ -63,12 +63,12 @@
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/Initialize()
. = ..()
if(spawn_mecha_type)
- var/obj/mecha/M = new spawn_mecha_type (get_turf(src))
+ var/obj/vehicle/sealed/mecha/M = new spawn_mecha_type (get_turf(src))
if(istype(M))
enter_mecha(M)
-/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/enter_mecha(obj/mecha/M)
+/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/enter_mecha(obj/vehicle/sealed/mecha/M)
if(!M)
return 0
target = null //Target was our mecha, so null it out
@@ -89,11 +89,11 @@
ranged = 0
wanted_objects = list()
search_objects = 0
- if(mecha && mecha.lights_action) //an AI mecha is an EVIL EVIL thing, so let's not hide them in the dark
- mecha.lights_action.Activate()
+ if(LAZYACCESSASSOC(mecha.occupant_actions, src, /datum/action/vehicle/sealed/mecha/mech_defense_mode) && !mecha.defense_mode)
+ var/datum/action/action = mecha.occupant_actions[src][/datum/action/vehicle/sealed/mecha/mech_defense_mode]
+ action.Trigger(TRUE)
-
-/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/exit_mecha(obj/mecha/M)
+/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/exit_mecha(obj/vehicle/sealed/mecha/M)
if(!M)
return 0
@@ -102,9 +102,9 @@
targets_from = src
//Find a new mecha
- wanted_objects = typecacheof(/obj/mecha/combat, TRUE)
+ wanted_objects = typecacheof(/obj/vehicle/sealed/mecha/combat, TRUE)
var/search_aggressiveness = 2
- for(var/obj/mecha/combat/C in range(vision_range,src))
+ for(var/obj/vehicle/sealed/mecha/combat/C in range(vision_range,src))
if(is_valid_mecha(C))
target = C
search_aggressiveness = 3 //We can see a mech? RUN FOR IT, IGNORE MOBS!
@@ -116,23 +116,23 @@
walk(M,0)//end any lingering movement loops, to prevent the haunted mecha bug
//Checks if a mecha is valid for theft
-/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/is_valid_mecha(obj/mecha/M)
+/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/is_valid_mecha(obj/vehicle/sealed/mecha/M)
if(!M)
- return 0
- if(M.occupant)
- return 0
+ return FALSE
+ if(LAZYLEN(M.occupants))
+ return FALSE
if(!M.has_charge(required_mecha_charge))
- return 0
+ return FALSE
if(M.obj_integrity < M.max_integrity*0.5)
- return 0
- return 1
+ return FALSE
+ return TRUE
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/proc/mecha_face_target(atom/A)
if(mecha)
var/dirto = get_dir(mecha,A)
if(mecha.dir != dirto) //checking, because otherwise the mecha makes too many turn noises
- mecha.mechturn(dirto)
+ mecha.vehicle_move(dirto, TRUE)
@@ -163,8 +163,7 @@
var/list/possible_weapons = get_mecha_equip_by_flag(MECHA_RANGED)
if(possible_weapons.len)
var/obj/item/mecha_parts/mecha_equipment/ME = pick(possible_weapons) //so we don't favor mecha.equipment[1] forever
- if(ME.action(A))
- ME.start_cooldown()
+ if(ME.action(src,A))
return
else
@@ -177,16 +176,15 @@
if(possible_weapons.len)
var/obj/item/mecha_parts/mecha_equipment/ME = pick(possible_weapons)
mecha_face_target(target)
- if(ME.action(target))
- ME.start_cooldown()
+ if(ME.action(src,target))
return
- if(mecha.melee_can_hit)
+ if(!TIMER_COOLDOWN_CHECK(mecha, COOLDOWN_MECHA_MELEE_ATTACK))
mecha_face_target(target)
- target.mech_melee_attack(mecha)
+ target.mech_melee_attack(mecha, src)
else
if(ismecha(target))
- var/obj/mecha/M = target
+ var/obj/vehicle/sealed/mecha/M = target
if(is_valid_mecha(M))
enter_mecha(M)
return
@@ -199,49 +197,54 @@
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/handle_automated_action()
- if(..())
- if(!mecha)
- for(var/obj/mecha/combat/C in range(src,vision_range))
- if(is_valid_mecha(C))
- target = C //Let's nab it!
- minimum_distance = 1
- ranged = 0
- break
- if(mecha)
- var/list/L = PossibleThreats()
- var/threat_count = L.len
+ . = ..()
+ if(!.)
+ return
+ if(!mecha)
+ for(var/obj/vehicle/sealed/mecha/combat/mecha_in_range in range(src,vision_range))
+ if(is_valid_mecha(mecha_in_range))
+ target = mecha_in_range //Let's nab it!
+ minimum_distance = 1
+ ranged = 0
+ break
+ if(mecha)
+ var/list/L = PossibleThreats()
+ var/threat_count = L.len
- //Low Charge - Eject
- if(!mecha.has_charge(mecha_charge_evacuate))
- exit_mecha(mecha)
- return
+ //Low Charge - Eject
+ if(!mecha.has_charge(mecha_charge_evacuate))
+ exit_mecha(mecha)
+ return
//Too Much Damage - Eject
- if(mecha.obj_integrity < mecha.max_integrity*0.1)
- exit_mecha(mecha)
- return
+ if(mecha.obj_integrity < mecha.max_integrity*0.1)
+ exit_mecha(mecha)
+ return
- //Smoke if there's too many targets - Smoke Power
- if(threat_count >= threat_use_mecha_smoke && prob(smoke_chance))
- if(mecha.smoke_action && mecha.smoke_action.owner && mecha.smoke)
- mecha.smoke_action.Activate()
+ //Smoke if there's too many targets - Smoke Power
+ if(threat_count >= threat_use_mecha_smoke && prob(smoke_chance))
+ if(LAZYACCESSASSOC(mecha.occupant_actions, src, /datum/action/vehicle/sealed/mecha/mech_smoke) && !mecha.smoke_charges)
+ var/datum/action/action = mecha.occupant_actions[src][/datum/action/vehicle/sealed/mecha/mech_smoke]
+ action.Trigger()
- //Heavy damage - Defense Power or Retreat
- if(mecha.obj_integrity < mecha.max_integrity*0.25)
- if(prob(defense_mode_chance))
- if(mecha.defense_action && mecha.defense_action.owner && !mecha.defense_mode)
- mecha.leg_overload_mode = 0
- mecha.defense_action.Activate(TRUE)
- addtimer(CALLBACK(mecha.defense_action, /datum/action/innate/mecha/mech_defense_mode.proc/Activate, FALSE), 100) //10 seconds of defense, then toggle off
+ //Heavy damage - Defense Power or Retreat
+ if(mecha.obj_integrity < mecha.max_integrity*0.25)
+ if(prob(defense_mode_chance))
+ if(LAZYACCESSASSOC(mecha.occupant_actions, src, /datum/action/vehicle/sealed/mecha/mech_defense_mode) && !mecha.defense_mode)
+ var/datum/action/action = mecha.occupant_actions[src][/datum/action/vehicle/sealed/mecha/mech_defense_mode]
+ action.Trigger(TRUE)
+ addtimer(CALLBACK(action, /datum/action/vehicle/sealed/mecha/mech_defense_mode.proc/Trigger, FALSE), 100) //10 seconds of defense, then toggle off
- else if(prob(retreat_chance))
- //Speed boost if possible
- if(mecha.overload_action && mecha.overload_action.owner && !mecha.leg_overload_mode)
- mecha.overload_action.Activate(TRUE)
- addtimer(CALLBACK(mecha.overload_action, /datum/action/innate/mecha/mech_defense_mode.proc/Activate, FALSE), 100) //10 seconds of speeeeed, then toggle off
+ else if(prob(retreat_chance))
+ //Speed boost if possible
+ if(LAZYACCESSASSOC(mecha.occupant_actions, src, /datum/action/vehicle/sealed/mecha/mech_overload_mode) && !mecha.leg_overload_mode)
+ var/datum/action/action = mecha.occupant_actions[src][/datum/action/vehicle/sealed/mecha/mech_overload_mode]
+ mecha.leg_overload_mode = FALSE
+ action.Trigger(TRUE)
+ addtimer(CALLBACK(action, /datum/action/vehicle/sealed/mecha/mech_overload_mode.proc/Trigger, FALSE), 100) //10 seconds of speeeeed, then toggle off
- retreat_distance = 50
- addtimer(VARSET_CALLBACK(src, retreat_distance, 0), 10 SECONDS)
+ retreat_distance = 50
+ addtimer(VARSET_CALLBACK(src, retreat_distance, 0), 10 SECONDS)
@@ -260,17 +263,17 @@
//~simple animals~
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/CanAttack(atom/the_target)
if(ismecha(the_target))
- var/obj/mecha/M = the_target
+ var/obj/vehicle/sealed/mecha/M = the_target
if(mecha)
- if(M == mecha || !CanAttack(M.occupant))
- return 0
+ if(M == mecha) //Dont kill yourself
+ return FALSE
else //we're not in a mecha, so we check if we can steal it instead.
if(is_valid_mecha(M))
- return 1
- else if (M.occupant && CanAttack(M.occupant))
- return 1
- else
- return 0
+ return TRUE
+ for(var/occupant in M.occupants)
+ if(CanAttack(occupant))
+ return TRUE
+ return FALSE
. = ..()
@@ -289,6 +292,6 @@
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/Goto(target, delay, minimum_distance)
if(mecha)
- walk_to(mecha, target, minimum_distance, mecha.step_in)
+ walk_to(mecha, target, minimum_distance, mecha.movedelay)
else
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 33f77868602..32d4db1ed3c 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -215,7 +215,7 @@ Difficulty: Medium
if(L.client)
empty += pick(((RANGE_TURFS(2, L) - RANGE_TURFS(1, L)) & turfs) - empty) // picks a turf within 2 of the creature not outside or in the shield
any_attack = 1
- for(var/obj/mecha/M in T.contents)
+ for(var/obj/vehicle/sealed/mecha/M in T.contents)
empty += pick(((RANGE_TURFS(2, M) - RANGE_TURFS(1, M)) & turfs) - empty)
any_attack = 1
if(!any_attack)
@@ -285,7 +285,7 @@ Difficulty: Medium
to_chat(L, "You're hit by [source]'s fire breath!")
// deals damage to mechs
- for(var/obj/mecha/M in T.contents)
+ for(var/obj/vehicle/sealed/mecha/M in T.contents)
if(M in hit_list)
continue
hit_list += M
@@ -372,7 +372,7 @@ Difficulty: Medium
var/throwtarget = get_edge_target_turf(src, throw_dir)
L.throw_at(throwtarget, 3)
visible_message("[L] is thrown clear of [src]!")
- for(var/obj/mecha/M in orange(1, src))
+ for(var/obj/vehicle/sealed/mecha/M in orange(1, src))
M.take_damage(75, BRUTE, MELEE, 1)
for(var/mob/M in range(7, src))
@@ -444,7 +444,7 @@ Difficulty: Medium
to_chat(L, "You fall directly into the pool of lava!")
// deals damage to mechs
- for(var/obj/mecha/M in T.contents)
+ for(var/obj/vehicle/sealed/mecha/M in T.contents)
M.take_damage(45, BRUTE, MELEE, 1)
// changes turf to lava temporarily
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 2dcf01d4ca3..959c6de311a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -694,14 +694,15 @@ Difficulty: Hard
L.adjustBruteLoss(damage)
if(caster)
log_combat(caster, L, "struck with a [name]")
- for(var/obj/mecha/M in T.contents - hit_things) //also damage mechs.
+ for(var/obj/vehicle/sealed/mecha/M in T.contents - hit_things) //also damage mechs.
hit_things += M
- if(M.occupant)
- if(friendly_fire_check && caster && caster.faction_check_mob(M.occupant))
+ for(var/O in M.occupants)
+ var/mob/living/occupant = O
+ if(friendly_fire_check && caster && caster.faction_check_mob(occupant))
continue
- to_chat(M.occupant, "Your [M.name] is struck by a [name]!")
- playsound(M,'sound/weapons/sear.ogg', 50, TRUE, -4)
- M.take_damage(damage, BURN, 0, 0)
+ to_chat(occupant, "Your [M.name] is struck by a [name]!")
+ playsound(M,'sound/weapons/sear.ogg', 50, TRUE, -4)
+ M.take_damage(damage, BURN, 0, 0)
/obj/effect/temp_visual/hierophant/blast/visual
icon_state = "hierophant_blast"
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index dce179b1b4a..f82217c109c 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -52,8 +52,8 @@
if(ismineralturf(target))
var/turf/closed/mineral/M = target
M.gets_drilled()
- if(istype(target, /obj/mecha))
- var/obj/mecha/M = target
+ if(istype(target, /obj/vehicle/sealed/mecha))
+ var/obj/vehicle/sealed/mecha/M = target
M.take_damage(50, BRUTE, MELEE, 1)
//Elites can't talk (normally)!
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index 6605bf613ff..209eebe5bc4 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -98,10 +98,11 @@
if(M.client && CanAttack(M) && !M.has_unlimited_silicon_privilege)
if(!M.is_blind())
return M
- for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
- if(M.occupant && M.occupant.client)
- if(!M.occupant.is_blind())
- return M.occupant
+ for(var/obj/vehicle/sealed/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
+ for(var/O in M.occupants)
+ var/mob/mechamob = O
+ if(mechamob.client && !mechamob.is_blind())
+ return mechamob
return null
/mob/living/simple_animal/hostile/netherworld/migo
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
index 3a80e32d450..9d24b03bdeb 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
@@ -9,8 +9,8 @@
else
enemies -= L
else if(ismecha(A))
- var/obj/mecha/M = A
- if(M.occupant)
+ var/obj/vehicle/sealed/mecha/M = A
+ if(LAZYLEN(M.occupants))
return A
/mob/living/simple_animal/hostile/retaliate/ListTargets()
@@ -31,10 +31,10 @@
if(faction_check_mob(M) && attack_same || !faction_check_mob(M))
enemies |= M
else if(ismecha(A))
- var/obj/mecha/M = A
- if(M.occupant)
+ var/obj/vehicle/sealed/mecha/M = A
+ if(LAZYLEN(M.occupants))
enemies |= M
- enemies |= M.occupant
+ enemies |= M.occupants
for(var/mob/living/simple_animal/hostile/retaliate/H in around)
if(faction_check_mob(H) && !attack_same && !H.attack_same)
diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
index c963ed0d717..61fed648467 100644
--- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
@@ -128,8 +128,8 @@
adjustHealth(-L.maxHealth * 0.5)
return
. = ..()
- if(istype(target, /obj/mecha))
- var/obj/mecha/M = target
+ if(istype(target, /obj/vehicle/sealed/mecha))
+ var/obj/vehicle/sealed/mecha/M = target
M.take_damage(50, BRUTE, MELEE, 1)
/mob/living/simple_animal/hostile/space_dragon/Move()
@@ -221,7 +221,7 @@
L.adjustFireLoss(30)
to_chat(L, "You're hit by [src]'s fire breath!")
// deals damage to mechs
- for(var/obj/mecha/M in T.contents)
+ for(var/obj/vehicle/sealed/mecha/M in T.contents)
if(M in hit_list)
continue
hit_list += M
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index cc3f9949402..722ebf0e5ff 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -134,10 +134,11 @@
if(M.client && CanAttack(M) && !M.has_unlimited_silicon_privilege)
if(!M.is_blind())
return M
- for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
- if(M.occupant && M.occupant.client)
- if(!M.occupant.is_blind())
- return M.occupant
+ for(var/obj/vehicle/sealed/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
+ for(var/O in M.occupants)
+ var/mob/mechamob = O
+ if(mechamob.client && !mechamob.is_blind())
+ return mechamob
return null
// Cannot talk
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 84fa8932571..9bc311d65fd 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -450,8 +450,8 @@
if(L.stat != CONSCIOUS)
return FALSE
if (ismecha(the_target))
- var/obj/mecha/M = the_target
- if (M.occupant)
+ var/obj/vehicle/sealed/mecha/M = the_target
+ if(LAZYLEN(M.occupants))
return FALSE
return TRUE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 1f05b0212d8..14abd2e90da 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1157,7 +1157,7 @@
return
client.mouse_pointer_icon = initial(client.mouse_pointer_icon)
if (ismecha(loc))
- var/obj/mecha/M = loc
+ var/obj/vehicle/sealed/mecha/M = loc
if(M.mouse_pointer)
client.mouse_pointer_icon = M.mouse_pointer
else if (istype(loc, /obj/vehicle/sealed))
diff --git a/code/modules/ninja/suit/ninjaDrainAct.dm b/code/modules/ninja/suit/ninjaDrainAct.dm
index 376e07aecfc..189f70a71c9 100644
--- a/code/modules/ninja/suit/ninjaDrainAct.dm
+++ b/code/modules/ninja/suit/ninjaDrainAct.dm
@@ -190,7 +190,7 @@ They *could* go in their appropriate files, but this is supposed to be modular
S.spark_system.start()
//MECH//
-/obj/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
+/obj/vehicle/sealed/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
if(!S || !H || !G)
return INVALID_DRAIN
@@ -198,7 +198,7 @@ They *could* go in their appropriate files, but this is supposed to be modular
var/drain = 0 //Drain amount
. = 0
- occupant_message("Warning: Unauthorized access through sub-route 4, block H, detected.")
+ to_chat(occupants, "[icon2html(src, occupants)]Warning: Unauthorized access through sub-route 4, block H, detected.")
if(get_charge())
while(G.candrain && cell.charge > 0 && !maxcapacity)
drain = rand(G.mindrain,G.maxdrain)
diff --git a/code/modules/projectiles/projectile/special/rocket.dm b/code/modules/projectiles/projectile/special/rocket.dm
index 577a87fc8f0..defd84f1b40 100644
--- a/code/modules/projectiles/projectile/special/rocket.dm
+++ b/code/modules/projectiles/projectile/special/rocket.dm
@@ -24,7 +24,7 @@
explosion(target, -1, 1, 3, 1, 0, flame_range = 4)
if(ismecha(target))
- var/obj/mecha/M = target
+ var/obj/vehicle/sealed/mecha/M = target
M.take_damage(anti_armour_damage)
if(issilicon(target))
var/mob/living/silicon/S = target
@@ -56,7 +56,7 @@
embedding = null
var/sturdy = list(
/turf/closed,
- /obj/mecha,
+ /obj/vehicle/sealed/mecha,
/obj/machinery/door/,
/obj/machinery/door/poddoor/shutters
)
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index f3b97ea39db..9a034485da7 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -491,7 +491,7 @@
/obj/effect/CanEnterDisposals()
return
-/obj/mecha/CanEnterDisposals()
+/obj/vehicle/sealed/mecha/CanEnterDisposals()
return
/obj/machinery/disposal/bin/newHolderDestination(obj/structure/disposalholder/H)
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index bd22f7ec20b..f1773c166ae 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -206,7 +206,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
continue
if(bounty_ship_item_and_contents(AM, dry_run = FALSE))
matched_bounty = TRUE
- if(!AM.anchored || istype(AM, /obj/mecha))
+ if(!AM.anchored || istype(AM, /obj/vehicle/sealed/mecha))
export_item_and_contents(AM, export_categories , dry_run = FALSE, external_report = ex)
if(ex.exported_atoms)
diff --git a/code/modules/shuttle/white_ship.dm b/code/modules/shuttle/white_ship.dm
index 66146edea1e..4477489aaad 100644
--- a/code/modules/shuttle/white_ship.dm
+++ b/code/modules/shuttle/white_ship.dm
@@ -51,6 +51,6 @@
/obj/effect/spawner/lootdrop/whiteship_cere_ripley
name = "25% mech 75% wreckage ripley spawner"
- loot = list(/obj/mecha/working/ripley/mining = 1,
+ loot = list(/obj/vehicle/sealed/mecha/working/ripley/mining = 1,
/obj/structure/mecha_wreckage/ripley = 5)
lootdoubles = FALSE
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index b9dbc374ce4..4d15bcf0d32 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1148,13 +1148,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Dark Gygax Exosuit"
desc = "A lightweight exosuit, painted in a dark scheme. Its speed and equipment selection make it excellent \
for hit-and-run style attacks. Features an incendiary carbine, flash bang launcher, teleporter, ion thrusters and a Tesla energy array."
- item = /obj/mecha/combat/gygax/dark/loaded
+ item = /obj/vehicle/sealed/mecha/combat/gygax/dark/loaded
cost = 80
/datum/uplink_item/support/honker
name = "Dark H.O.N.K."
desc = "A clown combat mech equipped with bombanana peel and tearstache grenade launchers, as well as the ubiquitous HoNkER BlAsT 5000."
- item = /obj/mecha/combat/honker/dark/loaded
+ item = /obj/vehicle/sealed/mecha/combat/honker/dark/loaded
cost = 80
include_modes = list(/datum/game_mode/nuclear/clown_ops)
@@ -1162,7 +1162,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Mauler Exosuit"
desc = "A massive and incredibly deadly military-grade exosuit. Features long-range targeting, thrust vectoring \
and deployable smoke. Comes equipped with an LMG, scattershot carbine, missile rack, an antiprojectile armor booster and a Tesla energy array."
- item = /obj/mecha/combat/marauder/mauler/loaded
+ item = /obj/vehicle/sealed/mecha/combat/marauder/mauler/loaded
cost = 140
// Stealth Items
diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm
index 2c54bf605cc..293a9567540 100644
--- a/code/modules/vehicles/_vehicle.dm
+++ b/code/modules/vehicles/_vehicle.dm
@@ -7,6 +7,7 @@
armor = list(MELEE = 30, BULLET = 30, LASER = 30, ENERGY = 0, BOMB = 30, BIO = 0, RAD = 0, FIRE = 60, ACID = 60)
density = TRUE
anchored = FALSE
+ COOLDOWN_DECLARE(cooldown_vehicle_move)
var/list/mob/occupants //mob = bitflags of their control level.
var/max_occupants = 1
var/max_drivers = 1
@@ -124,9 +125,9 @@
return TRUE
/obj/vehicle/proc/vehicle_move(direction)
- if(lastmove + movedelay > world.time)
+ if(!COOLDOWN_FINISHED(src, cooldown_vehicle_move))
return FALSE
- lastmove = world.time
+ COOLDOWN_START(src, cooldown_vehicle_move, movedelay)
if(trailer)
var/dir_to_move = get_dir(trailer.loc, loc)
var/did_move = step(src, direction)
diff --git a/code/game/mecha/mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
similarity index 50%
rename from code/game/mecha/mecha.dm
rename to code/modules/vehicles/mecha/_mecha.dm
index 1eda8681fe7..34bebd2bb27 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -1,137 +1,183 @@
-/obj/mecha
+//////////////////WELCOME TO MECHA.DM, ENJOY YOUR STAY\\\\\\\\\\\\\\\\\
+
+/**
+ * Mechs are now (finally) vehicles, this means you can make them multicrew
+ * They can also grant select ability buttons based on occupant bitflags
+ *
+ * Movement is handled through vehicle_move() which is called by relaymove
+ * Clicking is done by way of signals registering to the entering mob
+ * NOTE: MMIS are NOT mobs but instead contain a brain that is, so you need special checks
+ * AI also has special checks becaus it gets in and out of the mech differently
+ * Always call remove_occupant(mob) when leaving the mech so the mob is removed properly
+ *
+ * For multi-crew, you need to set how the occupants recieve ability bitflags corresponding to their status on the vehicle(i.e: driver, gunner etc)
+ * Abilities can then be set to only apply for certain bitflags and are assigned as such automatically
+ *
+ * Clicks are wither translated into mech_melee_attack (see mech_melee_attack.dm)
+ * Or are used to call action() on equipped gear
+ * Cooldown for gear is on the mech because exploits
+ */
+/obj/vehicle/sealed/mecha
name = "mecha"
desc = "Exosuit"
icon = 'icons/mecha/mecha.dmi'
- density = TRUE //Dense. To raise the heat.
- move_force = MOVE_FORCE_VERY_STRONG
- move_resist = MOVE_FORCE_EXTREMELY_STRONG
resistance_flags = FIRE_PROOF | ACID_PROOF
- layer = BELOW_MOB_LAYER//icon draw layer
- infra_luminosity = 15 //byond implementation is bugged.
- force = 5
flags_1 = HEAR_1
+ max_integrity = 300
+ armor = list(MELEE = 20, BULLET = 10, LASER = 0, ENERGY = 0, BOMB = 10, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
+ movedelay = 1 SECONDS
+ anchored = TRUE
+ emulate_door_bumps = TRUE
+ COOLDOWN_DECLARE(mecha_bump_smash)
light_system = MOVABLE_LIGHT
light_on = FALSE
- var/ruin_mecha = FALSE //if the mecha starts on a ruin, don't automatically give it a tracking beacon to prevent metagaming.
- var/can_move = 0 //time of next allowed movement
- var/mob/living/carbon/occupant = null
- var/step_in = 10 //make a step in step_in/10 sec.
- var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South.
- var/normal_step_energy_drain = 10 //How much energy the mech will consume each time it moves. This variable is a backup for when leg actuators affect the energy drain.
+ ///What direction will the mech face when entered/powered on? Defaults to South.
+ var/dir_in = SOUTH
+ ///How much energy the mech will consume each time it moves. This variable is a backup for when leg actuators affect the energy drain.
+ var/normal_step_energy_drain = 10
+ ///How much energy the mech will consume each time it moves. this is the current active energy consumed
var/step_energy_drain = 10
+ ///How much energy we drain each time we mechpunch someone
var/melee_energy_drain = 15
+ ///The minimum amount of energy charge consumed by leg overload
var/overload_step_energy_drain_min = 100
- max_integrity = 300 //max_integrity is base health
- var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act.
- armor = list(MELEE = 20, BULLET = 10, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
+ ///chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act.
+ var/deflect_chance = 10
+ ///Modifiers for directional armor
var/list/facing_modifiers = list(MECHA_FRONT_ARMOUR = 1.5, MECHA_SIDE_ARMOUR = 1, MECHA_BACK_ARMOUR = 0.5)
- var/equipment_disabled = 0 //disabled due to EMP
+ ///if we cant use our equipment(such as due to EMP)
+ var/equipment_disabled = FALSE
/// Keeps track of the mech's cell
var/obj/item/stock_parts/cell/cell
/// Keeps track of the mech's scanning module
var/obj/item/stock_parts/scanning_module/scanmod
/// Keeps track of the mech's capacitor
var/obj/item/stock_parts/capacitor/capacitor
+ ///Whether the mechs maintenance protocols are on or off
var/construction_state = MECHA_LOCKED
- var/last_message = 0
- var/add_req_access = 1
- var/maint_access = 0
- var/dna_lock //dna-locking the mech
- var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
+ ///Contains flags for the mecha
+ var/mecha_flags = ADDING_ACCESS_POSSIBLE | CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS
+ ///Stores the DNA enzymes of a carbon so tht only they can access the mech
+ var/dna_lock
+ ///Spark effects are handled by this datum
var/datum/effect_system/spark_spread/spark_system = new
- var/lights = FALSE
+ ///How powerful our lights are
var/lights_power = 6
- var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference
- var/completely_disabled = FALSE //stops the mech from doing anything
+ ///Just stop the mech from doing anything
+ var/completely_disabled = FALSE
+ ///Whether this mech is allowed to move diagonally
+ var/allow_diagonal_movement = FALSE
+ ///Whether or not the mech destroys walls by running into it.
+ var/bumpsmash = FALSE
- var/bumpsmash = 0 //Whether or not the mech destroys walls by running into it.
- //inner atmos
- var/use_internal_tank = 0
+ ///////////ATMOS
+ ///Whether we are currrently drawing from the internal tank
+ var/use_internal_tank = FALSE
+ ///The setting of the valve on the internal tank
var/internal_tank_valve = ONE_ATMOSPHERE
+ ///The internal air tank obj of the mech
var/obj/machinery/portable_atmospherics/canister/internal_tank
+ ///Internal air mix datum
var/datum/gas_mixture/cabin_air
- var/obj/machinery/atmospherics/components/unary/portables_connector/connected_port = null
+ ///The connected air port, if we have one
+ var/obj/machinery/atmospherics/components/unary/portables_connector/connected_port
+ ///Special version of the radio, which is unsellable
var/obj/item/radio/mech/radio
var/list/trackers = list()
var/max_temperature = 25000
- var/internal_damage_threshold = 50 //health percentage below which internal damage is possible
- var/internal_damage = 0 //contains bitflags
+ ///health percentage below which internal damage is possible
+ var/internal_damage_threshold = 50
+ ///Bitflags for internal damage
+ var/internal_damage = NONE
- var/list/operation_req_access = list()//required access level for mecha operation
- var/list/internals_req_access = list(ACCESS_MECH_ENGINE, ACCESS_MECH_SCIENCE)//REQUIRED ACCESS LEVEL TO OPEN CELL COMPARTMENT
+ ///required access level for mecha operation
+ var/list/operation_req_access = list()
+ ///required access to change internal components
+ var/list/internals_req_access = list(ACCESS_MECH_ENGINE, ACCESS_MECH_SCIENCE)
+ ///Typepath for the wreckage it spawns when destroyed
var/wreckage
var/list/equipment = new
+ ///Current active equipment
var/obj/item/mecha_parts/mecha_equipment/selected
+ ///Maximum amount of equipment we can have
var/max_equip = 3
- var/step_silent = FALSE //Used for disabling mech step sounds while using thrusters or pushing off lockers
+ ///Whether our steps are silent, for example in zero-G
+ var/step_silent = FALSE
+ ///Sound played when the mech moves
var/stepsound = 'sound/mecha/mechstep.ogg'
+ ///Sound played when the mech walks
var/turnsound = 'sound/mecha/mechturn.ogg'
+ ///Cooldown duration between melee punches
var/melee_cooldown = 10
- var/melee_can_hit = 1
- var/silicon_pilot = FALSE //set to true if an AI or MMI is piloting.
+ ///TIme taken to leave the mech
+ var/exit_delay = 2 SECONDS
+ ///Time you get slept for if you get forcible ejected by the mech exploding
+ var/destruction_sleep_duration = 2 SECONDS
+ ///Whether outside viewers can see the pilot inside
+ var/enclosed = TRUE
+ ///In case theres a different iconstate for AI/MMI pilot(currently only used for ripley)
+ var/silicon_icon_state = null
+ ///Currently ejecting, and unable to do things
+ var/is_currently_ejecting = FALSE
- var/enter_delay = 40 //Time taken to enter the mech
- var/exit_delay = 20 //Time to exit mech
- var/destruction_sleep_duration = 20 //Time that mech pilot is put to sleep for if mech is destroyed
- var/enclosed = TRUE //Set to false for open-cockpit mechs
- var/silicon_icon_state = null //if the mech has a different icon when piloted by an AI or MMI
- var/is_currently_ejecting = FALSE //Mech cannot use equiptment when true, set to true if pilot is trying to exit mech
+ var/datum/effect_system/smoke_spread/smoke_system = new
- //Action datums
- var/datum/action/innate/mecha/mech_eject/eject_action = new
- var/datum/action/innate/mecha/mech_toggle_internals/internals_action = new
- var/datum/action/innate/mecha/mech_cycle_equip/cycle_action = new
- var/datum/action/innate/mecha/mech_toggle_lights/lights_action = new
- var/datum/action/innate/mecha/mech_view_stats/stats_action = new
- var/datum/action/innate/mecha/mech_defense_mode/defense_action = new
- var/datum/action/innate/mecha/mech_overload_mode/overload_action = new
- var/datum/effect_system/smoke_spread/smoke_system = new //not an action, but trigged by one
- var/datum/action/innate/mecha/mech_smoke/smoke_action = new
- var/datum/action/innate/mecha/mech_zoom/zoom_action = new
- var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new
- var/datum/action/innate/mecha/mech_toggle_phasing/phasing_action = new
- var/datum/action/innate/mecha/strafe/strafing_action = new
-
- //Action vars
+ ////Action vars
+ ///Ref to any active thrusters we might have
var/obj/item/mecha_parts/mecha_equipment/thrusters/active_thrusters
+
+ ///Bool for energy shield on/off
var/defense_mode = FALSE
+
+ ///Bool for leg overload on/off
var/leg_overload_mode = FALSE
+ ///Energy use modifier for leg overload
var/leg_overload_coeff = 100
+
+ //Bool for zoom on/off
var/zoom_mode = FALSE
- var/smoke = 5
- var/smoke_ready = 1
- var/smoke_cooldown = 100
+
+ ///Remaining smoke charges
+ var/smoke_charges = 5
+ ///Cooldown between using smoke
+ var/smoke_cooldown = 10 SECONDS
+
+ ///Bool for if the mech is currently phasing
var/phasing = FALSE
+ ///Power we use every time we phaze through something
var/phasing_energy_drain = 200
- var/phase_state = "" //icon_state when phasing
- var/strafe = FALSE //If we are strafing
- var/canstrafe = TRUE //if we can turn on strafing
- var/haslights = TRUE //if we can turn on lights
+ ///icon_state for flick() when phazing
+ var/phase_state = ""
- var/nextsmash = 0
- var/smashcooldown = 3 //deciseconds
+ ///Wether we are strafing
+ var/strafe = FALSE
+
+ ///Cooldown length between bumpsmashes
+ var/smashcooldown = 3
+
+ ///Bool for whether this mech can only be used on lavaland
+ var/lavaland_only = FALSE
- var/occupant_sight_flags = 0 //sight flags to give to the occupant (e.g. mech mining scanner gives meson-like vision)
- var/mouse_pointer
hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD)
/obj/item/radio/mech //this has to go somewhere
-/obj/mecha/Initialize()
+/obj/vehicle/sealed/mecha/Initialize()
. = ..()
- icon_state += "-open"
add_radio()
add_cabin()
- if (enclosed)
+ if(enclosed)
add_airtank()
+ RegisterSignal(src, COMSIG_MOVABLE_PRE_MOVE , .proc/disconnect_air)
+ RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/play_stepsound)
spark_system.set_up(2, 0, src)
spark_system.attach(src)
smoke_system.set_up(3, src)
@@ -149,77 +195,75 @@
diag_hud_set_mechhealth()
diag_hud_set_mechcell()
diag_hud_set_mechstat()
+ update_icon()
-/obj/mecha/update_icon_state()
- if(silicon_pilot && silicon_icon_state)
- icon_state = silicon_icon_state
-
-/obj/mecha/get_cell()
- return cell
-
-/obj/mecha/rust_heretic_act()
- take_damage(500, BRUTE)
-
-/obj/mecha/Destroy()
- if(occupant)
- occupant.SetSleeping(destruction_sleep_duration)
- go_out()
- var/mob/living/silicon/ai/AI
- for(var/mob/M in src) //Let's just be ultra sure
- if(isAI(M))
- occupant = null
- AI = M //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. They can be recovered with an AI card from the wreck.
+/obj/vehicle/sealed/mecha/Destroy()
+ for(var/M in occupants)
+ var/mob/living/occupant = M
+ if(isAI(occupant))
+ occupant.gib() //No wreck, no AI to recover
else
- M.forceMove(loc)
- for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
- E.detach(loc)
- qdel(E)
+ occupant.forceMove(loc)
+ occupant.SetSleeping(destruction_sleep_duration)
+ if(LAZYLEN(equipment))
+ for(var/E in equipment)
+ var/obj/item/mecha_parts/mecha_equipment/equip = E
+ equip.detach(loc)
+ qdel(equip)
if(cell)
- qdel(cell)
+ QDEL_NULL(cell)
if(scanmod)
- qdel(scanmod)
+ QDEL_NULL(scanmod)
if(capacitor)
- qdel(capacitor)
+ QDEL_NULL(capacitor)
if(internal_tank)
- qdel(internal_tank)
- if(AI)
- AI.gib() //No wreck, no AI to recover
+ QDEL_NULL(internal_tank)
STOP_PROCESSING(SSobj, src)
GLOB.poi_list.Remove(src)
- equipment.Cut()
- cell = null
- scanmod = null
- capacitor = null
- internal_tank = null
+ LAZYCLEARLIST(equipment)
if(loc)
loc.assume_air(cabin_air)
air_update_turf()
else
qdel(cabin_air)
cabin_air = null
- qdel(spark_system)
- spark_system = null
- qdel(smoke_system)
- smoke_system = null
+ QDEL_NULL(spark_system)
+ QDEL_NULL(smoke_system)
GLOB.mechas_list -= src //global mech list
return ..()
-/obj/mecha/proc/restore_equipment()
- equipment_disabled = 0
- if(occupant)
- SEND_SOUND(occupant, sound('sound/items/timer.ogg', volume=50))
- to_chat(occupant, "Equipment control unit has been rebooted successfully.")
- occupant.update_mouse_pointer()
+/obj/vehicle/sealed/mecha/update_icon_state()
+ if((mecha_flags & SILICON_PILOT) && silicon_icon_state)
+ icon_state = silicon_icon_state
+ else if(LAZYLEN(occupants))
+ icon_state = initial(icon_state)
+ else
+ icon_state = initial(icon_state)+ "-open"
-/obj/mecha/CheckParts(list/parts_list)
+
+/obj/vehicle/sealed/mecha/get_cell()
+ return cell
+
+/obj/vehicle/sealed/mecha/rust_heretic_act()
+ take_damage(500, BRUTE)
+
+/obj/vehicle/sealed/mecha/proc/restore_equipment()
+ equipment_disabled = FALSE
+ for(var/occupant in occupants)
+ var/mob/mob_occupant
+ SEND_SOUND(mob_occupant, sound('sound/items/timer.ogg', volume=50))
+ to_chat(mob_occupant, "Equipment control unit has been rebooted successfully.")
+ mob_occupant.update_mouse_pointer()
+
+/obj/vehicle/sealed/mecha/CheckParts(list/parts_list)
..()
cell = locate(/obj/item/stock_parts/cell) in contents
scanmod = locate(/obj/item/stock_parts/scanning_module) in contents
capacitor = locate(/obj/item/stock_parts/capacitor) in contents
update_part_values()
-/obj/mecha/proc/update_part_values() ///Updates the values given by scanning module and capacitor tier, called when a part is removed or inserted.
+/obj/vehicle/sealed/mecha/proc/update_part_values() ///Updates the values given by scanning module and capacitor tier, called when a part is removed or inserted.
if(scanmod)
normal_step_energy_drain = 20 - (5 * scanmod.rating) //10 is normal, so on lowest part its worse, on second its ok and on higher its real good up to 0 on best
step_energy_drain = normal_step_energy_drain
@@ -236,12 +280,12 @@
////// Helpers /////////
////////////////////////
-/obj/mecha/proc/add_airtank()
+/obj/vehicle/sealed/mecha/proc/add_airtank()
internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
return internal_tank
///Adds a cell, for use in Map-spawned mechs, Nuke Ops mechs, and admin-spawned mechs. Mechs built by hand will replace this.
-/obj/mecha/proc/add_cell(obj/item/stock_parts/cell/C=null)
+/obj/vehicle/sealed/mecha/proc/add_cell(obj/item/stock_parts/cell/C=null)
QDEL_NULL(cell)
if(C)
C.forceMove(src)
@@ -250,7 +294,7 @@
cell = new /obj/item/stock_parts/cell/high/plus(src)
///Adds a scanning module, for use in Map-spawned mechs, Nuke Ops mechs, and admin-spawned mechs. Mechs built by hand will replace this.
-/obj/mecha/proc/add_scanmod(obj/item/stock_parts/scanning_module/sm=null)
+/obj/vehicle/sealed/mecha/proc/add_scanmod(obj/item/stock_parts/scanning_module/sm=null)
QDEL_NULL(scanmod)
if(sm)
sm.forceMove(src)
@@ -259,7 +303,7 @@
scanmod = new /obj/item/stock_parts/scanning_module(src)
///Adds a capacitor, for use in Map-spawned mechs, Nuke Ops mechs, and admin-spawned mechs. Mechs built by hand will replace this.
-/obj/mecha/proc/add_capacitor(obj/item/stock_parts/capacitor/cap=null)
+/obj/vehicle/sealed/mecha/proc/add_capacitor(obj/item/stock_parts/capacitor/cap=null)
QDEL_NULL(capacitor)
if(cap)
cap.forceMove(src)
@@ -267,7 +311,7 @@
else
capacitor = new /obj/item/stock_parts/capacitor(src)
-/obj/mecha/proc/add_cabin()
+/obj/vehicle/sealed/mecha/proc/add_cabin()
cabin_air = new
cabin_air.temperature = T20C
cabin_air.volume = 200
@@ -276,24 +320,22 @@
cabin_air.gases[/datum/gas/nitrogen][MOLES] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
return cabin_air
-/obj/mecha/proc/add_radio()
+/obj/vehicle/sealed/mecha/proc/add_radio()
radio = new(src)
radio.name = "[src] radio"
radio.icon = icon
radio.icon_state = icon_state
radio.subspace_transmission = TRUE
-/obj/mecha/proc/can_use(mob/user)
- if(user != occupant)
- return 0
- if(user && ismob(user))
+/obj/vehicle/sealed/mecha/proc/can_use(mob/user)
+ if(istype(user) && is_occupant(user))
if(!user.incapacitated())
- return 1
- return 0
+ return TRUE
+ return FALSE
////////////////////////////////////////////////////////////////////////////////
-/obj/mecha/examine(mob/user)
+/obj/vehicle/sealed/mecha/examine(mob/user)
. = ..()
var/integrity = obj_integrity*100/max_integrity
switch(integrity)
@@ -315,10 +357,11 @@
for(var/obj/item/mecha_parts/mecha_equipment/ME in visible_equipment)
. += "[icon2html(ME, user)] \A [ME]."
if(!enclosed)
- if(silicon_pilot)
+ if(mecha_flags & SILICON_PILOT)
. += "[src] appears to be piloting itself..."
- else if(occupant && occupant != user) //!silicon_pilot implied
- . += "You can see [occupant] inside."
+ else
+ for(var/occupante in occupants)
+ . += "You can see [occupante] inside."
if(ishuman(user))
var/mob/living/carbon/human/H = user
for(var/O in H.held_items)
@@ -327,7 +370,7 @@
break //in case user is holding two guns
//processing internal damage, temperature, air regulation, alert updates, lights power use.
-/obj/mecha/process()
+/obj/vehicle/sealed/mecha/process()
var/internal_temp_regulation = 1
if(internal_damage)
@@ -394,103 +437,101 @@
else //just delete the cabin gas, we're in space or some shit
qdel(removed)
- if(occupant)
- if(cell)
- var/cellcharge = cell.charge/cell.maxcharge
- switch(cellcharge)
- if(0.75 to INFINITY)
- occupant.clear_alert("charge")
- if(0.5 to 0.75)
- occupant.throw_alert("charge", /obj/screen/alert/lowcell, 1)
- if(0.25 to 0.5)
- occupant.throw_alert("charge", /obj/screen/alert/lowcell, 2)
- if(0.01 to 0.25)
- occupant.throw_alert("charge", /obj/screen/alert/lowcell, 3)
+ if(occupants)
+ for(var/i in occupants)
+ var/mob/living/occupant = i
+ if(cell)
+ var/cellcharge = cell.charge/cell.maxcharge
+ switch(cellcharge)
+ if(0.75 to INFINITY)
+ occupant.clear_alert("charge")
+ if(0.5 to 0.75)
+ occupant.throw_alert("charge", /obj/screen/alert/lowcell, 1)
+ if(0.25 to 0.5)
+ occupant.throw_alert("charge", /obj/screen/alert/lowcell, 2)
+ if(0.01 to 0.25)
+ occupant.throw_alert("charge", /obj/screen/alert/lowcell, 3)
+ else
+ occupant.throw_alert("charge", /obj/screen/alert/emptycell)
+
+ var/integrity = obj_integrity/max_integrity*100
+ switch(integrity)
+ if(30 to 45)
+ occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 1)
+ if(15 to 35)
+ occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 2)
+ if(-INFINITY to 15)
+ occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 3)
else
- occupant.throw_alert("charge", /obj/screen/alert/emptycell)
+ occupant.clear_alert("mech damage")
+ var/atom/checking = occupant.loc
+ // recursive check to handle all cases regarding very nested occupants,
+ // such as brainmob inside brainitem inside MMI inside mecha
+ while(!isnull(checking))
+ if(isturf(checking))
+ // hit a turf before hitting the mecha, seems like they have been moved out
+ occupant.clear_alert("charge")
+ occupant.clear_alert("mech damage")
+ occupant = null
+ break
+ else if (checking == src)
+ break // all good
+ checking = checking.loc
- var/integrity = obj_integrity/max_integrity*100
- switch(integrity)
- if(30 to 45)
- occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 1)
- if(15 to 35)
- occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 2)
- if(-INFINITY to 15)
- occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 3)
- else
- occupant.clear_alert("mech damage")
- var/atom/checking = occupant.loc
- // recursive check to handle all cases regarding very nested occupants,
- // such as brainmob inside brainitem inside MMI inside mecha
- while (!isnull(checking))
- if (isturf(checking))
- // hit a turf before hitting the mecha, seems like they have
- // been moved out
- occupant.clear_alert("charge")
- occupant.clear_alert("mech damage")
- RemoveActions(occupant, human_occupant=1)
- occupant = null
- break
- else if (checking == src)
- break // all good
- checking = checking.loc
-
- if(lights)
+ if(mecha_flags & LIGHTS_ON)
var/lights_energy_drain = 2
use_power(lights_energy_drain)
- if(!enclosed && occupant?.incapacitated()) //no sides mean it's easy to just sorta fall out if you're incapacitated.
- visible_message("[occupant] tumbles out of the cockpit!")
- go_out() //Maybe we should install seat belts?
+ for(var/b in occupants)
+ var/mob/living/occupant = b
+ if(!enclosed && occupant?.incapacitated()) //no sides mean it's easy to just sorta fall out if you're incapacitated.
+ visible_message("[occupant] tumbles out of the cockpit!")
+ mob_exit(occupant) //bye bye
//Diagnostic HUD updates
diag_hud_set_mechhealth()
diag_hud_set_mechcell()
diag_hud_set_mechstat()
-/obj/mecha/fire_act() //Check if we should ignite the pilot of an open-canopy mech
+/obj/vehicle/sealed/mecha/fire_act() //Check if we should ignite the pilot of an open-canopy mech
. = ..()
- if (occupant && !enclosed && !silicon_pilot)
- if (occupant.fire_stacks < 5)
- occupant.fire_stacks += 1
- occupant.IgniteMob()
+ if(LAZYLEN(occupants) && !enclosed && !(mecha_flags & SILICON_PILOT))
+ for(var/M in occupants)
+ var/mob/living/cookedalive = M
+ if(cookedalive.fire_stacks < 5)
+ cookedalive.fire_stacks += 1
+ cookedalive.IgniteMob()
-/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
- return
-
-/obj/mecha/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
- . = ..()
- if(speaker == occupant)
- if(radio?.broadcasting)
- radio.talk_into(speaker, text, , spans, message_language, message_mods)
- //flick speech bubble
- var/list/speech_bubble_recipients = list()
- for(var/mob/M in get_hearers_in_view(7,src))
- if(M.client)
- speech_bubble_recipients.Add(M.client)
- INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, image('icons/mob/talk.dmi', src, "machine[say_test(raw_message)]",MOB_LAYER+1), speech_bubble_recipients, 30)
+/obj/vehicle/sealed/mecha/proc/display_speech_bubble(datum/source, list/speech_args)
+ SIGNAL_HANDLER
+ var/list/speech_bubble_recipients = get_hearers_in_view(7,src)
+ for(var/mob/M in speech_bubble_recipients)
+ if(M.client)
+ speech_bubble_recipients.Add(M.client)
+ INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, image('icons/mob/talk.dmi', src, "machine[say_test(speech_args[SPEECH_MESSAGE])]",MOB_LAYER+1), speech_bubble_recipients, 30)
////////////////////////////
///// Action processing ////
////////////////////////////
-
-/obj/mecha/proc/click_action(atom/target,mob/user,params)
- if(!occupant || occupant != user )
- return
+/obj/vehicle/sealed/mecha/proc/on_mouseclick(mob/user, atom/target, params)
+ SIGNAL_HANDLER
if(!locate(/turf) in list(target,target.loc)) // Prevents inventory from being drilled
return
if(completely_disabled)
return
if(is_currently_ejecting)
return
+ var/list/mouse_control = params2list(params)
+ if(isAI(user) && !mouse_control["middle"])//AIs use MMB
+ return
if(phasing)
- occupant_message("Unable to interact with objects while phasing.")
+ to_chat(occupants, "[icon2html(src, occupants)]Unable to interact with objects while phasing.")
return
if(user.incapacitated())
return
if(construction_state)
- occupant_message("Maintenance protocols in effect.")
+ to_chat(occupants, "[icon2html(src, occupants)]Maintenance protocols in effect.")
return
if(!get_charge())
return
@@ -500,39 +541,32 @@
if(dir_to_target && !(dir_to_target & dir))//wrong direction
return
if(internal_damage & MECHA_INT_CONTROL_LOST)
- if (!target)
- return
target = pick(view(3,target))
-
+ if(!target)
+ return
var/mob/living/L = user
- if(!Adjacent(target))
- if(selected && selected.is_ranged())
+ if(selected)
+ if(!Adjacent(target) && (selected.range & MECHA_RANGED))
if(HAS_TRAIT(L, TRAIT_PACIFISM) && selected.harmful)
- to_chat(user, "You don't want to harm other living beings!")
+ to_chat(L, "You don't want to harm other living beings!")
return
- if(selected.action(target,params))
- selected.start_cooldown()
- else if(selected && selected.is_melee())
- if(isliving(target) && selected.harmful && HAS_TRAIT(L, TRAIT_PACIFISM))
- to_chat(user, "You don't want to harm other living beings!")
+ selected.action(user, target, params)
return
- if(selected.action(target,params))
- selected.start_cooldown()
- else
- if(internal_damage & MECHA_INT_CONTROL_LOST)
- var/list/possible_targets = oview(1,src)
- if (!length(possible_targets))
+ if((selected.range & MECHA_MELEE) && Adjacent(target))
+ if(isliving(target) && selected.harmful && HAS_TRAIT(L, TRAIT_PACIFISM))
+ to_chat(L, "You don't want to harm other living beings!")
return
- target = pick(possible_targets)
- if(!melee_can_hit || !istype(target, /atom))
+ selected.action(user, target, params)
return
- target.mech_melee_attack(src)
- melee_can_hit = FALSE
- addtimer(VARSET_CALLBACK(src, melee_can_hit, TRUE), melee_cooldown)
-
-
-/obj/mecha/proc/range_action(atom/target)
- return
+ if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MELEE_ATTACK) || !istype(target, /atom) || !Adjacent(target))
+ return
+ if(internal_damage & MECHA_INT_CONTROL_LOST)
+ var/list/possible_targets = oview(1,src)
+ if(!length(possible_targets))
+ return
+ target = pick(possible_targets)
+ target.mech_melee_attack(src, user)
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown)
//////////////////////////////////
@@ -540,17 +574,18 @@
//////////////////////////////////
///Plays the mech step sound effect. Split from movement procs so that other mechs (HONK) can override this one specific part.
-/obj/mecha/proc/play_stepsound()
+/obj/vehicle/sealed/mecha/proc/play_stepsound()
+ SIGNAL_HANDLER
if(stepsound)
playsound(src,stepsound,40,1)
-/obj/mecha/Move(atom/newloc, direct)
- . = ..()
- if (internal_tank?.disconnect()) // Something moved us and broke connection
- occupant_message("Air port connection has been severed!")
+/obj/vehicle/sealed/mecha/proc/disconnect_air()
+ SIGNAL_HANDLER
+ if(internal_tank.disconnect()) // Something moved us and broke connection
+ to_chat(occupants, "[icon2html(src, occupants)]Air port connection has been severed!")
log_message("Lost connection to gas port.", LOG_MECHA)
-/obj/mecha/Process_Spacemove(movement_dir = 0)
+/obj/vehicle/sealed/mecha/Process_Spacemove(movement_dir = 0)
. = ..()
if(.)
return TRUE
@@ -560,124 +595,105 @@
if(istype(backup) && movement_dir && !backup.anchored)
if(backup.newtonian_move(turn(movement_dir, 180)))
step_silent = TRUE
- if(occupant)
- to_chat(occupant, "You push off [backup] to propel yourself.")
+ if(return_drivers())
+ to_chat(occupants, "[icon2html(src, occupants)]The [src] push off [backup] to propel yourself.")
return TRUE
- if(can_move <= world.time && active_thrusters && movement_dir && active_thrusters.thrust(movement_dir))
+ if(movedelay <= world.time && active_thrusters && movement_dir && active_thrusters.thrust(movement_dir))
step_silent = TRUE
return TRUE
return FALSE
-/obj/mecha/relaymove(mob/living/user, direction)
+/obj/vehicle/sealed/mecha/vehicle_move(direction, forcerotate = FALSE)
+ if(!COOLDOWN_FINISHED(src, cooldown_vehicle_move))
+ return FALSE
+ COOLDOWN_START(src, cooldown_vehicle_move, movedelay)
if(completely_disabled)
- return
+ return FALSE
if(!direction)
- return
- if(user != occupant) //While not "realistic", this piece is player friendly.
- user.forceMove(get_turf(src))
- to_chat(user, "You climb out from [src].")
- return 0
+ return FALSE
if(internal_tank?.connected_port)
- if(world.time - last_message > 20)
- occupant_message("Unable to move while connected to the air system port!")
- last_message = world.time
- return 0
+ if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MESSAGE))
+ to_chat(occupants, "[icon2html(src, occupants)]Unable to move while connected to the air system port!")
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
+ return FALSE
if(construction_state)
- if(world.time - last_message > 20)
- occupant_message("Maintenance protocols in effect.")
- last_message = world.time
- return
- return domove(direction)
+ if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MESSAGE))
+ to_chat(occupants, "[icon2html(src, occupants)]Maintenance protocols in effect.")
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
+ return FALSE
-/obj/mecha/proc/domove(direction)
- if(can_move >= world.time)
- return 0
if(!Process_Spacemove(direction))
- return 0
+ return FALSE
if(!has_charge(step_energy_drain))
- return 0
+ return FALSE
if(zoom_mode)
- if(world.time - last_message > 20)
- occupant_message("Unable to move while in zoom mode!")
- last_message = world.time
- return 0
+ to_chat(occupants, "[icon2html(src, occupants)]Unable to move while in zoom mode!")
+ return FALSE
if(!cell)
- if(world.time - last_message > 20)
- occupant_message("Missing power cell.")
- last_message = world.time
- return 0
+ to_chat(occupants, "[icon2html(src, occupants)]Missing power cell.")
+ return FALSE
if(!scanmod || !capacitor)
- if(world.time - last_message > 20)
- occupant_message("Missing [scanmod? "capacitor" : "scanning module"].")
- last_message = world.time
- return 0
+ to_chat(occupants, "[icon2html(src, occupants)]Missing [scanmod? "capacitor" : "scanning module"].")
+ return FALSE
+ if(lavaland_only && is_mining_level(z))
+ to_chat(occupants, "[icon2html(src, occupants)]Invalid Environment.")
+ return FALSE
+
+ var/olddir = dir
- var/move_result = 0
- var/oldloc = loc
if(internal_damage & MECHA_INT_CONTROL_LOST)
- set_glide_size(DELAY_TO_GLIDE_SIZE(step_in))
- move_result = mechsteprand()
- else if(dir != direction && (!strafe || occupant.client.keys_held["Alt"]))
- move_result = mechturn(direction)
- else
- set_glide_size(DELAY_TO_GLIDE_SIZE(step_in))
- move_result = mechstep(direction)
- if(move_result || loc != oldloc)// halfway done diagonal move still returns false
- use_power(step_energy_drain)
- can_move = world.time + step_in
- return 1
- return 0
+ direction = pick(GLOB.alldirs)
-/obj/mecha/proc/mechturn(direction)
- setDir(direction)
- if(turnsound)
- playsound(src,turnsound,40,TRUE)
- return 1
+ //only mechs with diagonal movement may move diagonally
+ if(!allow_diagonal_movement && ISDIAGONALDIR(direction))
+ return TRUE
+
+ //if we're not facing the way we're going rotate us
+ if(dir != direction && !strafe || forcerotate)
+ setDir(direction)
+ if(turnsound)
+ playsound(src,turnsound,40,TRUE)
+ return TRUE
+
+ set_glide_size(DELAY_TO_GLIDE_SIZE(movedelay))
+ //Otherwise just walk normally
+ . = step(src,direction, dir)
-/obj/mecha/proc/mechstep(direction)
- var/current_dir = dir
- . = step(src,direction)
if(strafe)
- setDir(current_dir)
- if(. && !step_silent)
- play_stepsound()
- step_silent = FALSE
+ for(var/D in return_drivers())
+ var/mob/driver = D
+ if(driver.client?.keys_held["Alt"])
+ return
+ setDir(olddir)
-/obj/mecha/proc/mechsteprand()
- . = step_rand(src)
- if(. && !step_silent)
- play_stepsound()
- step_silent = FALSE
-/obj/mecha/Bump(atom/obstacle)
+/obj/vehicle/sealed/mecha/Bump(atom/obstacle)
if(phasing && get_charge() >= phasing_energy_drain && !throwing)
- if(!can_move)
- return
- can_move = 0
if(phase_state)
flick(phase_state, src)
- forceMove(get_step(src,dir))
+ forceMove(get_step(src,dir))//This is jank I hate it thanks, this should be done thrugh move not this dumb shit
use_power(phasing_energy_drain)
- addtimer(VARSET_CALLBACK(src, can_move, TRUE), step_in*3)
- else
- if(..()) //mech was thrown
- return
- if(bumpsmash && occupant) //Need a pilot to push the PUNCH button.
- if(nextsmash < world.time)
- obstacle.mech_melee_attack(src)
- nextsmash = world.time + smashcooldown
- if(!obstacle || obstacle.CanPass(src,get_step(src,dir)))
- step(src,dir)
- if(isobj(obstacle))
- var/obj/O = obstacle
- if(!O.anchored && O.move_resist <= move_force)
- step(obstacle, dir)
- else if(ismob(obstacle))
- var/mob/M = obstacle
- if(M.move_resist <= move_force)
- step(obstacle, dir)
+ addtimer(VARSET_CALLBACK(src, movedelay, TRUE), movedelay*3)
+ return
+ . = ..()
+ if(.) //mech was thrown/door/whatever
+ return
+ if(bumpsmash) //Need a pilot to push the PUNCH button.
+ if(COOLDOWN_FINISHED(src, mecha_bump_smash))
+ obstacle.mech_melee_attack(src)
+ COOLDOWN_START(src, mecha_bump_smash, smashcooldown)
+ if(!obstacle || obstacle.CanPass(src,get_step(src,dir)))
+ step(src,dir)
+ if(isobj(obstacle))
+ var/obj/obj_obstacle = obstacle
+ if(!obj_obstacle.anchored && obj_obstacle.move_resist <= move_force)
+ step(obstacle, dir)
+ else if(ismob(obstacle))
+ var/mob/mob_obstacle = obstacle
+ if(mob_obstacle.move_resist <= move_force)
+ step(obstacle, dir)
@@ -687,7 +703,7 @@
//////// Internal damage ////////
///////////////////////////////////
-/obj/mecha/proc/check_for_internal_damage(list/possible_int_damage,ignore_threshold=null)
+/obj/vehicle/sealed/mecha/proc/check_for_internal_damage(list/possible_int_damage,ignore_threshold=null)
if(!islist(possible_int_damage) || !length(possible_int_damage))
return
if(prob(20))
@@ -701,25 +717,25 @@
setInternalDamage(int_dam_flag)
if(prob(5))
if(ignore_threshold || obj_integrity*100/max_integrity < internal_damage_threshold)
- if (length(equipment))
+ if(LAZYLEN(equipment))
var/obj/item/mecha_parts/mecha_equipment/ME = pick(equipment)
qdel(ME)
-/obj/mecha/proc/setInternalDamage(int_dam_flag)
+/obj/vehicle/sealed/mecha/proc/setInternalDamage(int_dam_flag)
internal_damage |= int_dam_flag
log_message("Internal damage of type [int_dam_flag].", LOG_MECHA)
- SEND_SOUND(occupant, sound('sound/machines/warning-buzzer.ogg',wait=0))
+ SEND_SOUND(occupants, sound('sound/machines/warning-buzzer.ogg',wait=0))
diag_hud_set_mechstat()
-/obj/mecha/proc/clearInternalDamage(int_dam_flag)
+/obj/vehicle/sealed/mecha/proc/clearInternalDamage(int_dam_flag)
if(internal_damage & int_dam_flag)
switch(int_dam_flag)
if(MECHA_INT_TEMP_CONTROL)
- occupant_message("Life support system reactivated.")
+ to_chat(occupants, "[icon2html(src, occupants)]Life support system reactivated.")
if(MECHA_INT_FIRE)
- occupant_message("Internal fire extinguished.")
+ to_chat(occupants, "[icon2html(src, occupants)]Internal fire extinguished.")
if(MECHA_INT_TANK_BREACH)
- occupant_message("Damaged internal tank has been sealed.")
+ to_chat(occupants, "[icon2html(src, occupants)]Damaged internal tank has been sealed.")
internal_damage &= ~int_dam_flag
diag_hud_set_mechstat()
@@ -727,7 +743,7 @@
//////////// AI piloting ////////////
/////////////////////////////////////
-/obj/mecha/attack_ai(mob/living/silicon/ai/user)
+/obj/vehicle/sealed/mecha/attack_ai(mob/living/silicon/ai/user)
if(!isAI(user))
return
//Allows the Malf to scan a mech's status and loadout, helping it to decide if it is a worthy chariot.
@@ -741,7 +757,7 @@
to_chat(user, "ASSUME DIRECT CONTROL?
")
else
examine(user)
- if(occupant)
+ if(length(return_drivers()) > 0)
to_chat(user, "This exosuit has a pilot and cannot be controlled.")
return
var/can_control_mech = 0
@@ -754,42 +770,40 @@
return
to_chat(user, "Take control of exosuit?
")
-/obj/mecha/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
+/obj/vehicle/sealed/mecha/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
if(!..())
return
- //Transfer from core or card to mech. Proc is called by mech.
+ //Transfer from core or card to mech. Proc is called by mech.
switch(interaction)
if(AI_TRANS_TO_CARD) //Upload AI from mech to AI card.
if(!construction_state) //Mech must be in maint mode to allow carding.
to_chat(user, "[name] must have maintenance protocols active in order to allow a transfer.")
return
- AI = occupant
- if(!AI || !isAI(occupant)) //Mech does not have an AI for a pilot
+ if(!locate(AI) in occupants) //Mech does not have an AI for a pilot
to_chat(user, "No AI detected in the [name] onboard computer.")
return
+ for(var/mob/living/silicon/ai in occupants)
AI.ai_restore_power()//So the AI initially has power.
AI.control_disabled = TRUE
AI.radio_enabled = FALSE
AI.disconnect_shell()
- RemoveActions(AI, TRUE)
- occupant = null
- silicon_pilot = FALSE
+ remove_occupant(AI)
+ mecha_flags &= ~SILICON_PILOT
AI.forceMove(card)
card.AI = AI
AI.controlled_mech = null
AI.remote_control = null
- icon_state = initial(icon_state)+"-open"
to_chat(AI, "You have been downloaded to a mobile storage device. Wireless connection offline.")
to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
if(AI_MECH_HACK) //Called by AIs on the mech
AI.linked_core = new /obj/structure/ai_core/deactivated(AI.loc)
if(AI.can_dominate_mechs)
- if(occupant) //Oh, I am sorry, were you using that?
- to_chat(AI, "Pilot detected! Forced ejection initiated!")
- to_chat(occupant, "You have been forcibly ejected!")
- go_out(1) //IT IS MINE, NOW. SUCK IT, RD!
+ if(LAZYLEN(occupants)) //Oh, I am sorry, were you using that?
+ to_chat(AI, "Occupants detected! Forced ejection initiated!")
+ to_chat(occupants, "You have been forcibly ejected!")
+ ejectall() //IT IS MINE, NOW. SUCK IT, RD!
ai_enter_mech(AI, interaction)
if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech.
@@ -802,8 +816,8 @@
if(AI.stat || !AI.client)
to_chat(user, "[AI.name] is currently unresponsive, and cannot be uploaded.")
return
- if(occupant || dna_lock) //Normal AIs cannot steal mechs!
- to_chat(user, "Access denied. [name] is [occupant ? "currently occupied" : "secured with a DNA lock"].")
+ if((LAZYLEN(occupants) >= max_occupants) || dna_lock) //Normal AIs cannot steal mechs!
+ to_chat(user, "Access denied. [name] is [LAZYLEN(occupants) >= max_occupants ? "currently fully occupied" : "secured with a DNA lock"].")
return
AI.control_disabled = FALSE
AI.radio_enabled = TRUE
@@ -812,171 +826,160 @@
ai_enter_mech(AI, interaction)
//Hack and From Card interactions share some code, so leave that here for both to use.
-/obj/mecha/proc/ai_enter_mech(mob/living/silicon/ai/AI, interaction)
+/obj/vehicle/sealed/mecha/proc/ai_enter_mech(mob/living/silicon/ai/AI, interaction)
AI.ai_restore_power()
- AI.forceMove(src)
- occupant = AI
- silicon_pilot = TRUE
- icon_state = initial(icon_state)
- update_icon()
- playsound(src, 'sound/machines/windowdoor.ogg', 50, TRUE)
- if(!internal_damage)
- SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
+ mecha_flags |= SILICON_PILOT
+ moved_inside(AI)
AI.cancel_camera()
AI.controlled_mech = src
AI.remote_control = src
AI.mobility_flags = ALL //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow.
- AI.can_shunt = 0 //ONE AI ENTERS. NO AI LEAVES.
+ if(interaction == AI_MECH_HACK)
+ AI.can_shunt = FALSE //ONE AI ENTERS. NO AI LEAVES.
to_chat(AI, AI.can_dominate_mechs ? "Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!" :\
"You have been uploaded to a mech's onboard computer.")
to_chat(AI, "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.")
- if(interaction == AI_TRANS_FROM_CARD)
- GrantActions(AI, FALSE) //No eject/return to core action for AI uploaded by card
- else
- GrantActions(AI, !AI.can_dominate_mechs)
-//An actual AI (simple_animal mecha pilot) entering the mech
-/obj/mecha/proc/aimob_enter_mech(mob/living/simple_animal/hostile/syndicate/mecha_pilot/pilot_mob)
+///Handles an actual AI (simple_animal mecha pilot) entering the mech
+/obj/vehicle/sealed/mecha/proc/aimob_enter_mech(mob/living/simple_animal/hostile/syndicate/mecha_pilot/pilot_mob)
if(pilot_mob && pilot_mob.Adjacent(src))
- if(occupant)
+ if(occupants)
return
- icon_state = initial(icon_state)
- occupant = pilot_mob
+ LAZYADD(occupants, src)
pilot_mob.mecha = src
pilot_mob.forceMove(src)
- GrantActions(pilot_mob)//needed for checks, and incase a badmin puts somebody in the mob
+ update_icon()
-/obj/mecha/proc/aimob_exit_mech(mob/living/simple_animal/hostile/syndicate/mecha_pilot/pilot_mob)
- if(occupant == pilot_mob)
- occupant = null
+///Handles an actual AI (simple_animal mecha pilot) exiting the mech
+/obj/vehicle/sealed/mecha/proc/aimob_exit_mech(mob/living/simple_animal/hostile/syndicate/mecha_pilot/pilot_mob)
+ LAZYREMOVE(occupants, pilot_mob)
if(pilot_mob.mecha == src)
pilot_mob.mecha = null
- icon_state = "[initial(icon_state)]-open"
pilot_mob.forceMove(get_turf(src))
- RemoveActions(pilot_mob)
+ update_icon()
/////////////////////////////////////
//////// Atmospheric stuff ////////
/////////////////////////////////////
-/obj/mecha/remove_air(amount)
+/obj/vehicle/sealed/mecha/remove_air(amount)
if(use_internal_tank)
return cabin_air.remove(amount)
return ..()
-/obj/mecha/return_air()
+/obj/vehicle/sealed/mecha/return_air()
if(use_internal_tank)
return cabin_air
return ..()
-/obj/mecha/return_analyzable_air()
+/obj/vehicle/sealed/mecha/return_analyzable_air()
return cabin_air
-/obj/mecha/proc/return_pressure()
+/obj/vehicle/sealed/mecha/proc/return_pressure()
var/datum/gas_mixture/t_air = return_air()
if(t_air)
- . = t_air.return_pressure()
+ return t_air.return_pressure()
-/obj/mecha/return_temperature()
+/obj/vehicle/sealed/mecha/return_temperature()
var/datum/gas_mixture/t_air = return_air()
if(t_air)
- . = t_air.return_temperature()
+ return t_air.return_temperature()
-/obj/mecha/MouseDrop_T(mob/M, mob/user)
- if((user != M) || user.incapacitated() || !Adjacent(user))
+/obj/vehicle/sealed/mecha/mob_try_enter(mob/M)
+ if(!ishuman(M)) // no silicons or drones in mechas.
return
- if(!ishuman(user)) // no silicons or drones in mechas.
+ if(HAS_TRAIT(M, TRAIT_PRIMITIVE)) //no lavalizards either.
+ to_chat(M, "The knowledge to use this device eludes you!")
return
- if(HAS_TRAIT(user, TRAIT_PRIMITIVE)) //no lavalizards either.
- to_chat(user, "The knowledge to use this device eludes you!")
- return
- log_message("[user] tries to move in.", LOG_MECHA)
- if (occupant)
- to_chat(usr, "The [name] is already occupied!")
- log_message("Permission denied (Occupied).", LOG_MECHA)
- return
- if(dna_lock)
- var/passed = FALSE
- if(user.has_dna())
- var/mob/living/carbon/C = user
- if(C.dna.unique_enzymes==dna_lock)
- passed = TRUE
- if (!passed)
- to_chat(user, "Access denied. [name] is secured with a DNA lock.")
+ log_message("[M] tries to move into [src].", LOG_MECHA)
+ if(dna_lock && M.has_dna())
+ var/mob/living/carbon/entering_carbon = M
+ if(entering_carbon.dna.unique_enzymes != dna_lock)
+ to_chat(M, "Access denied. [name] is secured with a DNA lock.")
log_message("Permission denied (DNA LOCK).", LOG_MECHA)
return
- if(!operation_allowed(user))
- to_chat(user, "Access denied. Insufficient operation keycodes.")
+ if(!operation_allowed(M))
+ to_chat(M, "Access denied. Insufficient operation keycodes.")
log_message("Permission denied (No keycode).", LOG_MECHA)
return
- if(user.buckled)
- to_chat(user, "You are currently buckled and cannot move.")
+ if(M.buckled)
+ to_chat(M, "You are currently buckled and cannot move.")
log_message("Permission denied (Buckled).", LOG_MECHA)
return
- if(user.has_buckled_mobs()) //mob attached to us
- to_chat(user, "You can't enter the exosuit with other creatures attached to you!")
+ if(M.has_buckled_mobs()) //mob attached to us
+ to_chat(M, "You can't enter the exosuit with other creatures attached to you!")
log_message("Permission denied (Attached mobs).", LOG_MECHA)
return
- visible_message("[user] starts to climb into [name].")
+ visible_message("[M] starts to climb into [name].")
- if(do_after(user, enter_delay, target = src))
+ if(do_after(M, enter_delay, target = src))
if(obj_integrity <= 0)
- to_chat(user, "You cannot get in the [name], it has been destroyed!")
- else if(occupant)
- to_chat(user, "[occupant] was faster! Try better next time, loser.")
- else if(user.buckled)
- to_chat(user, "You can't enter the exosuit while buckled.")
- else if(user.has_buckled_mobs())
- to_chat(user, "You can't enter the exosuit with other creatures attached to you!")
+ to_chat(M, "You cannot get in the [name], it has been destroyed!")
+ else if(LAZYLEN(occupants) >= max_occupants)
+ to_chat(M, "[occupants[occupants.len]] was faster! Try better next time, loser.")//get the last one that hopped in
+ else if(M.buckled)
+ to_chat(M, "You can't enter the exosuit while buckled.")
+ else if(M.has_buckled_mobs())
+ to_chat(M, "You can't enter the exosuit with other creatures attached to you!")
else
- moved_inside(user)
+ moved_inside(M)
+ return ..()
else
- to_chat(user, "You stop entering the exosuit!")
+ to_chat(M, "You stop entering the exosuit!")
-/obj/mecha/proc/moved_inside(mob/living/carbon/human/H)
- . = FALSE
- if(H && H.client && (H in range(1)))
- occupant = H
- H.forceMove(src)
- H.update_mouse_pointer()
- add_fingerprint(H)
- GrantActions(H, human_occupant=1)
- forceMove(loc)
- log_message("[H] moved in as pilot.", LOG_MECHA)
- icon_state = initial(icon_state)
- setDir(dir_in)
- playsound(src, 'sound/machines/windowdoor.ogg', 50, TRUE)
- if(!internal_damage)
- SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
- return TRUE
-/obj/mecha/proc/mmi_move_inside(obj/item/mmi/M, mob/user)
+/obj/vehicle/sealed/mecha/generate_actions()
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_eject)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_internals)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_cycle_equip)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_lights)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_view_stats)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/strafe)
+
+/obj/vehicle/sealed/mecha/proc/moved_inside(mob/living/H)
. = FALSE
- if(!M.brain_check(user))
+ if(!(H?.client))
return
+ if(ishuman(H) && !Adjacent(H))
+ return
+ add_occupant(H)
+ H.forceMove(src)
+ H.update_mouse_pointer()
+ add_fingerprint(H)
+ log_message("[H] moved in as pilot.", LOG_MECHA)
+ setDir(dir_in)
+ playsound(src, 'sound/machines/windowdoor.ogg', 50, TRUE)
+ if(!internal_damage)
+ SEND_SOUND(H, sound('sound/mecha/nominal.ogg',volume=50))
+ return TRUE
+
+/obj/vehicle/sealed/mecha/proc/mmi_move_inside(obj/item/mmi/M, mob/user)
+ if(!M.brain_check(user))
+ return FALSE
var/mob/living/brain/B = M.brainmob
- if(occupant)
- to_chat(user, "Occupant detected!")
- return
+ if(LAZYLEN(occupants) >= max_occupants)
+ to_chat(user, "It's full!")
+ return FALSE
if(dna_lock && (!B.stored_dna || (dna_lock != B.stored_dna.unique_enzymes)))
to_chat(user, "Access denied. [name] is secured with a DNA lock.")
- return
+ return FALSE
visible_message("[user] starts to insert an MMI into [name].")
if(do_after(user, 40, target = src))
- if(!occupant)
+ if(LAZYLEN(occupants) < max_occupants)
return mmi_moved_inside(M, user)
else
- to_chat(user, "Occupant detected!")
+ to_chat(user, "Maximum occupants detected!")
else
to_chat(user, "You stop inserting the MMI.")
+ return FALSE
-/obj/mecha/proc/mmi_moved_inside(obj/item/mmi/M, mob/user)
+/obj/vehicle/sealed/mecha/proc/mmi_moved_inside(obj/item/mmi/M, mob/user)
if(!(Adjacent(M) && Adjacent(user)))
return FALSE
if(!M.brain_check(user))
@@ -988,69 +991,53 @@
return FALSE
M.mecha = src
- occupant = B
- silicon_pilot = TRUE
- B.forceMove(src) //should allow relaymove
+ add_occupant(B)//Note this forcemoves the brain into the mech to allow relaymove
+ mecha_flags |= SILICON_PILOT
B.reset_perspective(src)
B.remote_control = src
B.update_mobility()
B.update_mouse_pointer()
- icon_state = initial(icon_state)
update_icon()
setDir(dir_in)
log_message("[M] moved in as pilot.", LOG_MECHA)
if(!internal_damage)
- SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
- GrantActions(B)
+ SEND_SOUND(M, sound('sound/mecha/nominal.ogg',volume=50))
log_game("[key_name(user)] has put the MMI/posibrain of [key_name(B)] into [src] at [AREACOORD(src)]")
return TRUE
-/obj/mecha/container_resist_act(mob/living/user)
+/obj/vehicle/sealed/mecha/container_resist_act(mob/living/user)
+ if(isAI(user))
+ var/mob/living/silicon/ai/AI = user
+ if(!AI.can_shunt)
+ to_chat(AI, "You can't leave a mech after dominating it!.")
+ return FALSE
+ to_chat(user, "You begin the ejection procedure. Equipment is disabled during this process. Hold still to finish ejecting.")
is_currently_ejecting = TRUE
- to_chat(occupant, "You begin the ejection procedure. Equipment is disabled during this process. Hold still to finish ejecting.")
- if(do_after(occupant, has_gravity() ? exit_delay : 0 , target = src))
- to_chat(occupant, "You exit the mech.")
- go_out()
+ if(do_after(user, has_gravity() ? exit_delay : 0 , target = src))
+ to_chat(user, "You exit the mech.")
+ mob_exit(user, TRUE)
else
- to_chat(occupant, "You stop exiting the mech. Weapons are enabled again.")
+ to_chat(user, "You stop exiting the mech. Weapons are enabled again.")
is_currently_ejecting = FALSE
-/obj/mecha/Exited(atom/movable/M, atom/newloc)
- if(occupant && occupant == M) // The occupant exited the mech without calling go_out()
- go_out(TRUE, newloc)
+/obj/vehicle/sealed/mecha/proc/ejectall()
+ for(var/ejectee in occupants)
+ mob_exit(ejectee, TRUE, TRUE)
- if(cell && cell == M)
- cell = null
- return
- if(scanmod && scanmod == M)
- scanmod = null
- update_part_values()
- return
- if(capacitor && capacitor == M)
- armor = armor.modifyRating(energy = (capacitor.rating * -5)) //lose the energy armor if we lose this cap
- capacitor = null
- update_part_values()
-
-/obj/mecha/proc/go_out(forced, atom/newloc = loc)
- if(!occupant)
- return
+/obj/vehicle/sealed/mecha/mob_exit(mob/M, silent, forced)
+ var/newloc = get_turf(src)
var/atom/movable/mob_container
- occupant.clear_alert("charge")
- occupant.clear_alert("mech damage")
- if(ishuman(occupant))
- mob_container = occupant
- RemoveActions(occupant, human_occupant=1)
- else if(isbrain(occupant))
- var/mob/living/brain/brain = occupant
- RemoveActions(brain)
+ if(ishuman(M))
+ mob_container = M
+ else if(isbrain(M))
+ var/mob/living/brain/brain = M
mob_container = brain.container
- else if(isAI(occupant))
- var/mob/living/silicon/ai/AI = occupant
+ else if(isAI(M))
+ var/mob/living/silicon/ai/AI = M
if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf.
- RemoveActions(occupant)
- occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
- occupant = null
- silicon_pilot = FALSE
+ AI.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
+ AI = null
+ mecha_flags &= ~SILICON_PILOT
return
else
if(!AI.linked_core)
@@ -1060,15 +1047,13 @@
to_chat(AI, "Returning to core...")
AI.controlled_mech = null
AI.remote_control = null
- RemoveActions(occupant, 1)
mob_container = AI
newloc = get_turf(AI.linked_core)
qdel(AI.linked_core)
else
- return
- var/mob/living/L = occupant
- occupant = null //we need it null when forceMove calls Exited().
- silicon_pilot = FALSE
+ return ..()
+ var/mob/living/L = M
+ mecha_flags &= ~SILICON_PILOT
if(mob_container.forceMove(newloc))//ejecting mob container
log_message("[mob_container] moved out.", LOG_MECHA)
L << browse(null, "window=exosuit")
@@ -1078,53 +1063,65 @@
if(mmi.brainmob)
L.forceMove(mmi)
L.reset_perspective()
+ remove_occupant(L)
mmi.mecha = null
mmi.update_icon()
L.mobility_flags = NONE
- icon_state = initial(icon_state)+"-open"
+ update_icon()
setDir(dir_in)
+ return ..()
- if(L && L.client)
- L.update_mouse_pointer()
- L.client.view_size.resetToDefault()
+
+/obj/vehicle/sealed/mecha/add_occupant(mob/M, control_flags)
+ RegisterSignal(M, COMSIG_MOB_DEATH, .proc/mob_exit)
+ RegisterSignal(M, COMSIG_MOB_CLICKON, .proc/on_mouseclick)
+ RegisterSignal(M, COMSIG_MOB_SAY, .proc/display_speech_bubble)
+ update_icon()
+ return ..()
+
+/obj/vehicle/sealed/mecha/remove_occupant(mob/M)
+ UnregisterSignal(M, COMSIG_MOB_DEATH)
+ UnregisterSignal(M, COMSIG_MOB_CLICKON)
+ UnregisterSignal(M, COMSIG_MOB_SAY)
+ update_icon()
+ M.clear_alert("charge")
+ M.clear_alert("mech damage")
+ if(M.client)
+ M.update_mouse_pointer()
+ M.client.view_size.resetToDefault()
zoom_mode = 0
+ return ..()
/////////////////////////
////// Access stuff /////
/////////////////////////
-/obj/mecha/proc/operation_allowed(mob/M)
+/obj/vehicle/sealed/mecha/proc/operation_allowed(mob/M)
req_access = operation_req_access
req_one_access = list()
return allowed(M)
-/obj/mecha/proc/internals_access_allowed(mob/M)
+/obj/vehicle/sealed/mecha/proc/internals_access_allowed(mob/M)
req_one_access = internals_req_access
req_access = list()
return allowed(M)
-
-
////////////////////////////////
/////// Messages and Log ///////
////////////////////////////////
-/obj/mecha/proc/occupant_message(message as text)
- if(message)
- if(occupant && occupant.client)
- to_chat(occupant, "[icon2html(src, occupant)] [message]")
-
GLOBAL_VAR_INIT(year, time2text(world.realtime,"YYYY"))
GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013???
+//why is this in mecha
///////////////////////
///// Power stuff /////
///////////////////////
-/obj/mecha/proc/has_charge(amount)
+/obj/vehicle/sealed/mecha/proc/has_charge(amount)
return (get_charge()>=amount)
-/obj/mecha/proc/get_charge()
+/obj/vehicle/sealed/mecha/proc/get_charge()
for(var/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/R in equipment)
var/relay_charge = R.get_charge()
if(relay_charge)
@@ -1132,27 +1129,22 @@ GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013???
if(cell)
return max(0, cell.charge)
-/obj/mecha/proc/use_power(amount)
+/obj/vehicle/sealed/mecha/proc/use_power(amount)
if(get_charge() && cell.use(amount))
- return 1
- return 0
+ return TRUE
+ return FALSE
-/obj/mecha/proc/give_power(amount)
+/obj/vehicle/sealed/mecha/proc/give_power(amount)
if(!isnull(get_charge()))
cell.give(amount)
- return 1
- return 0
-
-/obj/mecha/update_remote_sight(mob/living/user)
- if(occupant_sight_flags)
- if(user == occupant)
- user.sight |= occupant_sight_flags
+ return TRUE
+ return FALSE
///////////////////////
////// Ammo stuff /////
///////////////////////
-/obj/mecha/proc/ammo_resupply(obj/item/mecha_ammo/A, mob/user,fail_chat_override = FALSE)
+/obj/vehicle/sealed/mecha/proc/ammo_resupply(obj/item/mecha_ammo/A, mob/user,fail_chat_override = FALSE)
if(!A.rounds)
if(!fail_chat_override)
to_chat(user, "This box of ammo is empty!")
diff --git a/code/game/mecha/combat/combat.dm b/code/modules/vehicles/mecha/combat/combat.dm
similarity index 75%
rename from code/game/mecha/combat/combat.dm
rename to code/modules/vehicles/mecha/combat/combat.dm
index d0e8a62cc65..4f964017958 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/modules/vehicles/mecha/combat/combat.dm
@@ -1,4 +1,4 @@
-/obj/mecha/combat
+/obj/vehicle/sealed/mecha/combat
force = 30
internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_SECURITY)
internal_damage_threshold = 50
@@ -7,11 +7,12 @@
destruction_sleep_duration = 40
exit_delay = 40
-/obj/mecha/combat/restore_equipment()
+/obj/vehicle/sealed/mecha/combat/restore_equipment()
mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi'
. = ..()
-/obj/mecha/combat/proc/max_ammo() //Max the ammo stored for Nuke Ops mechs, or anyone else that calls this
+
+/obj/vehicle/sealed/mecha/combat/proc/max_ammo() //Max the ammo stored for Nuke Ops mechs, or anyone else that calls this
for(var/obj/item/I in equipment)
if(istype(I, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/))
var/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/gun = I
diff --git a/code/game/mecha/combat/durand.dm b/code/modules/vehicles/mecha/combat/durand.dm
similarity index 57%
rename from code/game/mecha/combat/durand.dm
rename to code/modules/vehicles/mecha/combat/durand.dm
index 1e40ba99bc0..576b5bacd0b 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/modules/vehicles/mecha/combat/durand.dm
@@ -1,81 +1,80 @@
-/obj/mecha/combat/durand
+/obj/vehicle/sealed/mecha/combat/durand
desc = "An aging combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms."
name = "\improper Durand"
icon_state = "durand"
- step_in = 4
+ movedelay = 4
dir_in = 1 //Facing North.
max_integrity = 400
deflect_chance = 20
armor = list(MELEE = 40, BULLET = 35, LASER = 15, ENERGY = 10, BOMB = 20, BIO = 0, RAD = 50, FIRE = 100, ACID = 100)
max_temperature = 30000
- infra_luminosity = 8
force = 40
wreckage = /obj/structure/mecha_wreckage/durand
var/obj/durand_shield/shield
-/obj/mecha/combat/durand/Initialize()
+/obj/vehicle/sealed/mecha/combat/durand/Initialize()
. = ..()
shield = new /obj/durand_shield(loc, src, layer, dir)
- RegisterSignal(src, COMSIG_MECHA_ACTION_ACTIVATE, .proc/relay)
+ RegisterSignal(src, COMSIG_MECHA_ACTION_TRIGGER, .proc/relay)
RegisterSignal(src, COMSIG_PROJECTILE_PREHIT, .proc/prehit)
-/obj/mecha/combat/durand/Destroy()
+/obj/vehicle/sealed/mecha/combat/durand/Destroy()
if(shield)
QDEL_NULL(shield)
return ..()
-/obj/mecha/combat/durand/GrantActions(mob/living/user, human_occupant = 0)
- ..()
- defense_action.Grant(user, src)
-
-/obj/mecha/combat/durand/RemoveActions(mob/living/user, human_occupant = 0)
- ..()
- defense_action.Remove(user)
-
-/obj/mecha/combat/durand/process()
+/obj/vehicle/sealed/mecha/combat/durand/generate_actions()
. = ..()
- if(defense_mode && !use_power(100))
- defense_action.Activate(forced_state = TRUE)
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_defense_mode)
-/obj/mecha/combat/durand/domove(direction)
+/obj/vehicle/sealed/mecha/combat/durand/process()
+ . = ..()
+ if(defense_mode && !use_power(100)) //Defence mode can only be on with a occupant so we check if one of them can toggle it and toggle
+ for(var/O in occupants)
+ var/mob/living/occupant = O
+ var/datum/action/action = LAZYACCESSASSOC(occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/mech_defense_mode)
+ if(action)
+ action.Trigger()
+ break
+
+/obj/vehicle/sealed/mecha/combat/durand/Move(direction)
. = ..()
if(shield)
shield.forceMove(loc)
shield.setDir(dir)
-/obj/mecha/combat/durand/forceMove(turf/T)
+/obj/vehicle/sealed/mecha/combat/durand/forceMove(turf/T)
. = ..()
shield.forceMove(T)
-/obj/mecha/combat/durand/go_out(forced, atom/newloc = loc)
+/obj/vehicle/sealed/mecha/combat/durand/mob_exit(mob/M, silent, randomstep, forced)
if(defense_mode)
- defense_action.Activate(forced_state = TRUE)
- . = ..()
+ var/datum/action/action = LAZYACCESSASSOC(occupant_actions, M, /datum/action/vehicle/sealed/mecha/mech_defense_mode)
+ if(action)
+ action.Trigger(FALSE)
+ return ..()
///Relays the signal from the action button to the shield, and creates a new shield if the old one is MIA.
-/obj/mecha/combat/durand/proc/relay(datum/source, list/signal_args)
+/obj/vehicle/sealed/mecha/combat/durand/proc/relay(datum/source, mob/owner, list/signal_args)
SIGNAL_HANDLER
-
if(!shield) //if the shield somehow got deleted
stack_trace("Durand triggered relay without a shield")
shield = new /obj/durand_shield(loc, src, layer)
shield.setDir(dir)
- SEND_SIGNAL(shield, COMSIG_MECHA_ACTION_ACTIVATE, source, signal_args)
+ SEND_SIGNAL(shield, COMSIG_MECHA_ACTION_TRIGGER, owner, signal_args)
//Redirects projectiles to the shield if defense_check decides they should be blocked and returns true.
-/obj/mecha/combat/durand/proc/prehit(obj/projectile/source, list/signal_args)
- SIGNAL_HANDLER
-
+/obj/vehicle/sealed/mecha/combat/durand/proc/prehit(obj/projectile/source, list/signal_args)
if(defense_check(source.loc) && shield)
signal_args[2] = shield
/**Checks if defense mode is enabled, and if the attacker is standing in an area covered by the shield.
Expects a turf. Returns true if the attack should be blocked, false if not.*/
-/obj/mecha/combat/durand/proc/defense_check(turf/aloc)
+/obj/vehicle/sealed/mecha/combat/durand/proc/defense_check(turf/aloc)
if (!defense_mode || !shield || shield.switching)
return FALSE
. = FALSE
@@ -94,14 +93,14 @@ Expects a turf. Returns true if the attack should be blocked, false if not.*/
. = TRUE
return
-/obj/mecha/combat/durand/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0)
+/obj/vehicle/sealed/mecha/combat/durand/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0)
if(defense_check(user.loc))
log_message("Attack absorbed by defense field. Attacker - [user].", LOG_MECHA, color="orange")
shield.attack_generic(user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration)
else
. = ..()
-/obj/mecha/combat/durand/blob_act(obj/structure/blob/B)
+/obj/vehicle/sealed/mecha/combat/durand/blob_act(obj/structure/blob/B)
if(defense_check(B.loc))
log_message("Attack by blob. Attacker - [B].", LOG_MECHA, color="red")
log_message("Attack absorbed by defense field.", LOG_MECHA, color="orange")
@@ -109,14 +108,14 @@ Expects a turf. Returns true if the attack should be blocked, false if not.*/
else
. = ..()
-/obj/mecha/combat/durand/attackby(obj/item/W as obj, mob/user as mob, params)
+/obj/vehicle/sealed/mecha/combat/durand/attackby(obj/item/W as obj, mob/user as mob, params)
if(defense_check(user.loc))
log_message("Attack absorbed by defense field. Attacker - [user], with [W]", LOG_MECHA, color="orange")
shield.attackby(W, user, params)
else
. = ..()
-/obj/mecha/combat/durand/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
+/obj/vehicle/sealed/mecha/combat/durand/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(defense_check(AM.loc))
log_message("Impact with [AM] absorbed by defense field.", LOG_MECHA, color="orange")
shield.hitby(AM, skipcatch, hitpush, blocked, throwingdatum)
@@ -147,8 +146,11 @@ own integrity back to max. Shield is automatically dropped if we run out of powe
light_power = 5
light_color = LIGHT_COLOR_ELECTRIC_CYAN
light_on = FALSE
- var/obj/mecha/combat/durand/chassis ///Our link back to the durand
- var/switching = FALSE ///To keep track of things during the animation
+ ///Our link back to the durand
+ var/obj/vehicle/sealed/mecha/combat/durand/chassis
+ ///To keep track of things during the animation
+ var/switching = FALSE
+ var/currentuser
/obj/durand_shield/Initialize(mapload, _chassis, _layer, _dir)
@@ -156,7 +158,7 @@ own integrity back to max. Shield is automatically dropped if we run out of powe
chassis = _chassis
layer = _layer
setDir(_dir)
- RegisterSignal(src, COMSIG_MECHA_ACTION_ACTIVATE, .proc/activate)
+ RegisterSignal(src, COMSIG_MECHA_ACTION_TRIGGER, .proc/activate)
/obj/durand_shield/Destroy()
@@ -165,29 +167,36 @@ own integrity back to max. Shield is automatically dropped if we run out of powe
chassis = null
return ..()
-/**Handles activating and deactivating the shield. This proc is called by a signal sent from the mech's action button
-and relayed by the mech itself. The "forced" variabe, signal_args[1], will skip the to-pilot text and is meant for when
-the shield is disabled by means other than the action button (like running out of power)*/
-
-/obj/durand_shield/proc/activate(datum/source, datum/action/innate/mecha/mech_defense_mode/button, list/signal_args)
+/**
+ *Handles activating and deactivating the shield. This proc is called by a signal sent from the mech's action button
+ *and relayed by the mech itself. The "forced" variabe, signal_args[1], will skip the to-pilot text and is meant for when
+ *the shield is disabled by means other than the action button (like running out of power)
+ * Arguments:
+ * * source: the shield
+ * * owner: mob that activated the shield
+ * * signal_args: whether it's forced
+ */
+/obj/durand_shield/proc/activate(datum/source, mob/owner, list/signal_args)
SIGNAL_HANDLER
-
- if(!chassis || !chassis.occupant)
+ currentuser = owner
+ if(!chassis?.occupants)
return
if(switching && !signal_args[1])
return
if(!chassis.defense_mode && (!chassis.cell || chassis.cell.charge < 100)) //If it's off, and we have less than 100 units of power
- chassis.occupant_message("Insufficient power; cannot activate defense mode.")
+ to_chat(currentuser, "[icon2html(src, currentuser)]Insufficient power; cannot activate defense mode.")
return
switching = TRUE
chassis.defense_mode = !chassis.defense_mode
- chassis.defense_action.button_icon_state = "mech_defense_mode_[chassis.defense_mode ? "on" : "off"]" //This is backwards because we haven't changed the var yet
if(!signal_args[1])
- chassis.occupant_message("Defense mode [chassis.defense_mode?"enabled":"disabled"].")
+ to_chat(currentuser, "[icon2html(src, currentuser)]Defense mode [chassis.defense_mode?"enabled":"disabled"].")
chassis.log_message("User has toggled defense mode -- now [chassis.defense_mode?"enabled":"disabled"].", LOG_MECHA)
else
chassis.log_message("defense mode state changed -- now [chassis.defense_mode?"enabled":"disabled"].", LOG_MECHA)
- chassis.defense_action.UpdateButtonIcon()
+ for(var/occupant in chassis.occupants)
+ var/datum/action/button = chassis.occupant_actions[occupant][/datum/action/vehicle/sealed/mecha/mech_defense_mode]
+ button.button_icon_state = "mech_defense_mode_[chassis.defense_mode ? "on" : "off"]"
+ button.UpdateButtonIcon()
set_light_on(chassis.defense_mode)
@@ -195,19 +204,20 @@ the shield is disabled by means other than the action button (like running out o
invisibility = 0
flick("shield_raise", src)
playsound(src, 'sound/mecha/mech_shield_raise.ogg', 50, FALSE)
- addtimer(CALLBACK(src, .proc/shield_icon_enable), 3)
+ set_light(l_range = MINIMUM_USEFUL_LIGHT_RANGE , l_power = 5, l_color = "#00FFFF")
+ icon_state = "shield"
+ RegisterSignal(chassis, COMSIG_ATOM_DIR_CHANGE, .proc/resetdir)
else
flick("shield_drop", src)
playsound(src, 'sound/mecha/mech_shield_drop.ogg', 50, FALSE)
- addtimer(CALLBACK(src, .proc/shield_icon_reset), 5)
+ set_light(0)
+ icon_state = "shield_null"
+ invisibility = INVISIBILITY_MAXIMUM //no showing on right-click
+ UnregisterSignal(chassis, COMSIG_ATOM_DIR_CHANGE)
switching = FALSE
-/obj/durand_shield/proc/shield_icon_enable()
- icon_state = "shield"
-
-/obj/durand_shield/proc/shield_icon_reset()
- icon_state = "shield_null"
- invisibility = INVISIBILITY_MAXIMUM //no showing on right-click
+/obj/durand_shield/proc/resetdir(datum/source, olddir, newdir)
+ setDir(newdir)
/obj/durand_shield/take_damage()
if(!chassis)
@@ -219,7 +229,10 @@ the shield is disabled by means other than the action button (like running out o
flick("shield_impact", src)
if(!chassis.use_power((max_integrity - obj_integrity) * 100))
chassis.cell?.charge = 0
- chassis.defense_action.Activate(forced_state = TRUE)
+ for(var/O in chassis.occupants)
+ var/mob/living/occupant = O
+ var/datum/action/action = LAZYACCESSASSOC(chassis.occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/mech_defense_mode)
+ action.Trigger(FALSE)
obj_integrity = 10000
/obj/durand_shield/play_attack_sound()
diff --git a/code/game/mecha/combat/gygax.dm b/code/modules/vehicles/mecha/combat/gygax.dm
similarity index 73%
rename from code/game/mecha/combat/gygax.dm
rename to code/modules/vehicles/mecha/combat/gygax.dm
index b9ea3287ae4..a90b7763741 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/modules/vehicles/mecha/combat/gygax.dm
@@ -1,27 +1,22 @@
-/obj/mecha/combat/gygax
+/obj/vehicle/sealed/mecha/combat/gygax
desc = "A lightweight, security exosuit. Popular among private and corporate security."
name = "\improper Gygax"
icon_state = "gygax"
- step_in = 3
+ allow_diagonal_movement = TRUE
+ movedelay = 3
dir_in = 1 //Facing North.
max_integrity = 250
deflect_chance = 5
armor = list(MELEE = 25, BULLET = 20, LASER = 30, ENERGY = 15, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
max_temperature = 25000
leg_overload_coeff = 80
- infra_luminosity = 6
force = 25
wreckage = /obj/structure/mecha_wreckage/gygax
internal_damage_threshold = 35
max_equip = 3
step_energy_drain = 3
-/obj/mecha/combat/gygax/mechturn(direction)
- . = ..()
- if(!strafe && !occupant.client.keys_held["Alt"])
- mechstep(direction) //agile mechs get to move and turn in the same step
-
-/obj/mecha/combat/gygax/dark
+/obj/vehicle/sealed/mecha/combat/gygax/dark
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
name = "\improper Dark Gygax"
icon_state = "darkgygax"
@@ -37,7 +32,7 @@
max_equip = 5
destruction_sleep_duration = 20
-/obj/mecha/combat/gygax/dark/loaded/Initialize()
+/obj/vehicle/sealed/mecha/combat/gygax/dark/loaded/Initialize()
. = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src)
ME.attach(src)
@@ -51,7 +46,7 @@
ME.attach(src)
max_ammo()
-/obj/mecha/combat/gygax/dark/add_cell(obj/item/stock_parts/cell/C=null)
+/obj/vehicle/sealed/mecha/combat/gygax/dark/add_cell(obj/item/stock_parts/cell/C=null)
if(C)
C.forceMove(src)
cell = C
@@ -59,11 +54,6 @@
cell = new /obj/item/stock_parts/cell/bluespace(src)
-/obj/mecha/combat/gygax/GrantActions(mob/living/user, human_occupant = 0)
- ..()
- overload_action.Grant(user, src)
-
-
-/obj/mecha/combat/gygax/RemoveActions(mob/living/user, human_occupant = 0)
- ..()
- overload_action.Remove(user)
+/obj/vehicle/sealed/mecha/combat/gygax/generate_actions()
+ . = ..()
+ initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_overload_mode)
diff --git a/code/game/mecha/combat/honker.dm b/code/modules/vehicles/mecha/combat/honker.dm
similarity index 91%
rename from code/game/mecha/combat/honker.dm
rename to code/modules/vehicles/mecha/combat/honker.dm
index f2fa0e6c569..da96bb2b949 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/modules/vehicles/mecha/combat/honker.dm
@@ -1,22 +1,21 @@
-/obj/mecha/combat/honker
+/obj/vehicle/sealed/mecha/combat/honker
desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. Used to spread the fun and joy of life. HONK!"
name = "\improper H.O.N.K"
icon_state = "honker"
- step_in = 3
+ movedelay = 3
max_integrity = 140
deflect_chance = 60
internal_damage_threshold = 60
armor = list(MELEE = -20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
max_temperature = 25000
- infra_luminosity = 5
operation_req_access = list(ACCESS_THEATRE)
internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_THEATRE)
wreckage = /obj/structure/mecha_wreckage/honker
- add_req_access = 0
+ mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS
max_equip = 3
var/squeak = TRUE
-/obj/mecha/combat/honker/get_stats_part()
+/obj/vehicle/sealed/mecha/combat/honker/get_stats_part(mob/user)
var/integrity = obj_integrity/max_integrity*100
var/cell_charge = get_charge()
var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
@@ -35,12 +34,12 @@
AirHONK temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
HONK temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
- Lights: [lights?"on":"off"]
+ Lights: [(mecha_flags & LIGHTS_ON)?"on":"off"]
[dna_lock?"DNA-locked:
[dna_lock] \[Reset\]
":null]
"}
return output
-/obj/mecha/combat/honker/get_stats_html()
+/obj/vehicle/sealed/mecha/combat/honker/get_stats_html(mob/user)
var/output = {"