diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm
index 67292de6546..1c1eb7f2bb4 100644
--- a/code/datums/supplypacks/robotics.dm
+++ b/code/datums/supplypacks/robotics.dm
@@ -176,4 +176,25 @@
cost = 30
containertype = /obj/structure/closet/crate/secure/science
containername = "Jumper kit crate"
- access = access_robotics
\ No newline at end of file
+ access = access_robotics
+
+/datum/supply_pack/robotics/bike
+ name = "Spacebike Crate"
+ contains = list()
+ cost = 350
+ containertype = /obj/structure/largecrate/vehicle/bike
+ containername = "Spacebike Crate"
+
+/datum/supply_pack/robotics/quadbike
+ name = "ATV Crate"
+ contains = list()
+ cost = 300
+ containertype = /obj/structure/largecrate/vehicle/quadbike
+ containername = "ATV Crate"
+
+/datum/supply_pack/robotics/quadtrailer
+ name = "ATV Trailer Crate"
+ contains = list()
+ cost = 250
+ containertype = /obj/structure/largecrate/vehicle/quadtrailer
+ containername = "ATV Trailer Crate"
diff --git a/code/datums/supplypacks/supply.dm b/code/datums/supplypacks/supply.dm
index 0a40cae6a3a..8397dc8c871 100644
--- a/code/datums/supplypacks/supply.dm
+++ b/code/datums/supplypacks/supply.dm
@@ -124,14 +124,14 @@
/datum/supply_pack/supply/cargotrain
name = "Cargo Train Tug"
- contains = list(/obj/vehicle/train/cargo/engine)
+ contains = list(/obj/vehicle/train/engine)
cost = 35
containertype = /obj/structure/largecrate
containername = "Cargo Train Tug Crate"
/datum/supply_pack/supply/cargotrailer
name = "Cargo Train Trolley"
- contains = list(/obj/vehicle/train/cargo/trolley)
+ contains = list(/obj/vehicle/train/trolley)
cost = 15
containertype = /obj/structure/largecrate
containername = "Cargo Train Trolley Crate"
\ No newline at end of file
diff --git a/code/game/mecha/mech_sensor.dm b/code/game/mecha/mech_sensor.dm
index 5173f182cea..eee1ecefdbf 100644
--- a/code/game/mecha/mech_sensor.dm
+++ b/code/game/mecha/mech_sensor.dm
@@ -45,8 +45,8 @@
var/obj/mecha/R = O
if(R && R.occupant)
R.occupant << block_message
- else if(istype(O, /obj/vehicle/train/cargo/engine))
- var/obj/vehicle/train/cargo/engine/E = O
+ else if(istype(O, /obj/vehicle/train/engine))
+ var/obj/vehicle/train/engine/E = O
if(E && E.load && E.is_train_head())
E.load << block_message
diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm
index d747680baee..2c739985b26 100644
--- a/code/game/objects/structures/crates_lockers/largecrate.dm
+++ b/code/game/objects/structures/crates_lockers/largecrate.dm
@@ -15,6 +15,7 @@
if(I.density || I.anchored || I == src || !I.simulated)
continue
I.forceMove(src)
+ update_icon()
/obj/structure/largecrate/attack_hand(mob/user as mob)
to_chat(user, "You need a crowbar to pry this open!")
@@ -57,6 +58,29 @@
ME.attach(H)
..()
+/obj/structure/largecrate/vehicle
+ name = "vehicle crate"
+ desc = "It comes in a box for the consumer's sake. ..How is this lighter?"
+ icon_state = "vehiclecrate"
+
+/obj/structure/largecrate/vehicle/initialize()
+ ..()
+ spawn(1)
+ for(var/obj/O in contents)
+ O.update_icon()
+
+/obj/structure/largecrate/vehicle/bike
+ name = "spacebike crate"
+ starts_with = list(/obj/structure/vehiclecage/spacebike)
+
+/obj/structure/largecrate/vehicle/quadbike
+ name = "\improper ATV crate"
+ starts_with = list(/obj/structure/vehiclecage/quadbike)
+
+/obj/structure/largecrate/vehicle/quadtrailer
+ name = "\improper ATV trailer crate"
+ starts_with = list(/obj/structure/vehiclecage/quadtrailer)
+
/obj/structure/largecrate/animal
icon_state = "mulecrate"
diff --git a/code/game/objects/structures/crates_lockers/vehiclecage.dm b/code/game/objects/structures/crates_lockers/vehiclecage.dm
new file mode 100644
index 00000000000..9915ca6a7b6
--- /dev/null
+++ b/code/game/objects/structures/crates_lockers/vehiclecage.dm
@@ -0,0 +1,106 @@
+/obj/structure/vehiclecage
+ name = "vehicle cage"
+ desc = "A large metal lattice that seems to exist solely to annoy consumers."
+ icon = 'icons/obj/storage.dmi'
+ icon_state = "vehicle_cage"
+ density = 1
+ var/obj/vehicle/my_vehicle
+ var/my_vehicle_type
+ var/paint_color = "#666666"
+
+/obj/structure/vehiclecage/examine(mob/user)
+ ..()
+ if(my_vehicle)
+ to_chat(user, "It seems to contain \the [my_vehicle].")
+
+/obj/structure/vehiclecage/initialize()
+ . = ..()
+ if(my_vehicle_type)
+ my_vehicle = new my_vehicle_type(src)
+ for(var/obj/I in get_turf(src))
+ if(I.density || I.anchored || I == src || !I.simulated || !istype(I, my_vehicle_type))
+ continue
+ load_vehicle(I)
+ update_icon()
+
+/obj/structure/vehiclecage/attack_hand(mob/user as mob)
+ to_chat(user, "You need a wrench to take this apart!")
+ return
+
+/obj/structure/vehiclecage/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ var/turf/T = get_turf(src)
+ if(!T)
+ to_chat(user, "You can't open this here!")
+ if(W.is_wrench() && do_after(user, 60 * W.toolspeed, src))
+ playsound(loc, W.usesound, 50, 1)
+ disassemble(W, user)
+ user.visible_message("[user] begins loosening \the [src]'s bolts.")
+ if(W.is_wirecutter() && do_after(user, 70 * W.toolspeed, src))
+ playsound(loc, W.usesound, 50, 1)
+ disassemble(W, user)
+ user.visible_message("[user] begins cutting \the [src]'s bolts.")
+ else
+ return attack_hand(user)
+
+/obj/structure/vehiclecage/update_icon()
+ ..()
+ overlays.Cut()
+ underlays.Cut()
+
+ var/image/framepaint = new(icon = 'icons/obj/storage.dmi', icon_state = "[initial(icon_state)]_a", layer = MOB_LAYER + 1.1)
+ framepaint.plane = MOB_PLANE
+ framepaint.color = paint_color
+ overlays += framepaint
+
+ for(var/obj/vehicle/V in src.contents)
+ var/image/showcase = new(V)
+ showcase.layer = src.layer - 0.1
+ underlays += showcase
+
+/obj/structure/vehiclecage/MouseDrop_T(var/atom/movable/C, mob/user as mob)
+ if(user && (user.buckled || user.stat || user.restrained() || !Adjacent(user) || !user.Adjacent(C)))
+ return
+
+ var/obj/vehicle/V
+ if(istype(C, /obj/vehicle))
+ V = C
+ if(!V)
+ return
+
+ if(!my_vehicle)
+ load_vehicle(V, user)
+
+/obj/structure/vehiclecage/proc/load_vehicle(var/obj/vehicle/V, mob/user as mob)
+ if(user)
+ user.visible_message("[user] loads \the [V] into \the [src].", \
+ "You load \the [V] into \the [src].", \
+ "You hear creaking metal.")
+
+ V.forceMove(src)
+
+ paint_color = V.paint_color
+
+ update_icon()
+
+/obj/structure/vehiclecage/proc/disassemble(obj/item/weapon/W as obj, mob/user as mob)
+ var/turf/T = get_turf(src)
+ new /obj/item/stack/material/steel(src.loc, 5)
+
+ for(var/atom/movable/AM in contents)
+ if(AM.simulated)
+ AM.forceMove(T)
+
+ my_vehicle = null
+ user.visible_message("[user] release \the [src].", \
+ "You finally release \the [src].", \
+ "You hear creaking metal.")
+ qdel(src)
+
+/obj/structure/vehiclecage/spacebike
+ my_vehicle_type = /obj/vehicle/bike/random
+
+/obj/structure/vehiclecage/quadbike
+ my_vehicle_type = /obj/vehicle/train/engine/quadbike/random
+
+/obj/structure/vehiclecage/quadtrailer
+ my_vehicle_type = /obj/vehicle/train/trolley/trailer/random
diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm
index 17ae15f7bed..c225af1258a 100644
--- a/code/modules/research/mechfab_designs.dm
+++ b/code/modules/research/mechfab_designs.dm
@@ -564,4 +564,29 @@
build_type = MECHFAB
materials = list(DEFAULT_WALL_MATERIAL = 562, "glass" = 562)
build_path = /obj/item/device/flash/synthetic
- category = "Misc"
\ No newline at end of file
+ category = "Misc"
+
+/*
+ * Non-Mech Vehicles
+ */
+
+/datum/design/item/mechfab/vehicle
+ build_type = MECHFAB
+ category = "Vehicle"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 6)
+
+/datum/design/item/mechfab/vehicle/spacebike_chassis
+ name = "Spacebike Chassis"
+ desc = "A space-bike's un-assembled frame."
+ id = "vehicle_chassis_spacebike"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 6, TECH_BLUESPACE = 3, TECH_PHORON = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 12000, "silver" = 3000, "phoron" = 3000, "osmium" = 1000)
+ build_path = /obj/item/weapon/vehicle_assembly/spacebike
+
+/datum/design/item/mechfab/vehicle/quadbike_chassis
+ name = "Quadbike Chassis"
+ desc = "A space-bike's un-assembled frame."
+ id = "vehicle_chassis_quadbike"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 6, TECH_MAGNET = 3, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 15000, "silver" = 3000, "plastic" = 3000, "osmium" = 1000)
+ build_path = /obj/item/weapon/vehicle_assembly/quadbike
diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm
index f455be67a5b..d761dbd6e8c 100644
--- a/code/modules/vehicles/bike.dm
+++ b/code/modules/vehicles/bike.dm
@@ -1,6 +1,6 @@
-/obj/vehicle/bike/
+/obj/vehicle/bike
name = "space-bike"
- desc = "Space wheelies! Woo! "
+ desc = "Space wheelies! Woo!"
icon = 'icons/obj/bike.dmi'
icon_state = "bike_off"
dir = SOUTH
@@ -10,24 +10,49 @@
health = 100
maxhealth = 100
+ locked = 0
+ powered = 1
+
fire_dam_coeff = 0.6
brute_dam_coeff = 0.5
var/protection_percent = 60
- var/land_speed = 10 //if 0 it can't go on turf
- var/space_speed = 1
+ var/land_speed = 1.5 //if 0 it can't go on turf
+ var/space_speed = 0.5
var/bike_icon = "bike"
+ var/custom_icon = FALSE
+
+ paint_color = "#ffffff"
var/datum/effect/effect/system/ion_trail_follow/ion
var/kickstand = 1
/obj/vehicle/bike/New()
..()
+ cell = new /obj/item/weapon/cell/high(src)
ion = new /datum/effect/effect/system/ion_trail_follow()
ion.set_up(src)
turn_off()
- overlays += image('icons/obj/bike.dmi', "[icon_state]_off_overlay", MOB_LAYER + 1)
icon_state = "[bike_icon]_off"
+ update_icon()
+
+/obj/vehicle/bike/built/New()
+ ..()
+ qdel(cell)
+ cell = null
+
+/obj/vehicle/bike/random/New()
+ paint_color = rgb(rand(1,255),rand(1,255),rand(1,255))
+ ..()
+
+/obj/vehicle/bike/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/device/multitool) && open)
+ var/new_paint = input("Please select paint color.", "Paint Color", paint_color) as color|null
+ if(new_paint)
+ paint_color = new_paint
+ update_icon()
+ return
+ ..()
/obj/vehicle/bike/verb/toggle()
set name = "Toggle Engine"
@@ -36,7 +61,7 @@
if(usr.incapacitated()) return
- if(!on)
+ if(!on && cell && cell.charge > charge_use)
turn_on()
src.visible_message("\The [src] rumbles to life.", "You hear something rumble deeply.")
else
@@ -53,8 +78,8 @@
if(kickstand)
src.visible_message("You put up \the [src]'s kickstand.")
else
- if(istype(src.loc,/turf/space))
- usr << " You don't think kickstands work in space..."
+ if(istype(src.loc,/turf/space) || istype(src.loc, /turf/simulated/floor/water))
+ to_chat(usr, " You don't think kickstands work here...")
return
src.visible_message("You put down \the [src]'s kickstand.")
if(pulledby)
@@ -63,34 +88,45 @@
kickstand = !kickstand
anchored = (kickstand || on)
-/obj/vehicle/bike/load(var/atom/movable/C)
+/obj/vehicle/bike/load(var/atom/movable/C, var/mob/user as mob)
var/mob/living/M = C
if(!istype(C)) return 0
if(M.buckled || M.restrained() || !Adjacent(M) || !M.Adjacent(src))
return 0
- return ..(M)
+ return ..(M, user)
-/obj/vehicle/bike/MouseDrop_T(var/atom/movable/C, mob/user as mob)
- if(!load(C))
- user << " You were unable to load \the [C] onto \the [src]."
+/obj/vehicle/bike/MouseDrop_T(var/atom/movable/C, var/mob/user as mob)
+ if(!load(C, user))
+ to_chat(user, " You were unable to load \the [C] onto \the [src].")
return
/obj/vehicle/bike/attack_hand(var/mob/user as mob)
if(user == load)
- unload(load)
- user << "You unbuckle yourself from \the [src]"
+ unload(load, user)
+ to_chat(user, "You unbuckle yourself from \the [src].")
+ else if(!load && load(user, user))
+ to_chat(user, "You buckle yourself to \the [src].")
/obj/vehicle/bike/relaymove(mob/user, direction)
if(user != load || !on)
- return
- return Move(get_step(src, direction))
+ return 0
+ if(Move(get_step(src, direction)))
+ return 1
+ return 0
/obj/vehicle/bike/Move(var/turf/destination)
- if(kickstand) return
+ if(kickstand) return 0
+ if(on && (!cell || cell.charge < charge_use))
+ turn_off()
+ visible_message("\The [src] whines, before its engines wind down.")
+ return 0
//these things like space, not turf. Dragging shouldn't weigh you down.
- if(istype(destination,/turf/space) || pulledby)
+ if(on && cell)
+ cell.use(charge_use)
+
+ if(istype(destination,/turf/space) || istype(destination, /turf/simulated/floor/water) || pulledby)
if(!space_speed)
return 0
move_delay = space_speed
@@ -109,6 +145,7 @@
if(pulledby)
pulledby.stop_pulling()
..()
+
/obj/vehicle/bike/turn_off()
ion.stop()
anchored = kickstand
@@ -127,12 +164,74 @@
/obj/vehicle/bike/update_icon()
overlays.Cut()
+ if(custom_icon)
+ if(on)
+ var/image/bodypaint = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_on_a", src.layer)
+ bodypaint.color = paint_color
+ overlays += bodypaint
+
+ var/image/overmob = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_on_overlay", MOB_LAYER + 1)
+ var/image/overmob_color = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_on_overlay_a", MOB_LAYER + 1)
+ overmob.plane = MOB_PLANE
+ overmob_color.plane = MOB_PLANE
+ overmob_color.color = paint_color
+ overlays += overmob
+ overlays += overmob_color
+ if(open)
+ icon_state = "[bike_icon]_on-open"
+ else
+ icon_state = "[bike_icon]_on"
+ else
+ var/image/bodypaint = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_off_a", src.layer)
+ bodypaint.color = paint_color
+ overlays += bodypaint
+
+ var/image/overmob = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_off_overlay", MOB_LAYER + 1)
+ var/image/overmob_color = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_off_overlay_a", MOB_LAYER + 1)
+ overmob.plane = MOB_PLANE
+ overmob_color.plane = MOB_PLANE
+ overmob_color.color = paint_color
+ overlays += overmob
+ overlays += overmob_color
+ if(open)
+ icon_state = "[bike_icon]_off-open"
+ else
+ icon_state = "[bike_icon]_off"
+ ..()
+ return
+
if(on)
- overlays += image('icons/obj/bike.dmi', "[bike_icon]_on_overlay", MOB_LAYER + 1)
- icon_state = "[bike_icon]_on"
+ var/image/bodypaint = image('icons/obj/bike.dmi', "[bike_icon]_on_a", src.layer)
+ bodypaint.color = paint_color
+ overlays += bodypaint
+
+ var/image/overmob = image('icons/obj/bike.dmi', "[bike_icon]_on_overlay", MOB_LAYER + 1)
+ var/image/overmob_color = image('icons/obj/bike.dmi', "[bike_icon]_on_overlay_a", MOB_LAYER + 1)
+ overmob.plane = MOB_PLANE
+ overmob_color.plane = MOB_PLANE
+ overmob_color.color = paint_color
+ overlays += overmob
+ overlays += overmob_color
+ if(open)
+ icon_state = "[bike_icon]_on-open"
+ else
+ icon_state = "[bike_icon]_on"
else
- overlays += image('icons/obj/bike.dmi', "[bike_icon]_off_overlay", MOB_LAYER + 1)
- icon_state = "[bike_icon]_off"
+ var/image/bodypaint = image('icons/obj/bike.dmi', "[bike_icon]_off_a", src.layer)
+ bodypaint.color = paint_color
+ overlays += bodypaint
+
+ var/image/overmob = image('icons/obj/bike.dmi', "[bike_icon]_off_overlay", MOB_LAYER + 1)
+ var/image/overmob_color = image('icons/obj/bike.dmi', "[bike_icon]_off_overlay_a", MOB_LAYER + 1)
+ overmob.plane = MOB_PLANE
+ overmob_color.plane = MOB_PLANE
+ overmob_color.color = paint_color
+ overlays += overmob
+ overlays += overmob_color
+ if(open)
+ icon_state = "[bike_icon]_off-open"
+ else
+ icon_state = "[bike_icon]_off"
..()
@@ -140,4 +239,4 @@
/obj/vehicle/bike/Destroy()
qdel(ion)
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm
index e8927197dcb..508ad2a7502 100644
--- a/code/modules/vehicles/cargo_train.dm
+++ b/code/modules/vehicles/cargo_train.dm
@@ -1,4 +1,4 @@
-/obj/vehicle/train/cargo/engine
+/obj/vehicle/train/engine
name = "cargo train tug"
desc = "A ridable electric car designed for pulling cargo trolleys."
icon = 'icons/obj/vehicles.dmi'
@@ -11,9 +11,11 @@
load_offset_x = 0
mob_offset_y = 7
+ var/speed_mod = 1.1
var/car_limit = 3 //how many cars an engine can pull before performance degrades
active_engines = 1
- var/obj/item/weapon/key/cargo_train/key
+ var/obj/item/weapon/key/key
+ var/key_type = /obj/item/weapon/key/cargo_train
/obj/item/weapon/key/cargo_train
name = "key"
@@ -22,7 +24,7 @@
icon_state = "train_keys"
w_class = ITEMSIZE_TINY
-/obj/vehicle/train/cargo/trolley
+/obj/vehicle/train/trolley
name = "cargo train trolley"
icon = 'icons/obj/vehicles.dmi'
icon_state = "cargo_trailer"
@@ -38,15 +40,15 @@
//-------------------------------------------
// Standard procs
//-------------------------------------------
-/obj/vehicle/train/cargo/engine/New()
+/obj/vehicle/train/engine/New()
..()
cell = new /obj/item/weapon/cell/high(src)
- key = new(src)
+ key = new(key_type)
var/image/I = new(icon = 'icons/obj/vehicles.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs
overlays += I
turn_off() //so engine verbs are correctly set
-/obj/vehicle/train/cargo/engine/Move(var/turf/destination)
+/obj/vehicle/train/engine/Move(var/turf/destination)
if(on && cell.charge < charge_use)
turn_off()
update_stats()
@@ -62,23 +64,24 @@
return ..()
-/obj/vehicle/train/cargo/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/vehicle/train/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(open && W.is_wirecutter())
passenger_allowed = !passenger_allowed
user.visible_message("[user] [passenger_allowed ? "cuts" : "mends"] a cable in [src].","You [passenger_allowed ? "cut" : "mend"] the load limiter cable.")
else
..()
-/obj/vehicle/train/cargo/engine/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W, /obj/item/weapon/key/cargo_train))
+/obj/vehicle/train/engine/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, key_type))
if(!key)
user.drop_item()
W.forceMove(src)
key = W
- verbs += /obj/vehicle/train/cargo/engine/verb/remove_key
+ verbs += /obj/vehicle/train/engine/verb/remove_key
return
..()
+/*
//cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead
/obj/vehicle/train/cargo/bullet_act(var/obj/item/projectile/Proj)
if(has_buckled_mobs() && prob(70))
@@ -92,19 +95,20 @@
icon_state = initial(icon_state) + "_open"
else
icon_state = initial(icon_state)
+*/
-/obj/vehicle/train/cargo/trolley/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H)
+/obj/vehicle/train/trolley/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H)
return
-/obj/vehicle/train/cargo/engine/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H)
+/obj/vehicle/train/engine/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H)
..()
update_stats()
-/obj/vehicle/train/cargo/engine/remove_cell(var/mob/living/carbon/human/H)
+/obj/vehicle/train/engine/remove_cell(var/mob/living/carbon/human/H)
..()
update_stats()
-/obj/vehicle/train/cargo/engine/Bump(atom/Obstacle)
+/obj/vehicle/train/engine/Bump(atom/Obstacle)
var/obj/machinery/door/D = Obstacle
var/mob/living/carbon/human/H = load
if(istype(D) && istype(H))
@@ -112,7 +116,7 @@
..()
-/obj/vehicle/train/cargo/trolley/Bump(atom/Obstacle)
+/obj/vehicle/train/trolley/Bump(atom/Obstacle)
if(!lead)
return //so people can't knock others over by pushing a trolley around
..()
@@ -120,44 +124,44 @@
//-------------------------------------------
// Train procs
//-------------------------------------------
-/obj/vehicle/train/cargo/engine/turn_on()
+/obj/vehicle/train/engine/turn_on()
if(!key)
return
else
..()
update_stats()
- verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine
- verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine
+ verbs -= /obj/vehicle/train/engine/verb/stop_engine
+ verbs -= /obj/vehicle/train/engine/verb/start_engine
if(on)
- verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine
+ verbs += /obj/vehicle/train/engine/verb/stop_engine
else
- verbs += /obj/vehicle/train/cargo/engine/verb/start_engine
+ verbs += /obj/vehicle/train/engine/verb/start_engine
-/obj/vehicle/train/cargo/engine/turn_off()
+/obj/vehicle/train/engine/turn_off()
..()
- verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine
- verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine
+ verbs -= /obj/vehicle/train/engine/verb/stop_engine
+ verbs -= /obj/vehicle/train/engine/verb/start_engine
if(!on)
- verbs += /obj/vehicle/train/cargo/engine/verb/start_engine
+ verbs += /obj/vehicle/train/engine/verb/start_engine
else
- verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine
+ verbs += /obj/vehicle/train/engine/verb/stop_engine
-/obj/vehicle/train/cargo/RunOver(var/mob/living/carbon/human/H)
+/obj/vehicle/train/RunOver(var/mob/living/carbon/human/H)
var/list/parts = list(BP_HEAD, BP_TORSO, BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM)
H.apply_effects(5, 5)
for(var/i = 0, i < rand(1,3), i++)
H.apply_damage(rand(1,5), BRUTE, pick(parts))
-/obj/vehicle/train/cargo/trolley/RunOver(var/mob/living/carbon/human/H)
+/obj/vehicle/train/trolley/RunOver(var/mob/living/carbon/human/H)
..()
attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])")
-/obj/vehicle/train/cargo/engine/RunOver(var/mob/living/carbon/human/H)
+/obj/vehicle/train/engine/RunOver(var/mob/living/carbon/human/H)
..()
if(is_train_head() && istype(load, /mob/living/carbon/human))
@@ -173,7 +177,7 @@
//-------------------------------------------
// Interaction procs
//-------------------------------------------
-/obj/vehicle/train/cargo/engine/relaymove(mob/user, direction)
+/obj/vehicle/train/engine/relaymove(mob/user, direction)
if(user != load)
return 0
@@ -186,7 +190,7 @@
else
return ..()
-/obj/vehicle/train/cargo/engine/examine(mob/user)
+/obj/vehicle/train/engine/examine(mob/user)
if(!..(user, 1))
return
@@ -196,7 +200,7 @@
user << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition."
user << "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%"
-/obj/vehicle/train/cargo/engine/verb/start_engine()
+/obj/vehicle/train/engine/verb/start_engine()
set name = "Start engine"
set category = "Vehicle"
set src in view(0)
@@ -217,7 +221,7 @@
else
usr << "[src]'s engine won't start."
-/obj/vehicle/train/cargo/engine/verb/stop_engine()
+/obj/vehicle/train/engine/verb/stop_engine()
set name = "Stop engine"
set category = "Vehicle"
set src in view(0)
@@ -233,7 +237,7 @@
if (!on)
usr << "You stop [src]'s engine."
-/obj/vehicle/train/cargo/engine/verb/remove_key()
+/obj/vehicle/train/engine/verb/remove_key()
set name = "Remove key"
set category = "Vehicle"
set src in view(0)
@@ -252,12 +256,12 @@
usr.put_in_hands(key)
key = null
- verbs -= /obj/vehicle/train/cargo/engine/verb/remove_key
+ verbs -= /obj/vehicle/train/engine/verb/remove_key
//-------------------------------------------
// Loading/unloading procs
//-------------------------------------------
-/obj/vehicle/train/cargo/trolley/load(var/atom/movable/C, var/mob/user)
+/obj/vehicle/train/trolley/load(var/atom/movable/C, var/mob/user)
if(ismob(C) && !passenger_allowed)
return 0
if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !istype(C, /mob/living/carbon/human))
@@ -273,7 +277,7 @@
if(load)
return 1
-/obj/vehicle/train/cargo/engine/load(var/atom/movable/C, var/mob/user)
+/obj/vehicle/train/engine/load(var/atom/movable/C, var/mob/user)
if(!istype(C, /mob/living/carbon/human))
return 0
@@ -283,7 +287,7 @@
//This prevents the object from being interacted with until it has
// been unloaded. A dummy object is loaded instead so the loading
// code knows to handle it correctly.
-/obj/vehicle/train/cargo/trolley/proc/load_object(var/atom/movable/C)
+/obj/vehicle/train/trolley/proc/load_object(var/atom/movable/C)
if(!isturf(C.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly.
return 0
if(load || C.anchored)
@@ -309,7 +313,7 @@
C.pixel_y = initial(C.pixel_y)
C.layer = initial(C.layer)
-/obj/vehicle/train/cargo/trolley/unload(var/mob/user, var/direction)
+/obj/vehicle/train/trolley/unload(var/mob/user, var/direction)
if(istype(load, /datum/vehicle_dummy_load))
var/datum/vehicle_dummy_load/dummy_load = load
load = dummy_load.actual_load
@@ -322,13 +326,13 @@
// Latching/unlatching procs
//-------------------------------------------
-/obj/vehicle/train/cargo/engine/latch(obj/vehicle/train/T, mob/user)
+/obj/vehicle/train/engine/latch(obj/vehicle/train/T, mob/user)
if(!istype(T) || !Adjacent(T))
return 0
//if we are attaching a trolley to an engine we don't care what direction
// it is in and it should probably be attached with the engine in the lead
- if(istype(T, /obj/vehicle/train/cargo/trolley))
+ if(istype(T, /obj/vehicle/train/trolley))
T.attach_to(src, user)
else
var/T_dir = get_dir(src, T) //figure out where T is wrt src
@@ -349,7 +353,7 @@
// more engines increases this limit by car_limit per
// engine.
//-------------------------------------------------------
-/obj/vehicle/train/cargo/engine/update_car(var/train_length, var/active_engines)
+/obj/vehicle/train/engine/update_car(var/train_length, var/active_engines)
src.train_length = train_length
src.active_engines = active_engines
@@ -360,9 +364,9 @@
move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains
move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines)
move_delay += config.run_speed //base reference speed
- move_delay *= 1.1 //makes cargo trains 10% slower than running when not overweight
+ move_delay *= speed_mod //makes cargo trains 10% slower than running when not overweight
-/obj/vehicle/train/cargo/trolley/update_car(var/train_length, var/active_engines)
+/obj/vehicle/train/trolley/update_car(var/train_length, var/active_engines)
src.train_length = train_length
src.active_engines = active_engines
diff --git a/code/modules/vehicles/construction.dm b/code/modules/vehicles/construction.dm
new file mode 100644
index 00000000000..49021d5fd01
--- /dev/null
+++ b/code/modules/vehicles/construction.dm
@@ -0,0 +1,274 @@
+/*
+ * Construction!
+ */
+
+/obj/item/weapon/vehicle_assembly
+ name = "vehicle assembly"
+ desc = "The frame of some vehicle."
+ icon = 'icons/obj/vehicles_64x64.dmi'
+ icon_state = "quad-frame"
+ item_state = "buildpipe"
+
+ density = TRUE
+ slowdown = 10 //It's a vehicle frame, what do you expect?
+ w_class = 5
+ pixel_x = -16
+
+ var/build_stage = 0
+ var/obj/item/weapon/cell/cell = null
+
+/obj/item/weapon/vehicle_assembly/New()
+ ..()
+ icon_state = "[initial(icon_state)][build_stage]"
+ update_icon()
+
+/obj/item/weapon/vehicle_assembly/proc/increase_step(var/new_name = null)
+ build_stage++
+ if(new_name)
+ name = new_name
+ icon_state = "[initial(icon_state)][build_stage]"
+ update_icon()
+ return 1
+
+/*
+ * Quadbike and trailer.
+ */
+
+/obj/item/weapon/vehicle_assembly/quadbike
+ name = "all terrain vehicle assembly"
+ desc = "The frame of an ATV."
+ icon_state = "quad-frame"
+
+/obj/item/weapon/vehicle_assembly/quadbike/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ ..()
+
+ switch(build_stage)
+ if(0)
+ if(istype(W, /obj/item/stack/material/plastic))
+ var/obj/item/stack/material/plastic/P = W
+ if (P.get_amount() < 8)
+ to_chat(user, "You need eight sheets of plastic to add tires to \the [src].")
+ return
+ to_chat(user, "You start to add tires to [src].")
+ if(do_after(user, 40) && build_stage == 0)
+ if(P.use(8))
+ to_chat(user, "You add tires to \the [src].")
+ increase_step("wheeled [initial(name)]")
+ return
+
+ if(1)
+ if(istype(W, /obj/item/weapon/stock_parts/console_screen))
+ user.drop_item()
+ qdel(W)
+ to_chat(user, "You add the lights to \the [src].")
+ increase_step()
+ return
+
+ if(2)
+ if(istype(W, /obj/item/weapon/stock_parts/spring))
+ user.drop_item()
+ qdel(W)
+ to_chat(user, "You add the control system to \the [src].")
+ increase_step()
+ return
+ if(istype(W, /obj/item/stack/material/steel))
+ var/obj/item/stack/material/steel/S = W
+ if(S.get_amount() < 5)
+ to_chat(user, "You need five sheets of steel to convert \the [src] into a trailer.")
+ if(do_after(user, 80) && build_stage == 2)
+ if(S.use(5))
+ var/obj/item/weapon/vehicle_assembly/quadtrailer/Trailer = new(src)
+ Trailer.forceMove(get_turf(src))
+ Trailer.increase_step("framed [initial(Trailer.name)]")
+ to_chat(user, "You convert \the [src] into \the [Trailer].")
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+
+ if(3)
+ if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = W
+ if (C.get_amount() < 2)
+ to_chat(user, "You need two coils of wire to wire [src].")
+ return
+ to_chat(user, "You start to wire [src].")
+ if(do_after(user, 40) && build_stage == 3)
+ if(C.use(2))
+ to_chat(user, "You wire \the [src].")
+ increase_step("wired [initial(name)]")
+ return
+
+ if(4)
+ if(istype(W, /obj/item/weapon/cell))
+ user.drop_item()
+ W.forceMove(src)
+ cell = W
+ to_chat(user, "You add the power supply to \the [src].")
+ increase_step("powered [initial(name)]")
+ return
+
+ if(5)
+ if(istype(W, /obj/item/weapon/stock_parts/motor))
+ user.drop_item()
+ qdel(W)
+ to_chat(user, "You add the motor to \the [src].")
+ increase_step()
+ return
+
+ if(6)
+ if(istype(W, /obj/item/stack/material/plasteel))
+ var/obj/item/stack/material/plasteel/PL = W
+ if (PL.get_amount() < 2)
+ to_chat(user, "You need two sheets of plasteel to add reinforcement to \the [src].")
+ return
+ to_chat(user, "You start to add reinforcement to [src].")
+ if(do_after(user, 40) && build_stage == 6)
+ if(PL.use(2))
+ to_chat(user, "You add reinforcement to \the [src].")
+ increase_step("reinforced [initial(name)]")
+ return
+
+ if(7)
+ if(W.is_wrench() || W.is_screwdriver())
+ playsound(loc, W.usesound, 50, 1)
+ to_chat(user, "You begin your finishing touches on \the [src].")
+ if(do_after(user, 20) && build_stage == 7)
+ playsound(loc, W.usesound, 30, 1)
+ var/obj/vehicle/train/engine/quadbike/built/product = new(src)
+ to_chat(user, "You finish \the [product]")
+ product.loc = get_turf(src)
+ product.cell = cell
+ cell.forceMove(product)
+ cell = null
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+
+/obj/item/weapon/vehicle_assembly/quadtrailer
+ name = "all terrain trailer"
+ desc = "The frame of a small trailer."
+ icon_state = "quadtrailer-frame"
+
+/obj/item/weapon/vehicle_assembly/quadtrailer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ ..()
+
+ switch(build_stage)
+ if(0)
+ if(istype(W, /obj/item/weapon/vehicle_assembly/quadbike))
+ var/obj/item/weapon/vehicle_assembly/quadbike/Q = W
+ if(Q.build_stage > 2)
+ to_chat(user, "\The [Q] is too advanced to be of use with \the [src]")
+ return
+ user.drop_item()
+ qdel(W)
+ increase_step("framed [initial(name)]")
+
+ if(1)
+ if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = W
+ if (C.get_amount() < 2)
+ to_chat(user, "You need two coils of wire to wire [src].")
+ return
+ to_chat(user, "You start to wire [src].")
+ if(do_after(user, 40) && build_stage == 1)
+ if(C.use(2))
+ to_chat(user, "You wire \the [src].")
+ increase_step("wired [initial(name)]")
+ return
+
+ if(2)
+ if(W.is_screwdriver())
+ playsound(loc, W.usesound, 50, 1)
+ to_chat(user, "You close up \the [src].")
+ var/obj/vehicle/train/trolley/trailer/product = new(src)
+ product.loc = get_turf(src)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+
+/*
+ * Space bike.
+ */
+
+/obj/item/weapon/vehicle_assembly/spacebike
+ name = "vehicle assembly"
+ desc = "The frame of some vehicle."
+ icon = 'icons/obj/bike.dmi'
+ icon_state = "bike-frame"
+
+ pixel_x = 0
+
+/obj/item/weapon/vehicle_assembly/spacebike/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ switch(build_stage)
+ if(0)
+ if(istype(W, /obj/item/weapon/tank/jetpack) || istype(W, /obj/item/borg/upgrade/jetpack))
+ user.drop_item()
+ qdel(W)
+ increase_step()
+
+ if(1)
+ if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = W
+ if (C.get_amount() < 2)
+ to_chat(user, "You need two coils of wire to wire [src].")
+ return
+ to_chat(user, "You start to wire [src].")
+ if(do_after(user, 40) && build_stage == 1)
+ if(C.use(2))
+ to_chat(user, "You wire \the [src].")
+ increase_step("wired [initial(name)]")
+ return
+
+ if(2)
+ if(istype(W, /obj/item/stack/material/plastic))
+ var/obj/item/stack/material/plastic/P = W
+ if (P.get_amount() < 3)
+ to_chat(user, "You need three sheets of plastic to add a seat to \the [src].")
+ return
+ to_chat(user, "You start to add a seat to [src].")
+ if(do_after(user, 40) && build_stage == 2)
+ if(P.use(3))
+ to_chat(user, "You add a seat to \the [src].")
+ increase_step("seated [initial(name)]")
+ return
+
+ if(3)
+ if(istype(W, /obj/item/weapon/stock_parts/console_screen))
+ user.drop_item()
+ qdel(W)
+ to_chat(user, "You add the lights to \the [src].")
+ increase_step()
+ return
+
+ if(4)
+ if(istype(W, /obj/item/weapon/stock_parts/spring))
+ user.drop_item()
+ qdel(W)
+ to_chat(user, "You add the control system to \the [src].")
+ increase_step()
+ return
+
+ if(5)
+ if(istype(W, /obj/item/weapon/cell))
+ user.drop_item()
+ W.forceMove(src)
+ cell = W
+ to_chat(user, "You add the power supply to \the [src].")
+ increase_step("powered [initial(name)]")
+ return
+
+ if(6)
+ if(W.is_wrench() || W.is_screwdriver())
+ playsound(loc, W.usesound, 50, 1)
+ to_chat(user, "You begin your finishing touches on \the [src].")
+ if(do_after(user, 20) && build_stage == 6)
+ playsound(loc, W.usesound, 30, 1)
+ var/obj/vehicle/bike/built/product = new(src)
+ to_chat(user, "You finish \the [product]")
+ product.loc = get_turf(src)
+ product.cell = cell
+ cell.forceMove(product)
+ cell = null
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
diff --git a/code/modules/vehicles/quad.dm b/code/modules/vehicles/quad.dm
new file mode 100644
index 00000000000..23a00f6de72
--- /dev/null
+++ b/code/modules/vehicles/quad.dm
@@ -0,0 +1,259 @@
+
+/obj/vehicle/train/engine/quadbike //It's a train engine, so it can tow trailers.
+ name = "electric all terrain vehicle"
+ desc = "A ridable electric ATV designed for all terrain. Except space."
+ icon = 'icons/obj/vehicles_64x64.dmi'
+ icon_state = "quad"
+ on = 0
+ powered = 1
+ locked = 0
+
+ load_item_visible = 1
+ load_offset_x = 0
+ mob_offset_y = 5
+
+ pixel_x = -16
+ speed_mod = 0.45
+ car_limit = 1 //It gets a trailer. That's about it.
+ active_engines = 1
+ key_type = /obj/item/weapon/key/quadbike
+
+ var/frame_state = "quad" //Custom-item proofing!
+ var/custom_frame = FALSE
+
+ paint_color = "#ffffff"
+
+ var/outdoors_speed_mod = 0.7 //The general 'outdoors' speed. I.E., the general difference you'll be at when driving outside.
+
+/obj/vehicle/train/engine/quadbike/New()
+ cell = new /obj/item/weapon/cell/high(src)
+ key = new(key_type)
+ turn_off()
+
+/obj/vehicle/train/engine/quadbike/built/New()
+ key = new(key_type)
+ turn_off()
+
+/obj/vehicle/train/engine/quadbike/random/New()
+ paint_color = rgb(rand(1,255),rand(1,255),rand(1,255))
+ ..()
+
+/obj/item/weapon/key/quadbike
+ name = "key"
+ desc = "A keyring with a small steel key, and a blue fob reading \"ZOOM!\"."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "quad_keys"
+ w_class = ITEMSIZE_TINY
+
+/obj/vehicle/train/engine/quadbike/Move(var/turf/destination)
+ var/turf/T = get_turf(src)
+ ..() //Move it move it, so we can test it test it.
+ if(T != get_turf(src) && !istype(destination, T.type)) //Did we move at all, and are we changing turf types?
+ if(istype(destination, /turf/simulated/floor/water))
+ speed_mod = outdoors_speed_mod * 4 //It kind of floats due to its tires, but it is slow.
+ else if(istype(destination, /turf/simulated/floor/outdoors/rocks))
+ speed_mod = initial(speed_mod) //Rocks are good, rocks are solid.
+ else if(istype(destination, /turf/simulated/floor/outdoors/dirt) || istype(destination, /turf/simulated/floor/outdoors/grass))
+ speed_mod = outdoors_speed_mod //Dirt and grass are the outdoors bench mark.
+ else if(istype(destination, /turf/simulated/floor/outdoors/mud))
+ speed_mod = outdoors_speed_mod * 1.5 //Gets us roughly 1. Mud may be fun, but it's not the best.
+ else if(istype(destination, /turf/simulated/floor/outdoors/snow))
+ speed_mod = outdoors_speed_mod * 1.7 //Roughly a 1.25. Snow is coarse and wet and gets everywhere, especially your electric motors.
+ else
+ speed_mod = initial(speed_mod)
+ update_car(train_length, active_engines)
+ switch(dir) //Due to being a Big Boy sprite, it has to have special pixel shifting to look 'normal' when being driven.
+ if(1)
+ pixel_y = -6
+ if(2)
+ pixel_y = -6
+ if(4)
+ pixel_y = 0
+ if(8)
+ pixel_y = 0
+
+
+/obj/vehicle/train/engine/quadbike/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/device/multitool) && open)
+ var/new_paint = input("Please select paint color.", "Paint Color", paint_color) as color|null
+ if(new_paint)
+ paint_color = new_paint
+ update_icon()
+ return
+ ..()
+
+/obj/vehicle/train/engine/quadbike/update_icon()
+ ..()
+ overlays.Cut()
+ if(custom_frame)
+ var/image/Bodypaint = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_a", layer = src.layer)
+ Bodypaint.color = paint_color
+ overlays += Bodypaint
+
+ var/image/Overmob = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_overlay", layer = src.layer + 0.2) //over mobs
+ var/image/Overmob_color = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_overlay_a", layer = src.layer + 0.2) //over the over mobs, gives the color.
+ Overmob.plane = MOB_PLANE
+ Overmob_color.plane = MOB_PLANE
+ Overmob_color.color = paint_color
+
+ overlays += Overmob
+ overlays += Overmob_color
+ return
+
+ var/image/Bodypaint = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[frame_state]_a", layer = src.layer)
+ Bodypaint.color = paint_color
+ overlays += Bodypaint
+
+ var/image/Overmob = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[frame_state]_overlay", layer = src.layer + 0.2) //over mobs
+ var/image/Overmob_color = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[frame_state]_overlay_a", layer = src.layer + 0.2) //over the over mobs, gives the color.
+ Overmob.plane = MOB_PLANE
+ Overmob_color.plane = MOB_PLANE
+ Overmob_color.color = paint_color
+
+ overlays += Overmob
+ overlays += Overmob_color
+
+/obj/vehicle/train/engine/quadbike/Bump(atom/Obstacle)
+ if(!istype(Obstacle, /atom/movable))
+ return
+ var/atom/movable/A = Obstacle
+
+ if(!A.anchored)
+ var/turf/T = get_step(A, dir)
+ if(isturf(T))
+ A.Move(T) //bump things away when hit
+
+ if(istype(A, /mob/living))
+ var/mob/living/M = A
+ visible_message("[src] knocks over [M]!")
+ M.apply_effects(2, 2) // Knock people down for a short moment
+ M.apply_damages(8 / move_delay) // Smaller amount of damage than a tug, since this will always be possible because Quads don't have safeties.
+ var/list/throw_dirs = list(1, 2, 4, 8, 5, 6, 9, 10)
+ if(!emagged) // By the power of Bumpers TM, it won't throw them ahead of the quad's path unless it's emagged or the person turns.
+ health -= round(M.mob_size / 2)
+ throw_dirs -= dir
+ throw_dirs -= get_dir(M, src) //Don't throw it AT the quad either.
+ else
+ health -= round(M.mob_size / 4) // Less damage if they actually put the point in to emag it.
+ var/turf/T2 = get_step(A, pick(throw_dirs))
+ M.throw_at(T2, 1, 1, src)
+ if(istype(load, /mob/living/carbon/human))
+ var/mob/living/D = load
+ to_chat(D, "You hit [M]!")
+ add_attack_logs(D,M,"Ran over with [src.name]")
+
+
+/obj/vehicle/train/engine/quadbike/RunOver(var/mob/living/carbon/human/H)
+ ..()
+ var/list/throw_dirs = list(1, 2, 4, 8, 5, 6, 9, 10)
+ if(!emagged)
+ throw_dirs -= dir
+ if(tow)
+ throw_dirs -= get_dir(H, tow) //Don't throw it at the trailer either.
+ var/turf/T = get_step(H, pick(throw_dirs))
+ H.throw_at(T, 1, 1, src)
+
+/*
+ * Trailer bits and bobs.
+ */
+
+/obj/vehicle/train/trolley/trailer
+ name = "all terrain trailer"
+ icon = 'icons/obj/vehicles_64x64.dmi'
+ icon_state = "quadtrailer"
+ anchored = 0
+ passenger_allowed = 1
+ buckle_lying = 1
+ locked = 0
+
+ load_item_visible = 1
+ load_offset_x = 0
+ load_offset_y = 13
+ mob_offset_y = 16
+
+ pixel_x = -16
+
+ paint_color = "#ffffff"
+
+/obj/vehicle/train/trolley/trailer/random/New()
+ paint_color = rgb(rand(1,255),rand(1,255),rand(1,255))
+ ..()
+
+/obj/vehicle/train/trolley/trailer/proc/update_load()
+ if(load)
+ var/y_offset = load_offset_y
+ if(istype(load, /mob/living))
+ y_offset = mob_offset_y
+ load.pixel_x = (initial(load.pixel_x) + 16 + load_offset_x + pixel_x) //Base location for the sprite, plus 16 to center it on the 'base' sprite of the trailer, plus the x shift of the trailer, then shift it by the same pixel_x as the trailer to track it.
+ load.pixel_y = (initial(load.pixel_y) + y_offset + pixel_y) //Same as the above.
+ return 1
+ return 0
+
+/obj/vehicle/train/trolley/trailer/New()
+ ..()
+ update_icon()
+
+/obj/vehicle/train/trolley/trailer/Move()
+ ..()
+ if(lead)
+ switch(dir) //Due to being a Big Boy sprite, it has to have special pixel shifting to look 'normal'.
+ if(1)
+ pixel_y = -10
+ pixel_x = -16
+ if(2)
+ pixel_y = 0
+ pixel_x = -16
+ if(4)
+ pixel_y = 0
+ pixel_x = -25
+ if(8)
+ pixel_y = 0
+ pixel_x = -5
+ else
+ pixel_x = initial(pixel_x)
+ pixel_y = initial(pixel_y)
+ update_load()
+
+/obj/vehicle/train/trolley/trailer/Bump(atom/Obstacle)
+ if(!istype(Obstacle, /atom/movable))
+ return
+ var/atom/movable/A = Obstacle
+
+ if(!A.anchored)
+ var/turf/T = get_step(A, dir)
+ if(isturf(T))
+ A.Move(T) //bump things away when hit
+
+ if(istype(A, /mob/living))
+ var/mob/living/M = A
+ visible_message("[src] knocks over [M]!")
+ M.apply_effects(1, 1)
+ M.apply_damages(8 / move_delay)
+ if(load)
+ M.apply_damages(4/move_delay)
+ var/list/throw_dirs = list(1, 2, 4, 8, 5, 6, 9, 10)
+ if(!emagged)
+ throw_dirs -= dir
+ var/turf/T2 = get_step(A, pick(throw_dirs))
+ M.throw_at(T2, 1, 1, src)
+ if(istype(load, /mob/living/carbon/human))
+ var/mob/living/D = load
+ to_chat(D, "You hit [M]!")
+ add_attack_logs(D,M,"Ran over with [src.name]")
+
+/obj/vehicle/train/trolley/trailer/update_icon()
+ ..()
+ overlays.Cut()
+
+ var/image/Bodypaint = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[initial(icon_state)]_a", layer = src.layer)
+ Bodypaint.color = paint_color
+ overlays += Bodypaint
+
+/obj/vehicle/train/trolley/trailer/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/device/multitool) && open)
+ var/new_paint = input("Please select paint color.", "Paint Color", paint_color) as color|null
+ if(new_paint)
+ paint_color = new_paint
+ update_icon()
+ return
+ ..()
diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm
index 42f97676adf..6db4400f819 100644
--- a/code/modules/vehicles/train.dm
+++ b/code/modules/vehicles/train.dm
@@ -17,6 +17,7 @@
var/obj/vehicle/train/lead
var/obj/vehicle/train/tow
+ var/open_top = TRUE
//-------------------------------------------
// Standard procs
@@ -58,6 +59,19 @@
D << "You hit [M]!"
add_attack_logs(D,M,"Ran over with [src.name]")
+//trains are commonly open topped, so there is a chance the projectile will hit the mob riding the train instead
+/obj/vehicle/train/bullet_act(var/obj/item/projectile/Proj)
+ if(has_buckled_mobs() && prob(70))
+ var/mob/living/L = pick(buckled_mobs)
+ L.bullet_act(Proj)
+ return
+ ..()
+
+/obj/vehicle/train/update_icon()
+ if(open)
+ icon_state = initial(icon_state) + "_open"
+ else
+ icon_state = initial(icon_state)
//-------------------------------------------
// Vehicle procs
diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm
index 2109d42f44b..f3ea8fc91cd 100644
--- a/code/modules/vehicles/vehicle.dm
+++ b/code/modules/vehicles/vehicle.dm
@@ -34,6 +34,8 @@
var/obj/item/weapon/cell/cell
var/charge_use = 5 //set this to adjust the amount of power the vehicle uses per move
+ var/paint_color = "#666666" //For vehicles with special paint overlays.
+
var/atom/movable/load //all vehicles can take a load, since they should all be a least drivable
var/load_item_visible = 1 //set if the loaded item should be overlayed on the vehicle sprite
var/load_offset_x = 0 //pixel_x offset for item overlay
diff --git a/html/changelogs/Mechoid - Vehicles.yml b/html/changelogs/Mechoid - Vehicles.yml
new file mode 100644
index 00000000000..94b8e280e95
--- /dev/null
+++ b/html/changelogs/Mechoid - Vehicles.yml
@@ -0,0 +1,36 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: Mechoid
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Adds two vehicles to Robotics and Cargo, the Quad and Spacebike."
diff --git a/icons/obj/bike.dmi b/icons/obj/bike.dmi
index 69aa0ccb4ef..aecc6aa2e97 100644
Binary files a/icons/obj/bike.dmi and b/icons/obj/bike.dmi differ
diff --git a/icons/obj/custom_items_vehicle.dmi b/icons/obj/custom_items_vehicle.dmi
new file mode 100644
index 00000000000..a6afb68bab5
Binary files /dev/null and b/icons/obj/custom_items_vehicle.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index 91658df513f..e4124040754 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi
index 85e245ce9fe..6379879df75 100644
Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ
diff --git a/icons/obj/vehicles_64x64.dmi b/icons/obj/vehicles_64x64.dmi
new file mode 100644
index 00000000000..98ed024d68e
Binary files /dev/null and b/icons/obj/vehicles_64x64.dmi differ
diff --git a/maps/northern_star/polaris-1.dmm b/maps/northern_star/polaris-1.dmm
index 47dda061475..1021cbbcaa2 100644
--- a/maps/northern_star/polaris-1.dmm
+++ b/maps/northern_star/polaris-1.dmm
@@ -6990,7 +6990,7 @@
"cEv" = (/obj/effect/floor_decal/industrial/warning{dir = 9},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cEw" = (/obj/effect/floor_decal/industrial/warning/corner{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cEx" = (/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/quartermaster/storage)
-"cEy" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/cargo/engine,/obj/machinery/light{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/storage)
+"cEy" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/engine,/obj/machinery/light{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cEz" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/obj/structure/grille,/obj/machinery/door/firedoor/border_only,/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area/quartermaster/qm)
"cEA" = (/obj/structure/closet,/obj/item/weapon/storage/backpack/dufflebag,/turf/simulated/floor/tiled,/area/quartermaster/qm)
"cEB" = (/obj/structure/closet/secure_closet/quartermaster,/turf/simulated/floor/tiled,/area/quartermaster/qm)
@@ -7052,7 +7052,7 @@
"cFF" = (/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/structure/grille,/obj/machinery/door/firedoor/border_only,/turf/simulated/floor/plating,/area/quartermaster/storage)
"cFG" = (/obj/machinery/embedded_controller/radio/simple_docking_controller{frequency = 1380; id_tag = "cargo_bay"; name = "cargo bay hatch controller"; pixel_x = -30; pixel_y = 0; req_one_access = list(13,31); tag_door = "cargo_bay_door"},/obj/effect/floor_decal/industrial/warning{dir = 8},/obj/machinery/camera/network/cargo{c_tag = "CRG - Cargo Bay Port"; dir = 4; name = "security camera"},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cFH" = (/obj/machinery/hologram/holopad,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled,/area/quartermaster/storage)
-"cFI" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/cargo/trolley,/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/turf/simulated/floor/tiled,/area/quartermaster/storage)
+"cFI" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/trolley,/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cFJ" = (/obj/machinery/light/small,/turf/simulated/floor,/area/maintenance/apmaint)
"cFK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/maintenance/apmaint)
"cFL" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/machinery/space_heater,/turf/simulated/floor,/area/maintenance/apmaint)
@@ -7103,7 +7103,7 @@
"cGE" = (/obj/machinery/atmospherics/unary/vent_pump/on,/turf/simulated/floor/wood,/area/crew_quarters/sleep/vistor_room_10)
"cGF" = (/obj/machinery/newscaster{pixel_x = 32; pixel_y = 0},/turf/simulated/floor/wood,/area/crew_quarters/sleep/vistor_room_10)
"cGG" = (/obj/effect/floor_decal/industrial/warning{dir = 10},/turf/simulated/floor/tiled,/area/quartermaster/storage)
-"cGH" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/cargo/trolley,/obj/machinery/camera/network/cargo{c_tag = "CRG - Cargo Bay Starboard"; dir = 8; name = "security camera"},/turf/simulated/floor/tiled,/area/quartermaster/storage)
+"cGH" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/trolley,/obj/machinery/camera/network/cargo{c_tag = "CRG - Cargo Bay Starboard"; dir = 8; name = "security camera"},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cGI" = (/turf/simulated/wall,/area/quartermaster/warehouse)
"cGJ" = (/obj/structure/table/rack{dir = 8; layer = 2.9},/obj/effect/decal/cleanable/cobweb,/obj/effect/floor_decal/corner/brown/full{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/warehouse)
"cGK" = (/obj/structure/table/rack{dir = 8; layer = 2.9},/obj/item/weapon/module/power_control,/obj/item/weapon/cell{maxcharge = 2000},/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse)
@@ -7206,7 +7206,7 @@
"cID" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cIE" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cIF" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/storage)
-"cIG" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/cargo/trolley,/obj/machinery/light{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/storage)
+"cIG" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/trolley,/obj/machinery/light{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/storage)
"cIH" = (/obj/machinery/camera/network/cargo{c_tag = "CRG - Cargo Warehouse"; dir = 4; name = "security camera"},/turf/simulated/floor/tiled,/area/quartermaster/warehouse)
"cII" = (/obj/effect/landmark{name = "blobstart"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse)
"cIJ" = (/obj/machinery/atmospherics/unary/vent_pump/on,/turf/simulated/floor/tiled,/area/quartermaster/warehouse)
diff --git a/maps/northern_star/polaris-2.dmm b/maps/northern_star/polaris-2.dmm
index a2c9a941bd8..cbdb8d3e615 100644
--- a/maps/northern_star/polaris-2.dmm
+++ b/maps/northern_star/polaris-2.dmm
@@ -379,7 +379,7 @@
"ho" = (/obj/structure/table/steel_reinforced,/obj/random/tool,/obj/random/tool,/obj/random/tool,/obj/random/tool,/obj/random/tool,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hp" = (/obj/structure/table/steel_reinforced,/obj/random/toolbox,/obj/random/toolbox,/obj/random/toolbox,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hq" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/turf/simulated/shuttle/plating,/area/shuttle/trade/centcom)
-"hr" = (/obj/vehicle/train/cargo/engine,/obj/machinery/light{dir = 8; icon_state = "tube1"; pixel_y = 0},/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
+"hr" = (/obj/vehicle/train/engine,/obj/machinery/light{dir = 8; icon_state = "tube1"; pixel_y = 0},/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hs" = (/turf/simulated/shuttle/floor/darkred,/area/shuttle/trade/centcom)
"ht" = (/obj/machinery/door/airlock/glass_medical{name = "Medical Bay"; req_access = list(160)},/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hu" = (/obj/machinery/optable,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
@@ -395,7 +395,7 @@
"hE" = (/obj/effect/floor_decal/industrial/warning{dir = 5},/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hF" = (/obj/structure/table/steel_reinforced,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/item/weapon/weldpack,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hG" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/turf/simulated/shuttle/plating,/area/shuttle/trade/centcom)
-"hH" = (/obj/vehicle/train/cargo/trolley,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
+"hH" = (/obj/vehicle/train/trolley,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hI" = (/obj/machinery/light,/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hJ" = (/obj/machinery/vending/medical{pixel_y = -32; req_access = null},/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
"hK" = (/obj/machinery/door/airlock/multi_tile/glass{dir = 4; req_access = list(160)},/turf/simulated/shuttle/floor/black,/area/shuttle/trade/centcom)
diff --git a/maps/southern_cross/southern_cross-1.dmm b/maps/southern_cross/southern_cross-1.dmm
index 25c36307040..3f4beeb5ed5 100644
--- a/maps/southern_cross/southern_cross-1.dmm
+++ b/maps/southern_cross/southern_cross-1.dmm
@@ -7375,8 +7375,8 @@
"cLQ" = (/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/machinery/light_switch{pixel_x = 36; pixel_y = 0},/obj/structure/cable/green,/obj/effect/floor_decal/borderfloor/corner,/obj/effect/floor_decal/corner/brown/bordercorner,/turf/simulated/floor/tiled,/area/quartermaster/warehouse)
"cLR" = (/obj/structure/bed/chair/comfy/brown,/obj/effect/landmark/start{name = "Cargo Technician"},/obj/effect/floor_decal/borderfloor/corner{dir = 8},/obj/effect/floor_decal/corner/brown/bordercorner{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/office)
"cLS" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/office)
-"cLT" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/cargo/engine{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled,/area/quartermaster/office)
-"cLU" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/cargo/trolley{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/office)
+"cLT" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/engine{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled,/area/quartermaster/office)
+"cLU" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/vehicle/train/trolley{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/office)
"cLV" = (/obj/structure/cable/green,/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/machinery/light_switch{pixel_x = 36; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/brown/border{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/office)
"cLW" = (/turf/unsimulated/mask,/area/quartermaster/office)
"cLX" = (/turf/simulated/wall/r_wall,/area/maintenance/substation/cargo)
diff --git a/maps/southern_cross/southern_cross-4.dmm b/maps/southern_cross/southern_cross-4.dmm
index 4688297ec47..19928e3a458 100644
--- a/maps/southern_cross/southern_cross-4.dmm
+++ b/maps/southern_cross/southern_cross-4.dmm
@@ -430,8 +430,8 @@
"iq" = (/obj/effect/floor_decal/industrial/warning/dust{ icon_state = "warning_dust"; dir = 4},/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
"ir" = (/obj/machinery/mining/brace,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
"is" = (/obj/machinery/mining/drill,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
-"it" = (/obj/vehicle/train/cargo/engine,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
-"iu" = (/obj/vehicle/train/cargo/trolley,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
+"it" = (/obj/vehicle/train/engine,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
+"iu" = (/obj/vehicle/train/trolley,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
"iv" = (/obj/effect/floor_decal/industrial/warning/dust{ icon_state = "warning_dust"; dir = 8},/obj/machinery/light/small,/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
"iw" = (/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/obj/structure/cable/heavyduty{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
"ix" = (/obj/structure/cable/heavyduty{icon_state = "4-8"},/turf/simulated/floor/tiled/asteroid_steel,/area/surface/outpost/mining_main/cave)
diff --git a/maps/southern_cross/southern_cross-6.dmm b/maps/southern_cross/southern_cross-6.dmm
index 793f2966adf..92b664c4b7c 100644
--- a/maps/southern_cross/southern_cross-6.dmm
+++ b/maps/southern_cross/southern_cross-6.dmm
@@ -1176,7 +1176,7 @@
"wF" = (/obj/structure/table/steel_reinforced,/obj/random/tool,/obj/random/tool,/obj/random/tool,/obj/random/tool,/obj/random/tool,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wG" = (/obj/structure/table/steel_reinforced,/obj/random/toolbox,/obj/random/toolbox,/obj/random/toolbox,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wH" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/turf/simulated/shuttle/plating,/area/shuttle/merchant/home)
-"wI" = (/obj/vehicle/train/cargo/engine,/obj/machinery/light{dir = 8; icon_state = "tube1"; pixel_y = 0},/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
+"wI" = (/obj/vehicle/train/engine,/obj/machinery/light{dir = 8; icon_state = "tube1"; pixel_y = 0},/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wJ" = (/turf/simulated/shuttle/floor/darkred,/area/shuttle/merchant/home)
"wK" = (/obj/machinery/door/airlock/glass_medical{name = "Medical Bay"; req_access = list(160)},/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wL" = (/obj/machinery/optable,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
@@ -1190,7 +1190,7 @@
"wT" = (/obj/effect/floor_decal/industrial/warning{dir = 5},/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wU" = (/obj/structure/table/steel_reinforced,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/item/weapon/weldpack,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wV" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/turf/simulated/shuttle/plating,/area/shuttle/merchant/home)
-"wW" = (/obj/vehicle/train/cargo/trolley,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
+"wW" = (/obj/vehicle/train/trolley,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wX" = (/obj/machinery/light,/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wY" = (/obj/machinery/vending/medical{pixel_y = -32; req_access = null},/turf/simulated/shuttle/floor/black,/area/shuttle/merchant/home)
"wZ" = (/obj/machinery/door/airlock/glass_security{name = "Security Processing"; req_access = list(1)},/turf/unsimulated/floor{icon_state = "dark"},/area/centcom/security)
diff --git a/maps/submaps/surface_submaps/plains/Field1.dmm b/maps/submaps/surface_submaps/plains/Field1.dmm
index fdc4357179b..9dcafe04001 100644
--- a/maps/submaps/surface_submaps/plains/Field1.dmm
+++ b/maps/submaps/surface_submaps/plains/Field1.dmm
@@ -4,8 +4,8 @@
"d" = (/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
"e" = (/obj/structure/ore_box,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
"f" = (/obj/item/device/radio,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
-"g" = (/obj/vehicle/train/cargo/trolley,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
-"h" = (/obj/vehicle/train/cargo/engine,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
+"g" = (/obj/vehicle/train/trolley,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
+"h" = (/obj/vehicle/train/engine,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
"i" = (/obj/item/device/flashlight,/turf/simulated/floor/outdoors/dirt,/area/submap/Field1)
(1,1,1) = {"
diff --git a/maps/submaps/surface_submaps/plains/Thiefc.dmm b/maps/submaps/surface_submaps/plains/Thiefc.dmm
index 9e7a5e0069b..57a27da7c56 100644
--- a/maps/submaps/surface_submaps/plains/Thiefc.dmm
+++ b/maps/submaps/surface_submaps/plains/Thiefc.dmm
@@ -8,10 +8,10 @@
"h" = (/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
"i" = (/obj/structure/closet/crate,/obj/item/weapon/lipstick,/obj/item/weapon/lipstick/black,/obj/item/weapon/lipstick/random,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
"j" = (/obj/structure/table/steel,/obj/item/weapon/beartrap,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
-"k" = (/obj/vehicle/train/cargo/trolley,/obj/random/firstaid,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
+"k" = (/obj/vehicle/train/trolley,/obj/random/firstaid,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
"l" = (/obj/structure/closet/crate,/obj/item/weapon/folder/blue,/obj/item/weapon/folder/red,/obj/item/weapon/folder/white,/obj/item/weapon/folder/yellow,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
"m" = (/obj/structure/table/steel,/obj/item/weapon/paper{desc = "This is some bullshit. First chance we got to knick something that looks half decent turns out to be mostly junk. And now we're getting calls that the other stash we've got has got a spider problem. Fuck this, Between the shitty weather, The pissed of bugs, And now apparently some NT goon running around in the area there's hardly enough reason to stick around. I'm telling Carl I'm out tommorow."; name = "Note"},/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
-"n" = (/obj/vehicle/train/cargo/trolley,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
+"n" = (/obj/vehicle/train/trolley,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
"o" = (/obj/structure/closet/crate,/obj/item/weapon/cell/device/weapon,/obj/item/weapon/cell/device/weapon,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
"p" = (/obj/structure/closet/crate,/obj/item/weapon/storage/box/shotgunammo,/obj/item/weapon/storage/box/practiceshells,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Thiefc)
diff --git a/polaris.dme b/polaris.dme
index 5962661c843..60b06190e03 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -1103,6 +1103,7 @@
#include "code\game\objects\structures\crates_lockers\closets.dm"
#include "code\game\objects\structures\crates_lockers\crates.dm"
#include "code\game\objects\structures\crates_lockers\largecrate.dm"
+#include "code\game\objects\structures\crates_lockers\vehiclecage.dm"
#include "code\game\objects\structures\crates_lockers\closets\coffin.dm"
#include "code\game\objects\structures\crates_lockers\closets\crittercrate.dm"
#include "code\game\objects\structures\crates_lockers\closets\fireaxe.dm"
@@ -2396,8 +2397,11 @@
#include "code\modules\turbolift\turbolift_map.dm"
#include "code\modules\turbolift\turbolift_process.dm"
#include "code\modules\turbolift\turbolift_turfs.dm"
+#include "code\modules\vehicles\bike.dm"
#include "code\modules\vehicles\boat.dm"
#include "code\modules\vehicles\cargo_train.dm"
+#include "code\modules\vehicles\construction.dm"
+#include "code\modules\vehicles\quad.dm"
#include "code\modules\vehicles\train.dm"
#include "code\modules\vehicles\vehicle.dm"
#include "code\modules\ventcrawl\ventcrawl.dm"