diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index 4dcd2cbdd32..f8abaa7a17e 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -348,8 +348,8 @@
return
var/lootspawn = pickweight(loot)
var/obj/vehicle/V = new lootspawn(get_turf(src))
- if(V.keytype)
- new V.keytype(get_turf(src))
+ if(V.key_type)
+ new V.key_type(get_turf(src))
qdel(src)
diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm
index e5a2c94fa7d..ad936c35bf3 100644
--- a/code/modules/mining/lavaland/loot/tendril_loot.dm
+++ b/code/modules/mining/lavaland/loot/tendril_loot.dm
@@ -163,7 +163,7 @@
desc = "A boat used for traversing lava."
icon_state = "goliath_boat"
icon = 'icons/obj/lavaland/dragonboat.dmi'
- keytype = /obj/item/oar
+ held_key_type = /obj/item/oar
burn_state = LAVA_PROOF
/obj/vehicle/lavaboat/relaymove(mob/user, direction)
@@ -174,7 +174,7 @@
..()
else
to_chat(user, "Boats don't go on land!")
- return 0
+ return FALSE
/obj/item/oar
name = "oar"
@@ -218,7 +218,7 @@
/obj/vehicle/lavaboat/dragon
name = "mysterious boat"
desc = "This boat moves where you will it, without the need for an oar."
- keytype = null
+ held_key_type = null
icon_state = "dragon_boat"
generic_pixel_y = 2
generic_pixel_x = 1
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index f7798df7892..eacbd00ee5d 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -354,19 +354,31 @@
icon_state = "bottle3"
origin_tech = "biotech=5"
-/obj/item/slimepotion/speed/afterattack(obj/item/C, mob/user, proximity_flag)
+/obj/item/slimepotion/speed/afterattack(obj/O, mob/user, proximity_flag)
if(!proximity_flag)
return
..()
- if(!istype(C))
- to_chat(user, "The potion can only be used on items!")
+ if(!istype(O))
+ to_chat(user, "The potion can only be used on items or vehicles!")
return
- if(C.slowdown <= 0)
- to_chat(user, "[C] can't be made any faster!")
- return..()
- to_chat(user, "You slather the red gunk over [C], making it faster.")
- C.color = "#FF0000"
- C.slowdown = 0
+ if(isitem(O))
+ var/obj/item/I = O
+ if(I.slowdown <= 0)
+ to_chat(user, "[I] can't be made any faster!")
+ return ..()
+ I.slowdown = 0
+
+ if(istype(O, /obj/vehicle))
+ var/obj/vehicle/V = O
+ var/vehicle_speed_mod = config.run_speed
+ if(V.vehicle_move_delay <= vehicle_speed_mod)
+ to_chat(user, "[V] can't be made any faster!")
+ return ..()
+ V.vehicle_move_delay = vehicle_speed_mod
+
+ to_chat(user, "You slather the red gunk over [O], making it faster.")
+ O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+ O.add_atom_colour("#FF0000", FIXED_COLOUR_PRIORITY)
qdel(src)
/obj/item/slimepotion/speed/MouseDrop(obj/over_object)
diff --git a/code/modules/vehicle/ambulance.dm b/code/modules/vehicle/ambulance.dm
index 29fb4e0108f..7b4797c6fe3 100644
--- a/code/modules/vehicle/ambulance.dm
+++ b/code/modules/vehicle/ambulance.dm
@@ -2,12 +2,12 @@
name = "ambulance"
desc = "This is what the paramedic uses to run over people they need to take to medbay."
icon_state = "docwagon2"
- keytype = /obj/item/key/ambulance
+ key_type = /obj/item/key/ambulance
var/obj/structure/bed/amb_trolley/bed = null
var/datum/action/ambulance_alarm/AA
var/datum/looping_sound/ambulance_alarm/soundloop
-/obj/vehicle/ambulance/New()
+/obj/vehicle/ambulance/Initialize(mapload)
. = ..()
AA = new(src)
soundloop = new(list(src), FALSE)
diff --git a/code/modules/vehicle/atv.dm b/code/modules/vehicle/atv.dm
index a78791fddea..bd81553dbd7 100644
--- a/code/modules/vehicle/atv.dm
+++ b/code/modules/vehicle/atv.dm
@@ -2,18 +2,16 @@
name = "all-terrain vehicle"
desc = "An all-terrain vehicle built for traversing rough terrain with ease. One of the few old-earth technologies that are still relevant on most planet-bound outposts."
icon = 'icons/vehicles/4wheeler.dmi'
- icon_state = "fourwheel"
- keytype = /obj/item/key
+ icon_state = "atv"
+ key_type = /obj/item/key
generic_pixel_x = 0
generic_pixel_y = 4
vehicle_move_delay = 1
- var/static/image/atvcover = null
+ var/static/mutable_appearance/atvcover
-/obj/vehicle/atv/New()
- ..()
- if(!atvcover)
- atvcover = image("icons/vehicles/4wheeler.dmi", "4wheeler_north")
- atvcover.layer = MOB_LAYER + 0.1
+/obj/vehicle/atv/Initialize(mapload)
+ . = ..()
+ atvcover = mutable_appearance(icon, atvcover, ABOVE_MOB_LAYER)
/obj/vehicle/atv/post_buckle_mob(mob/living/M)
add_overlay(atvcover)
@@ -26,7 +24,7 @@
/obj/vehicle/atv/handle_vehicle_layer()
if(dir == SOUTH)
- layer = MOB_LAYER+0.1
+ layer = ABOVE_MOB_LAYER
else
layer = OBJ_LAYER
@@ -40,20 +38,20 @@
emp_vulnerable = 1
density = 0
-/obj/vehicle/atv/turret/New()
- ..()
+/obj/vehicle/atv/turret/Initialize(mapload)
+ . = ..()
turret = new(loc)
//turret.base = src
/obj/vehicle/atv/turret/handle_vehicle_layer()
if(dir == SOUTH)
- layer = MOB_LAYER+0.1
+ layer = ABOVE_MOB_LAYER
else
layer = OBJ_LAYER
if(turret)
if(dir == NORTH)
- turret.layer = MOB_LAYER+0.1
+ turret.layer = ABOVE_MOB_LAYER
else
turret.layer = OBJ_LAYER
diff --git a/code/modules/vehicle/janicart.dm b/code/modules/vehicle/janicart.dm
index 2445e983fd3..319d2338128 100644
--- a/code/modules/vehicle/janicart.dm
+++ b/code/modules/vehicle/janicart.dm
@@ -3,10 +3,13 @@
name = "janicart (pimpin' ride)"
desc = "A brave janitor cyborg gave its life to produce such an amazing combination of speed and utility."
icon_state = "pussywagon"
- keytype = /obj/item/key/janitor
- var/obj/item/storage/bag/trash/mybag = null
- var/floorbuffer = 0
+ key_type = /obj/item/key/janitor
+ var/obj/item/storage/bag/trash/mybag
+ var/floorbuffer = FALSE
+/obj/vehicle/janicart/Destroy()
+ QDEL_NULL(mybag)
+ return ..()
/obj/vehicle/janicart/handle_vehicle_offsets()
..()
@@ -63,35 +66,34 @@
/obj/vehicle/janicart/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/bag/trash))
- if(keytype == /obj/item/key/janitor)
- if(!user.drop_item())
- return
- to_chat(user, "You hook the trashbag onto \the [name].")
- I.loc = src
- mybag = I
- else if(istype(I, /obj/item/janiupgrade))
- if(keytype == /obj/item/key/janitor)
- floorbuffer = 1
- qdel(I)
- to_chat(user,"You upgrade \the [name] with the floor buffer.")
- update_icon()
-
- ..()
-
+ if(!user.drop_item())
+ return
+ to_chat(user, "You hook [I] onto [src].")
+ I.forceMove(src)
+ mybag = I
+ update_icon()
+ return
+ if(istype(I, /obj/item/janiupgrade))
+ floorbuffer = TRUE
+ qdel(I)
+ to_chat(user,"You upgrade [src] with [I].")
+ update_icon()
+ return
+ return ..()
/obj/vehicle/janicart/update_icon()
- overlays.Cut()
+ cut_overlays()
if(mybag)
- overlays += "cart_garbage"
+ add_overlay("cart_garbage")
if(floorbuffer)
- overlays += "cart_buffer"
+ add_overlay("cart_buffer")
/obj/vehicle/janicart/attack_hand(mob/user)
if(..())
- return 1
+ return TRUE
else if(mybag)
- mybag.loc = get_turf(user)
+ mybag.forceMove(get_turf(user))
user.put_in_hands(mybag)
mybag = null
update_icon()
\ No newline at end of file
diff --git a/code/modules/vehicle/motorcycle.dm b/code/modules/vehicle/motorcycle.dm
index a79f8e3fa12..ea165c1c8df 100644
--- a/code/modules/vehicle/motorcycle.dm
+++ b/code/modules/vehicle/motorcycle.dm
@@ -6,15 +6,11 @@
generic_pixel_x = 0
generic_pixel_y = 4
vehicle_move_delay = 1
- var/static/image/bikecover = null
-
-
-/obj/vehicle/motorcycle/New()
- ..()
- if(!bikecover)
- bikecover = image("icons/vehicles/motorcycle.dmi", "motorcycle_overlay_4d")
- bikecover.layer = MOB_LAYER + 0.1
+ var/mutable_appearance/bikecover
+/obj/vehicle/motorcycle/Initialize(mapload)
+ . = ..()
+ bikecover = mutable_appearance(icon, "motorcycle_overlay_4d", ABOVE_MOB_LAYER)
/obj/vehicle/motorcycle/post_buckle_mob(mob/living/M)
add_overlay(bikecover)
@@ -28,6 +24,6 @@
/obj/vehicle/motorcycle/handle_vehicle_layer()
if(dir == SOUTH)
- layer = MOB_LAYER+0.1
+ layer = ABOVE_MOB_LAYER
else
layer = OBJ_LAYER
\ No newline at end of file
diff --git a/code/modules/vehicle/secway.dm b/code/modules/vehicle/secway.dm
index 4f7c0bf9cb2..85117222247 100644
--- a/code/modules/vehicle/secway.dm
+++ b/code/modules/vehicle/secway.dm
@@ -2,9 +2,10 @@
name = "secway"
desc = "A brave security cyborg gave its life to help you look like a complete tool."
icon_state = "secway"
- keytype = /obj/item/key/security
+ key_type = /obj/item/key/security
generic_pixel_x = 0
generic_pixel_y = 4
+ vehicle_move_delay = 1
/obj/item/key/security
diff --git a/code/modules/vehicle/snowmobile.dm b/code/modules/vehicle/snowmobile.dm
index 311eb48c699..c4b8d7aefba 100644
--- a/code/modules/vehicle/snowmobile.dm
+++ b/code/modules/vehicle/snowmobile.dm
@@ -3,7 +3,7 @@
desc = "Wheeeeeeeeeeee."
icon = 'icons/obj/vehicles.dmi'
icon_state = "snowmobile"
- keytype = /obj/item/key/snowmobile
+ key_type = /obj/item/key/snowmobile
generic_pixel_x = 0
generic_pixel_y = 4
diff --git a/code/modules/vehicle/speedbike.dm b/code/modules/vehicle/speedbike.dm
index e1efe63bcbd..75e25c2c5e6 100644
--- a/code/modules/vehicle/speedbike.dm
+++ b/code/modules/vehicle/speedbike.dm
@@ -3,16 +3,14 @@
icon = 'icons/obj/bike.dmi'
icon_state = "speedbike_blue"
layer = MOB_LAYER - 0.1
- keytype = null
vehicle_move_delay = 0
var/overlay_state = "cover_blue"
- var/image/overlay = null
+ var/mutable_appearance/overlay
-/obj/vehicle/space/speedbike/New()
- ..()
- overlay = image("icons/obj/bike.dmi", overlay_state)
- overlay.layer = MOB_LAYER + 0.1
- overlays += overlay
+/obj/vehicle/space/speedbike/Initialize(mapload)
+ . = ..()
+ overlay = mutable_appearance(icon, overlay_state, ABOVE_MOB_LAYER)
+ add_overlay(overlay)
/obj/vehicle/space/speedbike/Move(newloc,move_dir)
if(has_buckled_mobs())
diff --git a/code/modules/vehicle/sportscar.dm b/code/modules/vehicle/sportscar.dm
index f52f4b77a92..0f9543d4811 100644
--- a/code/modules/vehicle/sportscar.dm
+++ b/code/modules/vehicle/sportscar.dm
@@ -6,14 +6,11 @@
generic_pixel_x = 0
generic_pixel_y = 4
vehicle_move_delay = 1
- var/static/image/carcover = null
+ var/mutable_appearance/carcover
-
-/obj/vehicle/car/New()
- ..()
- if(!carcover)
- carcover = image("icons/vehicles/sportscar.dmi", "sportscar_cover")
- carcover.layer = MOB_LAYER + 0.1
+/obj/vehicle/car/Initialize(mapload)
+ . = ..()
+ carcover = mutable_appearance(icon, "sportscar_cover", ABOVE_MOB_LAYER)
/obj/vehicle/car/post_buckle_mob(mob/living/M)
add_overlay(carcover)
@@ -46,6 +43,6 @@
/obj/vehicle/car/handle_vehicle_layer()
if(dir == SOUTH)
- layer = MOB_LAYER+0.1
+ layer = ABOVE_MOB_LAYER
else
layer = OBJ_LAYER
\ No newline at end of file
diff --git a/code/modules/vehicle/vehicle.dm b/code/modules/vehicle/vehicle.dm
index 9b3a747b7ff..edc6dc63a2e 100644
--- a/code/modules/vehicle/vehicle.dm
+++ b/code/modules/vehicle/vehicle.dm
@@ -9,8 +9,12 @@
can_buckle = TRUE
buckle_lying = FALSE
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0)
- var/keytype = null //item typepath, if non-null an item of this type is needed in your hands to drive this vehicle
- var/next_vehicle_move = 0 //used for move delays
+ var/key_type
+ var/held_key_type //Similar to above, but the vehicle needs the key in hands as opposed to inserted into the ignition
+ var/obj/item/key/inserted_key
+ var/key_type_exact = TRUE //can subtypes work
+ var/last_vehicle_move = 0 //used for move delays
+ var/last_move_diagonal = FALSE
var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
var/auto_door_open = TRUE
var/needs_gravity = 0 //To allow non-space vehicles to move in no gravity or not, mostly for adminbus
@@ -20,10 +24,56 @@
var/spaceworthy = FALSE
-/obj/vehicle/New()
- ..()
+/obj/vehicle/Initialize(mapload)
+ . = ..()
handle_vehicle_layer()
+/obj/vehicle/Destroy()
+ QDEL_NULL(inserted_key)
+ return ..()
+
+/obj/vehicle/examine(mob/user)
+ . = ..()
+ if(key_type)
+ if(!inserted_key)
+ . += "Put a key inside it by clicking it with the key."
+ else
+ . += "Alt-click [src] to remove the key."
+
+/obj/vehicle/attackby(obj/item/I, mob/user, params)
+ if(key_type && !is_key(inserted_key) && is_key(I))
+ if(user.drop_item())
+ I.forceMove(src)
+ to_chat(user, "You insert [I] into [src].")
+ if(inserted_key) //just in case there's an invalid key
+ inserted_key.forceMove(drop_location())
+ inserted_key = I
+ else
+ to_chat(user, "[I] seems to be stuck to your hand!")
+ return
+ return ..()
+
+/obj/vehicle/AltClick(mob/user)
+ if(inserted_key && user.Adjacent(user))
+ if(!(user in buckled_mobs))
+ to_chat(user, "You must be riding [src] to remove [src]'s key!")
+ return
+ to_chat(user, "You remove [inserted_key] from [src].")
+ inserted_key.forceMove(drop_location())
+ user.put_in_hands(inserted_key)
+ inserted_key = null
+ return ..()
+
+/obj/vehicle/proc/is_key(obj/item/I)
+ return I ? (key_type_exact ? (I.type == key_type) : istype(I, key_type)) : FALSE
+
+/obj/vehicle/proc/held_keycheck(mob/user)
+ if(held_key_type)
+ if(istype(user.l_hand, held_key_type) || istype(user.r_hand, held_key_type))
+ return TRUE
+ else
+ return TRUE
+ return FALSE
//APPEARANCE
/obj/vehicle/proc/handle_vehicle_layer()
@@ -49,15 +99,6 @@
return
-//KEYS
-/obj/vehicle/proc/keycheck(mob/user)
- if(keytype)
- if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype))
- return TRUE
- else
- return TRUE
- return FALSE
-
/obj/item/key
name = "key"
desc = "A small grey key."
@@ -93,25 +134,30 @@
//MOVEMENT
/obj/vehicle/relaymove(mob/user, direction)
+ if(key_type && !is_key(inserted_key))
+ to_chat(user, "[src] has no key inserted!")
+ return
+
if(user.incapacitated())
unbuckle_mob(user)
return
- if(world.time < next_vehicle_move)
+ if(world.time < last_vehicle_move + ((last_move_diagonal? 2 : 1) * (vehicle_move_delay + config.human_delay)))
return
- next_vehicle_move = world.time + vehicle_move_delay
- if(keycheck(user))
+ last_vehicle_move = world.time
+
+ if(held_keycheck(user))
+ var/turf/next = get_step(src, direction)
if(!Process_Spacemove(direction) || !isturf(loc))
return
step(src, direction)
- if(has_buckled_mobs())
- for(var/m in buckled_mobs)
- var/mob/living/buckled_mob = m
- if(buckled_mob.loc != loc)
- buckled_mob.buckled = null //Temporary, so Move() succeeds.
- buckled_mob.buckled = src //Restoring
+ if((direction & (direction - 1)) && (loc == next)) //moved diagonally
+ last_move_diagonal = TRUE
+ else
+ last_move_diagonal = FALSE
+ if(has_buckled_mobs())
if(issimulatedturf(loc))
var/turf/simulated/T = loc
if(T.wet == TURF_WET_LUBE) //Lube! Fall off!
@@ -125,20 +171,15 @@
handle_vehicle_layer()
handle_vehicle_offsets()
else
- to_chat(user, "You'll need the keys in one of your hands to drive \the [name].")
+ to_chat(user, "You'll need the keys in one of your hands to drive [src].")
-/obj/vehicle/Move(NewLoc,Dir=0,step_x=0,step_y=0)
+/obj/vehicle/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0)
. = ..()
handle_vehicle_layer()
handle_vehicle_offsets()
-/obj/vehicle/attackby(obj/item/I, mob/user, params)
- if(keytype && istype(I, keytype))
- to_chat(user, "Hold [I] in one of your hands while you drive \the [name].")
-
-
/obj/vehicle/Bump(atom/movable/M)
if(!spaceworthy && isspaceturf(get_turf(src)))
return FALSE
diff --git a/icons/vehicles/4wheeler.dmi b/icons/vehicles/4wheeler.dmi
index 0378b865fd3..e1bfd5e18fd 100644
Binary files a/icons/vehicles/4wheeler.dmi and b/icons/vehicles/4wheeler.dmi differ