Files
Bubberstation/code/modules/vehicles/mecha/mecha_movement.dm
+37 21b4095dfd [MDB IGNORE] [IDB IGNORE] Upstream Sync - 04/17/2026 (#5453)
Upstream 04/17/2026

fixes https://github.com/Bubberstation/Bubberstation/issues/5549

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com>
Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com>
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com>
Co-authored-by: loganuk <fakeemail123@aol.com>
Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com>
Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com>
Co-authored-by: Isratosh <Isratosh@hotmail.com>
Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com>
Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com>
Co-authored-by: Alexander V. <volas@ya.ru>
Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com>
Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Tim <timothymtorres@gmail.com>
Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com>
Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com>
Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com>
Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com>
Co-authored-by: Josh <josh.adam.powell@gmail.com>
Co-authored-by: Josh Powell <josh.powell@softwire.com>
Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com>
Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com>
Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com>
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
2026-05-16 00:56:00 +02:00

194 lines
7.5 KiB
Plaintext

/// Sets the direction of the mecha and all of its occcupents, required for FOV. Alternatively one could make a recursive contents registration and register topmost direction changes in the fov component
/obj/vehicle/sealed/mecha/setDir(newdir)
. = ..()
for(var/mob/living/occupant as anything in occupants)
occupant.setDir(newdir)
///Called when the mech moves
/obj/vehicle/sealed/mecha/proc/on_move()
SIGNAL_HANDLER
collect_ore()
play_stepsound()
///Collects ore when we move, if there is an orebox and it is functional
/obj/vehicle/sealed/mecha/proc/collect_ore()
if(isnull(ore_box) || !HAS_TRAIT(src, TRAIT_OREBOX_FUNCTIONAL))
return
for(var/obj/item/stack/ore/ore in range(1, src))
//we can reach it and it's in front of us? grab it!
if(ore.Adjacent(src) && ((get_dir(src, ore) & dir) || ore.loc == loc))
ore.forceMove(ore_box)
for(var/obj/item/boulder/boulder in range(1, src))
//As above, but for boulders
if(boulder.Adjacent(src) && ((get_dir(src, boulder) & dir) || boulder.loc == loc))
boulder.forceMove(ore_box)
///Plays the mech step sound effect. Split from movement procs so that other mechs (HONK) can override this one specific part.
/obj/vehicle/sealed/mecha/proc/play_stepsound()
if(mecha_flags & QUIET_STEPS)
return
// if we are on the second step of the diagonal movement, don't play step sound
if(src.moving_diagonally == SECOND_DIAG_STEP)
return
playsound(src, stepsound, 40, TRUE)
// Do whatever you do to mobs to these fuckers too
/obj/vehicle/sealed/mecha/Process_Spacemove(movement_dir = 0, continuous_move = FALSE)
. = ..()
if(.)
return TRUE
var/atom/movable/backup = get_spacemove_backup(movement_dir, continuous_move)
if(backup)
if(!istype(backup) || !movement_dir || backup.anchored || continuous_move) //get_spacemove_backup() already checks if a returned turf is solid, so we can just go
return TRUE
last_pushoff = world.time
if(backup.newtonian_move(dir2angle(REVERSE_DIR(movement_dir)), instant = TRUE))
backup.last_pushoff = world.time
step_silent = TRUE
if(return_drivers())
to_chat(occupants, "[icon2html(src, occupants)][span_info("The [src] push off [backup] to propel yourself.")]")
return TRUE
if(active_thrusters?.thrust(movement_dir))
step_silent = TRUE
return TRUE
return FALSE
///Called when the driver turns with the movement lock key
/obj/vehicle/sealed/mecha/proc/on_turn(mob/living/driver, direction)
SIGNAL_HANDLER
return COMSIG_IGNORE_MOVEMENT_LOCK
/obj/vehicle/sealed/mecha/relaymove(mob/living/user, direction)
. = TRUE
if(!canmove || !(user in return_drivers()))
return
if (!vehicle_move(direction))
return
SEND_SIGNAL(user, COMSIG_MOB_DROVE_MECH, src)
/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 FALSE
if(!direction)
return FALSE
if(ismovable(loc)) //Mech is inside an object, tell it we moved
var/atom/loc_atom = loc
return loc_atom.relaymove(src, direction)
var/obj/machinery/portable_atmospherics/canister/internal_tank = get_internal_tank()
if(internal_tank?.connected_port)
if(TIMER_COOLDOWN_FINISHED(src, COOLDOWN_MECHA_MESSAGE))
to_chat(occupants, "[icon2html(src, occupants)][span_warning("Unable to move while connected to the air system port!")]")
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
return FALSE
if(!Process_Spacemove(direction))
return FALSE
if(zoom_mode)
if(TIMER_COOLDOWN_FINISHED(src, COOLDOWN_MECHA_MESSAGE))
to_chat(occupants, "[icon2html(src, occupants)][span_warning("Unable to move while in zoom mode!")]")
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
return FALSE
var/list/missing_parts = list()
if(isnull(cell))
missing_parts += "power cell"
if(isnull(capacitor))
missing_parts += "capacitor"
if(isnull(servo))
missing_parts += "servo"
if(length(missing_parts))
if(TIMER_COOLDOWN_FINISHED(src, COOLDOWN_MECHA_MESSAGE))
to_chat(occupants, "[icon2html(src, occupants)][span_warning("Missing [english_list(missing_parts)].")]")
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
return FALSE
if((step_energy_drain != 0) && !use_energy(step_energy_drain))
if(TIMER_COOLDOWN_FINISHED(src, COOLDOWN_MECHA_MESSAGE))
to_chat(occupants, "[icon2html(src, occupants)][span_warning("Insufficient power to move!")]")
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
return FALSE
if(lavaland_only && is_mining_level(z))
if(TIMER_COOLDOWN_FINISHED(src, COOLDOWN_MECHA_MESSAGE))
to_chat(occupants, "[icon2html(src, occupants)][span_warning("Invalid Environment.")]")
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
return FALSE
var/olddir = dir
if(internal_damage & MECHA_INT_CONTROL_LOST)
direction = pick(GLOB.alldirs)
//only mechs with diagonal movement may move diagonally
if(!allow_diagonal_movement && ISDIAGONALDIR(direction))
return TRUE
var/keyheld = FALSE
if(strafe)
for(var/mob/driver as anything in return_drivers())
if(driver.client?.keys_held["Alt"])
keyheld = TRUE
break
//if we're not facing the way we're going rotate us
// if we're not strafing or if we are forced to rotate or if we are holding down the key
if(dir != direction && (!strafe || forcerotate || keyheld))
setDir(direction)
if(!(mecha_flags & QUIET_TURNS))
playsound(src, turnsound, 40, TRUE)
if(keyheld || !pivot_step) //If we pivot step, we don't return here so we don't just come to a stop
return TRUE
set_glide_size(DELAY_TO_GLIDE_SIZE(movedelay))
//Otherwise just walk normally
. = try_step_multiz(direction)
if(phasing)
use_energy(phasing_energy_drain)
if(strafe)
setDir(olddir)
/obj/vehicle/sealed/mecha/Bump(atom/obstacle)
. = ..()
if(phasing) //Theres only one cause for phasing canpass fails
to_chat(occupants, "[icon2html(src, occupants)][span_warning("A dull, universal force is preventing you from [phasing] here!")]")
spark_system.start()
return
if(.) //mech was thrown/door/whatever
return
// Whether or not we're on our mecha melee cooldown
var/on_cooldown = TIMER_COOLDOWN_RUNNING(src, COOLDOWN_MECHA_MELEE_ATTACK)
if(bumpsmash && !on_cooldown)
// Our pilot for this evening
var/list/mob/mobster = return_drivers()
if(obstacle.mech_melee_attack(src, mobster[1]))
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown * 0.3)
if(!obstacle || obstacle.CanPass(src, get_dir(obstacle, src) || dir)) // The else is in case the obstacle is in the same turf.
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)
//Following procs are camera static update related and are basically ripped off of code\modules\mob\living\silicon\silicon_movement.dm
//We only call a camera static update if we have successfully moved and have a camera installed
/obj/vehicle/sealed/mecha/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
if(!chassis_camera?.can_use())
return
// Delay's a bit faster then standard cameras to "avoid running out of the camera's fov" whatever that means
// An EMPd mecha with a lowered view_range on its camera can still sometimes run out into static before updating, however.
SScameras.camera_moved(chassis_camera, get_turf(old_loc), get_turf(chassis_camera), 0.5 SECONDS)