From 4b5cc8d85d52f65f88c5d3d375f369be6149fa8f Mon Sep 17 00:00:00 2001 From: DreamySkrell <107256943+DreamySkrell@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:40:48 +0100 Subject: [PATCH] Bike keys and registration plates (#18457) * 2w346 * 5yeh * qdel * Update code/modules/vehicles/bike.dm Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com> Signed-off-by: DreamySkrell <107256943+DreamySkrell@users.noreply.github.com> * l * y --------- Signed-off-by: DreamySkrell <107256943+DreamySkrell@users.noreply.github.com> Co-authored-by: DreamySkrell <> Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com> --- code/modules/lock/key.dm | 33 +++++++ code/modules/vehicles/bike.dm | 99 ++++++++++++++++++--- html/changelogs/DreamySkrell-bike-keys.yml | 7 ++ icons/obj/items.dmi | Bin 6047 -> 6795 bytes 4 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 html/changelogs/DreamySkrell-bike-keys.yml diff --git a/code/modules/lock/key.dm b/code/modules/lock/key.dm index dc995534396..d0360ce6239 100644 --- a/code/modules/lock/key.dm +++ b/code/modules/lock/key.dm @@ -28,3 +28,36 @@ to_chat(user, "\The [src] crumbles in your hands!") qdel(src) return ..() + +/obj/item/key/bike + name = "bike key" + desc = "Used to start a bike." + icon_state = "key_tag_gray" + +/obj/item/key/bike/get_examine_text(mob/user, distance, is_adjacent, infix, suffix) + . = ..() + if(distance <= 1) + . += "\The [src] has a small tag attached to it, written on it is '[key_data]'." + +/obj/item/key/bike/sport + name = "sports bike key" + desc = "Used to start a sporty, fast bike." + icon_state = "key_tag_red" + +/obj/item/key/bike/sport/Initialize(mapload, ...) + . = ..() + icon_state = pick("key_tag_red", "key_tag_blue") + +/obj/item/key/bike/moped + name = "moped key" + desc = "Used to start a cheap moped bike." + icon_state = "key_tag_green" + +/obj/item/key/bike/moped/Initialize(mapload, ...) + . = ..() + icon_state = pick("key_tag_gray", "key_tag_green", "key_tag_purple") + +/obj/item/key/bike/police + name = "police bike key" + desc = "Used to start a police bike." + icon_state = "key_tag_police" diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index e1281c211e9..f2f7d8c4c4a 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -1,11 +1,14 @@ /obj/vehicle/bike name = "space-bike" desc = "Space wheelies! Woo!" - desc_info = "Click-drag yourself onto the bike to climb onto it.
\ + desc_info = "\ + - Click-drag yourself onto the bike to climb onto it.
\ - Click-drag it onto yourself to access its mounted storage.
\ - CTRL-click the bike to toggle the engine.
\ + - Click the bike with a key to put it in, and click the bike with empty hand to take it out. The bike won't run without a key.
\ - ALT-click to toggle the kickstand which prevents movement by driving and dragging.
\ - - Click the resist button or type \"resist\" in the command bar at the bottom of your screen to get off the bike." + - Click the resist button or type \"resist\" in the command bar at the bottom of your screen to get off the bike.
\ + " icon = 'icons/obj/vehicle/bike.dmi' icon_state = "bike_off" dir = SOUTH @@ -30,6 +33,25 @@ var/kickstand = TRUE var/can_hover = TRUE + /// Registration plate string of the vehicle, visible on examine, + /// to distingush different vehicles of the same type from each other. + /// Also used to check if the key is for this vehicle. + /// If null, it is randomly generated on init. + var/registration_plate = null + /// Key type accepted in vehicle ignition. + var/key_type = /obj/item/key/bike + /// Actual key object in the vehicle ignition, or null if no key in ignition. + /// To actually start the vehicle, key data needs to match with the registration plate string. + var/obj/item/key/key = null + /// If TRUE, vehicle spawns with the key that matches its registration plate string. + /// If FALSE, the key needs to be mapped/spawned somewhere outside of the vehicle, + /// otherwise it will be an unusable prop. + var/spawns_with_key = TRUE + +/obj/vehicle/bike/Destroy() + QDEL_NULL(key) + return ..() + /obj/vehicle/bike/setup_vehicle() ..() ion = new ion_type(src) @@ -38,6 +60,23 @@ icon_state = "[bike_icon]_off" if(storage_type) storage_compartment = new storage_type(src) + if(!registration_plate) + generate_registration_plate() + if(spawns_with_key) + key = new key_type(src) + key.key_data = registration_plate + +/obj/vehicle/bike/get_examine_text(mob/user, distance, is_adjacent, infix, suffix) + . = ..() + if(distance <= 4) + . += "\The [src] has a small registration plate on the back, '[registration_plate]'." + if(key) + . += "\The [src] has \a [key] in." + else + . += "\The [src] does not have a key in." + +/obj/vehicle/bike/proc/generate_registration_plate() + registration_plate = "[rand(100,999)]-[rand(1000,9999)]" /obj/vehicle/bike/CtrlClick(var/mob/user) if(Adjacent(user) && anchored) @@ -50,9 +89,17 @@ return if(!on) - turn_on() - src.visible_message("\The [src] rumbles to life.", "You hear something rumble deeply.") - playsound(src, 'sound/machines/vehicles/bike_start.ogg', 100, 1) + if(!key) + to_chat(user, SPAN_WARNING("You cannot turn \the [src] on, without a key.")) + return + + if((key.key_data != registration_plate)) + user.visible_message("\The [user] turns \a [key] in the ignition of \the [src].", "You turn \a [key] in the ignition of \the [src], but it lets out a sharp buzz.") + else + user.visible_message("\The [user] turns \a [key] in the ignition of \the [src].", "You turn \a [key] in the ignition of \the [src], and it beeps happily.") + turn_on() + src.visible_message("\The [src] rumbles to life.", "You hear something rumble deeply.") + playsound(src, 'sound/machines/vehicles/bike_start.ogg', 100, 1) else turn_off() src.visible_message("\The [src] putters before turning off.", "You hear something putter slowly.") @@ -83,7 +130,6 @@ var/mob/M = pulledby M.stop_pulling() - kickstand = !kickstand anchored = (kickstand || on) @@ -105,9 +151,12 @@ return /obj/vehicle/bike/attack_hand(var/mob/user as mob) - if(user == load) - unload(load) - to_chat(user, "You unbuckle yourself from \the [src]") + if(key) + to_chat(user, "You take \the [key] out of \the [src]") + user.put_in_hands(key) + key = null + if(on) + toggle_engine(user) else if(user != load && load) user.visible_message ("[user] starts to unbuckle [load] from \the [src]!") if(do_after(user, 8 SECONDS, src)) @@ -115,6 +164,20 @@ to_chat(user, "You unbuckle [load] from \the [src]") to_chat(load, "You were unbuckled from \the [src] by [user]") +/obj/vehicle/bike/attackby(obj/item/attacking_item, mob/user) + if(istype(attacking_item, /obj/item/key)) + if(!key) + if(istype(attacking_item, key_type)) + user.drop_from_inventory(attacking_item, src) + key = attacking_item + to_chat(user, SPAN_NOTICE("You put \the [attacking_item] in \the [src].")) + update_icon() + else + to_chat(user, SPAN_NOTICE("You try to put \the [attacking_item] in \the [src], but it does not fit.")) + else + to_chat(user, SPAN_NOTICE("\The [src] already has a key in it.")) + ..() + /obj/vehicle/bike/relaymove(mob/user, direction) if(user != load || !on || user.incapacitated()) return @@ -373,6 +436,10 @@ space_speed = 0 protection_percent = 10 can_hover = FALSE + key_type = /obj/item/key/bike/sport + +/obj/vehicle/bike/motor/generate_registration_plate() + registration_plate = "[rand(10,99)]S-[rand(1000,9999)]" /obj/vehicle/bike/motor/blue icon_state = "bluesport_on" @@ -391,19 +458,31 @@ desc = "A two-wheeled vehicle meant for easy riding. This comes in stark white colors with flashy lights, indicating it is the law. It has the insignias of Konyang's police force." icon_state = "konyangpolice_on" bike_icon = "konyangpolice" + key_type = /obj/item/key/bike/police + +/obj/vehicle/bike/motor/police_konyang/generate_registration_plate() + registration_plate = "[rand(10,99)]P-[rand(1000,9999)]" /obj/vehicle/bike/motor/moped name = "moped" desc = "A cheap, two-wheeled motorized bicycle." icon_state = "greenmoped_on" bike_icon = "greenmoped" - land_speed = 2//slower than a sport bike but will still get you around big maps + land_speed = 2 // slower than a sport bike but will still get you around big maps + key_type = /obj/item/key/bike/moped + +/obj/vehicle/bike/motor/moped/generate_registration_plate() + registration_plate = "[rand(10,99)]M-[rand(1000,9999)]" /obj/vehicle/bike/motor/moped/police_konyang name = "police moped" desc = "A cheap, two-wheeled motorized bicycle. This comes in stark white colors with flashy lights, indicating it is the law. It has the insignias of Konyang's police force." icon_state = "konyangpolicemoped_on" bike_icon = "konyangpolicemoped" + key_type = /obj/item/key/bike/police + +/obj/vehicle/bike/motor/moped/police_konyang/generate_registration_plate() + registration_plate = "[rand(10,99)]P-[rand(1000,9999)]" /obj/vehicle/bike/motor/moped/red icon_state = "redmoped_on" diff --git a/html/changelogs/DreamySkrell-bike-keys.yml b/html/changelogs/DreamySkrell-bike-keys.yml new file mode 100644 index 00000000000..9f4c9729cdb --- /dev/null +++ b/html/changelogs/DreamySkrell-bike-keys.yml @@ -0,0 +1,7 @@ + +author: DreamySkrell + +delete-after: True + +changes: + - rscadd: "Adds bike keys and mechanics." diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index 31cb82318bf9face3506307606351a621eb7afa9..eab8c5091c8448b57e5941c4e278f235ec6b9241 100644 GIT binary patch literal 6795 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