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 = {" @@ -83,7 +82,7 @@
- [src.get_stats_part()] + [src.get_stats_part(user)]
[src.get_equipment_list()] @@ -97,7 +96,7 @@ "} return output -/obj/mecha/combat/honker/get_commands() +/obj/vehicle/sealed/mecha/combat/honker/get_commands() var/output = {"
Sounds of HONK:
[get_equipment_list()] @@ -52,7 +52,7 @@ "} ///Returns the status of the mech. -/obj/mecha/proc/get_stats_part() +/obj/vehicle/sealed/mecha/proc/get_stats_part(mob/user) var/integrity = obj_integrity/max_integrity*100 var/cell_charge = get_charge() var/datum/gas_mixture/int_tank_air = 0 @@ -74,20 +74,20 @@ Cabin pressure: [internal_tank?"[cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa":"N/A"]
Cabin temperature: [internal_tank?"[return_temperature()]°K|[return_temperature() - T0C]°C":"N/A"]
[dna_lock?"DNA-locked:
[dna_lock] \[Reset\]
":""]
"} - . += "[get_actions()]
" + . += "[get_actions(user)]
" ///Returns HTML for mech actions. Ideally, this proc would be empty for the base mecha. Segmented for easy refactoring. -/obj/mecha/proc/get_actions() +/obj/vehicle/sealed/mecha/proc/get_actions(mob/user) . = "" - . += "[defense_action.owner ? "Defense Mode: [defense_mode ? "Enabled" : "Disabled"]
" : ""]" - . += "[overload_action.owner ? "Leg Actuators Overload: [leg_overload_mode ? "Enabled" : "Disabled"]
" : ""]" - . += "[smoke_action.owner ? "Smoke: [smoke]
" : ""]" - . += "[zoom_action.owner ? "Zoom: [zoom_mode ? "Enabled" : "Disabled"]
" : ""]" - . += "[switch_damtype_action.owner ? "Damtype: [damtype]
" : ""]" - . += "[phasing_action.owner ? "Phase Modulator: [phasing ? "Enabled" : "Disabled"]
" : ""]" + . += "[LAZYACCESSASSOC(occupant_actions, user, /datum/action/vehicle/sealed/mecha/mech_defense_mode) ? "Defense Mode: [defense_mode ? "Enabled" : "Disabled"]
" : ""]" + . += "[LAZYACCESSASSOC(occupant_actions, user, /datum/action/vehicle/sealed/mecha/mech_overload_mode) ? "Leg Actuators Overload: [leg_overload_mode ? "Enabled" : "Disabled"]
" : ""]" + . += "[LAZYACCESSASSOC(occupant_actions, user, /datum/action/vehicle/sealed/mecha/mech_smoke) ? "Smoke Charges remaining: [smoke_charges]
" : ""]" + . += "[LAZYACCESSASSOC(occupant_actions, user, /datum/action/vehicle/sealed/mecha/mech_zoom) ? "Zoom: [zoom_mode ? "Enabled" : "Disabled"]
" : ""]" + . += "[LAZYACCESSASSOC(occupant_actions, user, /datum/action/vehicle/sealed/mecha/mech_switch_damtype) ? "Damtype: [damtype]
" : ""]" + . += "[LAZYACCESSASSOC(occupant_actions, user, /datum/action/vehicle/sealed/mecha/mech_toggle_phasing) ? "Phase Modulator: [phasing ? "Enabled" : "Disabled"]
" : ""]" ///HTML for internal damage. -/obj/mecha/proc/report_internal_damage() +/obj/vehicle/sealed/mecha/proc/report_internal_damage() . = "" var/list/dam_reports = list( "[MECHA_INT_FIRE]" = "INTERNAL FIRE", @@ -105,8 +105,8 @@ . += "DANGEROUSLY HIGH CABIN PRESSURE
" ///HTML for list of equipment. -/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html - if(!equipment.len) +/obj/vehicle/sealed/mecha/proc/get_equipment_list() //outputs mecha equipment list in html + if(!LAZYLEN(equipment)) return . = "Equipment:
" for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) @@ -114,7 +114,7 @@ . += "
" ///HTML for commands. -/obj/mecha/proc/get_commands() +/obj/vehicle/sealed/mecha/proc/get_commands() . = {"
Electronics
@@ -137,8 +137,8 @@
Permissions & Logging
"} -/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu +/obj/vehicle/sealed/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu . = {"
Equipment
"} -/obj/mecha/proc/output_access_dialog(obj/item/card/id/id_card, mob/user) +/obj/vehicle/sealed/mecha/proc/output_access_dialog(obj/item/card/id/id_card, mob/user) if(!id_card || !user) return . = {" @@ -191,7 +190,7 @@ onclose(user, "exosuit_add_access") -/obj/mecha/proc/output_maintenance_dialog(obj/item/card/id/id_card,mob/user) +/obj/vehicle/sealed/mecha/proc/output_maintenance_dialog(obj/item/card/id/id_card,mob/user) if(!id_card || !user) return . = {" @@ -203,8 +202,8 @@ - [add_req_access?"Edit operation keycodes":null] - [maint_access?"[(construction_state > MECHA_LOCKED) ? "Terminate" : "Initiate"] maintenance protocol":null] + [(mecha_flags & ADDING_ACCESS_POSSIBLE)?"Edit operation keycodes":null] + [(mecha_flags & ADDING_MAINT_ACCESS_POSSIBLE)?"[(construction_state > MECHA_LOCKED) ? "Terminate" : "Initiate"] maintenance protocol":null] [(construction_state == MECHA_OPEN_HATCH) ?"--------------------
":null] [(construction_state == MECHA_OPEN_HATCH) ?"[cell?"Drop power cell":"No cell installed
"]":null] [(construction_state == MECHA_OPEN_HATCH) ?"[scanmod?"Drop scanning module":"No scanning module installed
"]":null] @@ -223,7 +222,7 @@ ///// Topic ///// ///////////////// -/obj/mecha/Topic(href, href_list) +/obj/vehicle/sealed/mecha/Topic(href, href_list) ..() if(!usr) @@ -244,13 +243,13 @@ return if(href_list["req_access"]) - if(!add_req_access) + if(!(mecha_flags & ADDING_ACCESS_POSSIBLE)) return output_access_dialog(id_card,usr) return if(href_list["maint_access"]) - if(!maint_access) + if(!(mecha_flags & ADDING_MAINT_ACCESS_POSSIBLE)) return if(construction_state == MECHA_LOCKED) construction_state = MECHA_SECURE_BOLTS @@ -280,14 +279,14 @@ return if(href_list["add_req_access"]) - if(!add_req_access) + if(!(mecha_flags & ADDING_ACCESS_POSSIBLE)) return operation_req_access += text2num(href_list["add_req_access"]) output_access_dialog(id_card,usr) return if(href_list["del_req_access"]) - if(!add_req_access) + if(!(mecha_flags & ADDING_ACCESS_POSSIBLE)) return operation_req_access -= text2num(href_list["del_req_access"]) output_access_dialog(id_card, usr) @@ -296,7 +295,7 @@ //Here ID access stuff goes to die. if(href_list["finish_req_access"]) - add_req_access = 0 + mecha_flags &= ~ADDING_ACCESS_POSSIBLE usr << browse(null,"window=exosuit_add_access") return @@ -310,7 +309,7 @@ return //Start of all internal topic stuff. - if(usr != occupant) + if(!locate(usr) in occupants) return if(href_list["update_content"]) @@ -323,7 +322,7 @@ if(!equip || !equip.selectable) return selected = equip - occupant_message("You switch to [equip].") + to_chat(occupants, "[icon2html(src, occupants)]You switch to [equip].") visible_message("[src] raises [equip].") send_byjax(usr, "exosuit.browser", "eq_list", get_equipment_list()) return @@ -350,53 +349,54 @@ //Changes the exosuit name. if(href_list["change_name"]) var/userinput = stripped_input(usr, "Choose a new exosuit name.", "Rename exosuit", "", MAX_NAME_LEN) - if(!userinput || usr != occupant || usr.incapacitated()) + if(!userinput || !locate(usr) in occupants || usr.incapacitated()) return name = userinput return //Toggles ID upload. if (href_list["toggle_id_upload"]) - add_req_access = !add_req_access - send_byjax(usr,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") + mecha_flags ^= ADDING_ACCESS_POSSIBLE + send_byjax(usr,"exosuit.browser","t_id_upload","[(mecha_flags & ADDING_ACCESS_POSSIBLE)?"L":"Unl"]ock ID upload panel") return //Toggles main access. if(href_list["toggle_maint_access"]) if(construction_state) - occupant_message("Maintenance protocols in effect") + to_chat(occupants, "[icon2html(src, occupants)]Maintenance protocols in effect") return - maint_access = !maint_access - send_byjax(usr,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") + mecha_flags ^= ADDING_MAINT_ACCESS_POSSIBLE + send_byjax(usr,"exosuit.browser","t_maint_access","[(mecha_flags & ADDING_MAINT_ACCESS_POSSIBLE)?"Forbid":"Permit"] maintenance protocols") return //Toggles connection port. if (href_list["toggle_port_connection"]) if(internal_tank.connected_port) if(internal_tank.disconnect()) - occupant_message("Disconnected from the air system port.") + to_chat(occupants, "[icon2html(src, occupants)]Disconnected from the air system port.") log_message("Disconnected from gas port.", LOG_MECHA) else - occupant_message("Unable to disconnect from the air system port!") + to_chat(occupants, "[icon2html(src, occupants)]Unable to disconnect from the air system port!") return else var/obj/machinery/atmospherics/components/unary/portables_connector/possible_port = locate() in loc if(internal_tank.connect(possible_port)) - occupant_message("Connected to the air system port.") + to_chat(occupants, "[icon2html(src, occupants)]Connected to the air system port.") log_message("Connected to gas port.", LOG_MECHA) else - occupant_message("Unable to connect with air system port!") + to_chat(occupants, "[icon2html(src, occupants)]Unable to connect with air system port!") return - send_byjax(occupant,"exosuit.browser","t_port_connection","[internal_tank.connected_port?"Disconnect from":"Connect to"] gas port") + send_byjax(occupants,"exosuit.browser","t_port_connection","[internal_tank.connected_port?"Disconnect from":"Connect to"] gas port") return //Turns on the DNA lock if(href_list["dna_lock"]) - if(!iscarbon(occupant) || !occupant.dna) - occupant_message("You feel a prick as the needle takes your DNA sample.") + var/mob/living/carbon/user = usr + if(!istype(user) || !user.dna) + to_chat(user, "[icon2html(src, occupants)]You can't create a DNA lock with no DNA!.") return - dna_lock = occupant.dna.unique_enzymes - occupant_message("You feel a prick as the needle takes your DNA sample.") + dna_lock = user.dna.unique_enzymes + to_chat(user, "[icon2html(src, occupants)]You feel a prick as the needle takes your DNA sample.") return //Resets the DNA lock @@ -406,16 +406,16 @@ //Repairs internal damage if(href_list["repair_int_control_lost"]) - occupant_message("Recalibrating coordination system...") + to_chat(occupants, "[icon2html(src, occupants)]Recalibrating coordination system...") log_message("Recalibration of coordination system started.", LOG_MECHA) addtimer(CALLBACK(src, .proc/stationary_repair, loc), 100, TIMER_UNIQUE) ///Repairs internal damage if the mech hasn't moved. -/obj/mecha/proc/stationary_repair(location) +/obj/vehicle/sealed/mecha/proc/stationary_repair(location) if(location == loc) clearInternalDamage(MECHA_INT_CONTROL_LOST) - occupant_message("Recalibration successful.") + to_chat(occupants, "[icon2html(src, occupants)]Recalibration successful.") log_message("Recalibration of coordination system finished with 0 errors.", LOG_MECHA) else - occupant_message("Recalibration failed!") + to_chat(occupants, "[icon2html(src, occupants)]Recalibration failed!") log_message("Recalibration of coordination system failed with 1 error.", LOG_MECHA, color="red") diff --git a/code/game/mecha/mecha_wreckage.dm b/code/modules/vehicles/mecha/mecha_wreckage.dm similarity index 100% rename from code/game/mecha/mecha_wreckage.dm rename to code/modules/vehicles/mecha/mecha_wreckage.dm diff --git a/code/game/mecha/medical/odysseus.dm b/code/modules/vehicles/mecha/medical/odysseus.dm similarity index 59% rename from code/game/mecha/medical/odysseus.dm rename to code/modules/vehicles/mecha/medical/odysseus.dm index 27e139c84ab..1991d683af1 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/modules/vehicles/mecha/medical/odysseus.dm @@ -1,29 +1,31 @@ -/obj/mecha/medical/odysseus +/obj/vehicle/sealed/mecha/medical/odysseus desc = "These exosuits are developed and produced by Vey-Med. (© All rights reserved)." name = "\improper Odysseus" icon_state = "odysseus" - step_in = 2 + allow_diagonal_movement = TRUE + movedelay = 2 max_temperature = 15000 max_integrity = 120 wreckage = /obj/structure/mecha_wreckage/odysseus internal_damage_threshold = 35 deflect_chance = 15 step_energy_drain = 6 + internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_MEDICAL) -/obj/mecha/medical/odysseus/moved_inside(mob/living/carbon/human/H) +/obj/vehicle/sealed/mecha/medical/odysseus/moved_inside(mob/living/carbon/human/H) . = ..() if(.) var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] hud.add_hud_to(H) -/obj/mecha/medical/odysseus/go_out() - if(isliving(occupant)) - var/mob/living/L = occupant +/obj/vehicle/sealed/mecha/medical/odysseus/remove_occupant(mob/M) + if(isliving(M)) + var/mob/living/L = M var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] hud.remove_hud_from(L) - ..() + return ..() -/obj/mecha/medical/odysseus/mmi_moved_inside(obj/item/mmi/M, mob/user) +/obj/vehicle/sealed/mecha/medical/odysseus/mmi_moved_inside(obj/item/mmi/M, mob/user) . = ..() if(.) var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] diff --git a/code/game/mecha/working/clarke.dm b/code/modules/vehicles/mecha/working/clarke.dm similarity index 79% rename from code/game/mecha/working/clarke.dm rename to code/modules/vehicles/mecha/working/clarke.dm index 07ae1e62d3e..25e782ca96c 100644 --- a/code/game/mecha/working/clarke.dm +++ b/code/modules/vehicles/mecha/working/clarke.dm @@ -1,11 +1,11 @@ ///Lavaproof, fireproof, fast mech with low armor and higher energy consumption, cannot strafe and has an internal ore box. -/obj/mecha/working/clarke +/obj/vehicle/sealed/mecha/working/clarke desc = "Combining man and machine for a better, stronger engineer. Can even resist lava!" name = "\improper Clarke" icon_state = "clarke" max_temperature = 65000 max_integrity = 200 - step_in = 1.25 + movedelay = 1.25 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF lights_power = 7 deflect_chance = 10 @@ -14,34 +14,34 @@ max_equip = 7 wreckage = /obj/structure/mecha_wreckage/clarke enter_delay = 40 - canstrafe = FALSE + mecha_flags = ADDING_ACCESS_POSSIBLE | IS_ENCLOSED /// Handles an internal ore box for Clarke var/obj/structure/ore_box/box -/obj/mecha/working/clarke/Initialize() +/obj/vehicle/sealed/mecha/working/clarke/Initialize() . = ..() box = new /obj/structure/ore_box(src) var/obj/item/mecha_parts/mecha_equipment/orebox_manager/ME = new(src) ME.attach(src) -/obj/mecha/working/clarke/Destroy() +/obj/vehicle/sealed/mecha/working/clarke/Destroy() box.dump_box_contents() return ..() -/obj/mecha/working/clarke/moved_inside(mob/living/carbon/human/H) +/obj/vehicle/sealed/mecha/working/clarke/moved_inside(mob/living/carbon/human/H) . = ..() if(.) var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_DIAGNOSTIC_ADVANCED] hud.add_hud_to(H) -/obj/mecha/working/clarke/go_out() - if(isliving(occupant)) - var/mob/living/L = occupant +/obj/vehicle/sealed/mecha/working/clarke/remove_occupant(mob/M) + if(isliving(M)) + var/mob/living/L = M var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_DIAGNOSTIC_ADVANCED] hud.remove_hud_from(L) return ..() -/obj/mecha/working/clarke/mmi_moved_inside(obj/item/mmi/M, mob/user) +/obj/vehicle/sealed/mecha/working/clarke/mmi_moved_inside(obj/item/mmi/M, mob/user) . = ..() if(.) var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_DIAGNOSTIC_ADVANCED] @@ -60,11 +60,11 @@ detachable = FALSE salvageable = FALSE /// Var to avoid istype checking every time the topic button is pressed. This will only work inside Clarke mechs. - var/obj/mecha/working/clarke/hostmech + var/obj/vehicle/sealed/mecha/working/clarke/hostmech -/obj/item/mecha_parts/mecha_equipment/orebox_manager/attach(obj/mecha/M) +/obj/item/mecha_parts/mecha_equipment/orebox_manager/attach(obj/vehicle/sealed/mecha/M) . = ..() - if(istype(M, /obj/mecha/working/clarke)) + if(istype(M, /obj/vehicle/sealed/mecha/working/clarke)) hostmech = M /obj/item/mecha_parts/mecha_equipment/orebox_manager/detach() diff --git a/code/game/mecha/working/ripley.dm b/code/modules/vehicles/mecha/working/ripley.dm similarity index 79% rename from code/game/mecha/working/ripley.dm rename to code/modules/vehicles/mecha/working/ripley.dm index 3dc9531adae..3cc13ab6883 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/modules/vehicles/mecha/working/ripley.dm @@ -1,9 +1,9 @@ -/obj/mecha/working/ripley +/obj/vehicle/sealed/mecha/working/ripley desc = "Autonomous Power Loader Unit MK-I. Designed primarily around heavy lifting, the Ripley can be outfitted with utility equipment to fill a number of roles." name = "\improper APLU MK-I \"Ripley\"" icon_state = "ripley" silicon_icon_state = "ripley-empty" - step_in = 1.5 //Move speed, lower is faster. + movedelay = 1.5 //Move speed, lower is faster. /// How fast the mech is in low pressure var/fast_pressure_step_in = 1.5 /// How fast the mech is in normal pressure @@ -26,42 +26,42 @@ /// How much things Ripley can carry in their Cargo Compartment var/cargo_capacity = 15 -/obj/mecha/working/ripley/Move() +/obj/vehicle/sealed/mecha/working/ripley/Move() . = ..() update_pressure() -/obj/mecha/working/ripley/go_out() +/obj/vehicle/sealed/mecha/working/ripley/mob_exit(mob/M, silent, forced) ..() update_icon() -/obj/mecha/working/ripley/moved_inside(mob/living/carbon/human/H) +/obj/vehicle/sealed/mecha/working/ripley/moved_inside(mob/living/carbon/human/H) ..() update_icon() -/obj/mecha/working/ripley/check_for_internal_damage(list/possible_int_damage,ignore_threshold=null) +/obj/vehicle/sealed/mecha/working/ripley/check_for_internal_damage(list/possible_int_damage, ignore_threshold = FALSE) if (!enclosed) possible_int_damage -= (MECHA_INT_TEMP_CONTROL + MECHA_INT_TANK_BREACH) //if we don't even have an air tank, these two doesn't make a ton of sense. . = ..() -/obj/mecha/working/ripley/Initialize() +/obj/vehicle/sealed/mecha/working/ripley/Initialize() . = ..() AddComponent(/datum/component/armor_plate,3,/obj/item/stack/sheet/animalhide/goliath_hide,list(MELEE = 10, BULLET = 5, LASER = 5)) -/obj/mecha/working/ripley/Destroy() +/obj/vehicle/sealed/mecha/working/ripley/Destroy() for(var/atom/movable/A in cargo) A.forceMove(drop_location()) step_rand(A) cargo.Cut() return ..() -/obj/mecha/working/ripley/mkii +/obj/vehicle/sealed/mecha/working/ripley/mkii desc = "Autonomous Power Loader Unit MK-II. This prototype Ripley is refitted with a pressurized cabin, trading its prior speed for atmospheric protection and armor." name = "\improper APLU MK-II \"Ripley\"" icon_state = "ripleymkii" fast_pressure_step_in = 2 //step_in while in low pressure conditions slow_pressure_step_in = 4 //step_in while in normal pressure conditions - step_in = 4 + movedelay = 4 max_temperature = 30000 max_integrity = 250 armor = list(MELEE = 40, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 60, BIO = 0, RAD = 70, FIRE = 100, ACID = 100) @@ -69,47 +69,45 @@ enclosed = TRUE enter_delay = 40 silicon_icon_state = null - opacity = TRUE -/obj/mecha/working/ripley/deathripley +/obj/vehicle/sealed/mecha/working/ripley/deathripley desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE" name = "\improper DEATH-RIPLEY" icon_state = "deathripley" fast_pressure_step_in = 2 //step_in while in low pressure conditions slow_pressure_step_in = 3 //step_in while in normal pressure conditions - step_in = 4 + movedelay = 4 lights_power = 7 wreckage = /obj/structure/mecha_wreckage/ripley/deathripley step_energy_drain = 0 enclosed = TRUE enter_delay = 40 silicon_icon_state = null - opacity = TRUE -/obj/mecha/working/ripley/deathripley/Initialize() +/obj/vehicle/sealed/mecha/working/ripley/deathripley/Initialize() . = ..() var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill ME.attach(src) -/obj/mecha/working/ripley/deathripley/real +/obj/vehicle/sealed/mecha/working/ripley/deathripley/real desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE. FOR REAL" -/obj/mecha/working/ripley/deathripley/real/Initialize() +/obj/vehicle/sealed/mecha/working/ripley/deathripley/real/Initialize() . = ..() for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) E.detach() qdel(E) - equipment.Cut() + LAZYCLEARLIST(equipment) var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill/real ME.attach(src) -/obj/mecha/working/ripley/mining +/obj/vehicle/sealed/mecha/working/ripley/mining desc = "An old, dusty mining Ripley." name = "\improper APLU \"Miner\"" obj_integrity = 75 //Low starting health -/obj/mecha/working/ripley/mining/Initialize() +/obj/vehicle/sealed/mecha/working/ripley/mining/Initialize() . = ..() if(cell) cell.charge = FLOOR(cell.charge * 0.25, 1) //Starts at very low charge @@ -137,24 +135,24 @@ var/obj/item/mecha_parts/mecha_equipment/mining_scanner/scanner = new scanner.attach(src) -/obj/mecha/working/ripley/Exit(atom/movable/O) +/obj/vehicle/sealed/mecha/working/ripley/Exit(atom/movable/O) if(O in cargo) return 0 return ..() -/obj/mecha/working/ripley/Topic(href, href_list) +/obj/vehicle/sealed/mecha/working/ripley/Topic(href, href_list) ..() if(href_list["drop_from_cargo"]) var/obj/O = locate(href_list["drop_from_cargo"]) in cargo if(O) - occupant_message("You unload [O].") + to_chat(occupants, "[icon2html(src, occupants)]You unload [O].") O.forceMove(drop_location()) cargo -= O log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]", LOG_MECHA) return -/obj/mecha/working/ripley/contents_explosion(severity, target) +/obj/vehicle/sealed/mecha/working/ripley/contents_explosion(severity, target) for(var/X in cargo) var/obj/O = X if(prob(30/severity)) @@ -162,7 +160,7 @@ O.forceMove(drop_location()) . = ..() -/obj/mecha/working/ripley/get_stats_part() +/obj/vehicle/sealed/mecha/working/ripley/get_stats_part() var/output = ..() output += "Cargo Compartment Contents:
" if(cargo.len) @@ -173,7 +171,7 @@ output += "
" return output -/obj/mecha/working/ripley/relay_container_resist_act(mob/living/user, obj/O) +/obj/vehicle/sealed/mecha/working/ripley/relay_container_resist_act(mob/living/user, obj/O) to_chat(user, "You lean on the back of [O] and start pushing so it falls out of [src].") if(do_after(user, 300, target = O)) if(!user || user.stat != CONSCIOUS || user.loc != src || O.loc != src ) @@ -184,20 +182,21 @@ else if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. to_chat(user, "You fail to push [O] out of [src]!") + /** * Makes the mecha go faster and halves the mecha drill cooldown if in Lavaland pressure. * * Checks for Lavaland pressure, if that works out the mech's speed is equal to fast_pressure_step_in and the cooldown for the mecha drill is halved. If not it uses slow_pressure_step_in and drill cooldown is normal. */ -/obj/mecha/working/ripley/proc/update_pressure() +/obj/vehicle/sealed/mecha/working/ripley/proc/update_pressure() var/turf/T = get_turf(loc) if(lavaland_equipment_pressure_check(T)) - step_in = fast_pressure_step_in + movedelay = fast_pressure_step_in for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment) drill.equip_cooldown = initial(drill.equip_cooldown) * 0.5 else - step_in = slow_pressure_step_in + movedelay = slow_pressure_step_in for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment) drill.equip_cooldown = initial(drill.equip_cooldown) diff --git a/code/game/mecha/working/working.dm b/code/modules/vehicles/mecha/working/working.dm similarity index 84% rename from code/game/mecha/working/working.dm rename to code/modules/vehicles/mecha/working/working.dm index 51213bd110b..5d6a8537152 100644 --- a/code/game/mecha/working/working.dm +++ b/code/modules/vehicles/mecha/working/working.dm @@ -1,7 +1,7 @@ -/obj/mecha/working +/obj/vehicle/sealed/mecha/working internal_damage_threshold = 60 -/obj/mecha/working/Move() +/obj/vehicle/sealed/mecha/working/Move() . = ..() if(.) collect_ore() @@ -11,7 +11,7 @@ * * Checks for a hydraulic clamp or ore box manager and if it finds an ore box inside them puts ore in the ore box. */ -/obj/mecha/working/proc/collect_ore() +/obj/vehicle/sealed/mecha/working/proc/collect_ore() if((locate(/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) in equipment) || (locate(/obj/item/mecha_parts/mecha_equipment/orebox_manager) in equipment)) var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in contents if(ore_box) diff --git a/code/modules/vehicles/sealed.dm b/code/modules/vehicles/sealed.dm index 6751ddfe358..e3a019427bf 100644 --- a/code/modules/vehicles/sealed.dm +++ b/code/modules/vehicles/sealed.dm @@ -50,10 +50,12 @@ mob_exit(M, silent, randomstep) /obj/vehicle/sealed/proc/mob_exit(mob/M, silent = FALSE, randomstep = FALSE) + SIGNAL_HANDLER if(!istype(M)) return FALSE remove_occupant(M) - M.forceMove(exit_location(M)) + if(!isAI(M))//This is the ONE mob we dont want to be moved to the vehicle that should be handeled when used + M.forceMove(exit_location(M)) if(randomstep) var/turf/target_turf = get_step(exit_location(M), pick(GLOB.cardinals)) M.throw_at(target_turf, 5, 10) diff --git a/code/modules/vehicles/vehicle_actions.dm b/code/modules/vehicles/vehicle_actions.dm index cbb64694286..0e2b9893cfc 100644 --- a/code/modules/vehicles/vehicle_actions.dm +++ b/code/modules/vehicles/vehicle_actions.dm @@ -89,7 +89,7 @@ occupant_actions -= M return TRUE -//ACTION DATUMS +/////////////ACTION DATUMS\\\\\\\\\ /datum/action/vehicle check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS diff --git a/tgstation.dme b/tgstation.dme index e4167adc208..f1561c6376b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -885,37 +885,6 @@ #include "code\game\machinery\telecomms\machines\receiver.dm" #include "code\game\machinery\telecomms\machines\relay.dm" #include "code\game\machinery\telecomms\machines\server.dm" -#include "code\game\mecha\mech_bay.dm" -#include "code\game\mecha\mech_fabricator.dm" -#include "code\game\mecha\mecha.dm" -#include "code\game\mecha\mecha_actions.dm" -#include "code\game\mecha\mecha_construction_paths.dm" -#include "code\game\mecha\mecha_control_console.dm" -#include "code\game\mecha\mecha_defense.dm" -#include "code\game\mecha\mecha_parts.dm" -#include "code\game\mecha\mecha_topic.dm" -#include "code\game\mecha\mecha_wreckage.dm" -#include "code\game\mecha\combat\combat.dm" -#include "code\game\mecha\combat\durand.dm" -#include "code\game\mecha\combat\five_stars.dm" -#include "code\game\mecha\combat\gygax.dm" -#include "code\game\mecha\combat\honker.dm" -#include "code\game\mecha\combat\marauder.dm" -#include "code\game\mecha\combat\phazon.dm" -#include "code\game\mecha\combat\reticence.dm" -#include "code\game\mecha\equipment\mecha_equipment.dm" -#include "code\game\mecha\equipment\tools\medical_tools.dm" -#include "code\game\mecha\equipment\tools\mining_tools.dm" -#include "code\game\mecha\equipment\tools\other_tools.dm" -#include "code\game\mecha\equipment\tools\weapon_bay.dm" -#include "code\game\mecha\equipment\tools\work_tools.dm" -#include "code\game\mecha\equipment\weapons\mecha_ammo.dm" -#include "code\game\mecha\equipment\weapons\weapons.dm" -#include "code\game\mecha\medical\medical.dm" -#include "code\game\mecha\medical\odysseus.dm" -#include "code\game\mecha\working\clarke.dm" -#include "code\game\mecha\working\ripley.dm" -#include "code\game\mecha\working\working.dm" #include "code\game\objects\buckling.dm" #include "code\game\objects\empulse.dm" #include "code\game\objects\items.dm" @@ -3202,6 +3171,36 @@ #include "code\modules\vehicles\wheelchair.dm" #include "code\modules\vehicles\cars\car.dm" #include "code\modules\vehicles\cars\clowncar.dm" +#include "code\modules\vehicles\mecha\_mecha.dm" +#include "code\modules\vehicles\mecha\mech_bay.dm" +#include "code\modules\vehicles\mecha\mech_fabricator.dm" +#include "code\modules\vehicles\mecha\mech_melee_attack.dm" +#include "code\modules\vehicles\mecha\mecha_actions.dm" +#include "code\modules\vehicles\mecha\mecha_construction_paths.dm" +#include "code\modules\vehicles\mecha\mecha_control_console.dm" +#include "code\modules\vehicles\mecha\mecha_defense.dm" +#include "code\modules\vehicles\mecha\mecha_parts.dm" +#include "code\modules\vehicles\mecha\mecha_topic.dm" +#include "code\modules\vehicles\mecha\mecha_wreckage.dm" +#include "code\modules\vehicles\mecha\combat\combat.dm" +#include "code\modules\vehicles\mecha\combat\durand.dm" +#include "code\modules\vehicles\mecha\combat\gygax.dm" +#include "code\modules\vehicles\mecha\combat\honker.dm" +#include "code\modules\vehicles\mecha\combat\marauder.dm" +#include "code\modules\vehicles\mecha\combat\phazon.dm" +#include "code\modules\vehicles\mecha\combat\reticence.dm" +#include "code\modules\vehicles\mecha\equipment\mecha_equipment.dm" +#include "code\modules\vehicles\mecha\equipment\tools\medical_tools.dm" +#include "code\modules\vehicles\mecha\equipment\tools\mining_tools.dm" +#include "code\modules\vehicles\mecha\equipment\tools\other_tools.dm" +#include "code\modules\vehicles\mecha\equipment\tools\weapon_bay.dm" +#include "code\modules\vehicles\mecha\equipment\tools\work_tools.dm" +#include "code\modules\vehicles\mecha\equipment\weapons\mecha_ammo.dm" +#include "code\modules\vehicles\mecha\equipment\weapons\weapons.dm" +#include "code\modules\vehicles\mecha\medical\odysseus.dm" +#include "code\modules\vehicles\mecha\working\clarke.dm" +#include "code\modules\vehicles\mecha\working\ripley.dm" +#include "code\modules\vehicles\mecha\working\working.dm" #include "code\modules\vending\_vending.dm" #include "code\modules\vending\assist.dm" #include "code\modules\vending\autodrobe.dm"