[READY] New clown traitor item: The clown car (#39317)

I've been wanting to add this for a while, and now I have. The clown car is a vehicle you can use if you're a traitor clown to run people over, shove them into your compact trunk, and take them for a ride. If you drive into any walls however, you and everyone you kidnapped, fall out of the car, leaving you somewhat vulnerable.

It also comes with a lube-defense mechanism(tm) which has a 1/3 chance to drop some lube if someone decides to shoot at your sweet ride.

You can also honk your horn or drop all of the drivers if you would like to.
This commit is contained in:
Qustinnus
2018-08-26 02:41:05 +02:00
committed by yogstation13-bot
parent 94c8cbffb7
commit c9330feebc
20 changed files with 249 additions and 10 deletions

View File

@@ -0,0 +1,9 @@
//Vehicle control flags
#define VEHICLE_CONTROL_PERMISSION 1
#define VEHICLE_CONTROL_DRIVE 2
#define VEHICLE_CONTROL_KIDNAPPED 4 //Can't leave vehicle voluntarily, has to resist.
//Car trait flags
#define CAN_KIDNAP 1

View File

@@ -1472,6 +1472,17 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 15 cost = 15
restricted_roles = list("Clown") restricted_roles = list("Clown")
/datum/uplink_item/role_restricted/clowncar
name = "Clown Car"
desc = "The Clown Car is the ultimate transportation method for any worthy clown! \
Simply insert your bikehorn and get in, and get ready to have the funniest ride of your life! \
You can ram any spacemen you come across and stuff them into your car, kidnapping them and locking them inside until \
someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \
are very sensetive. Now with our included lube defense mechanism which will protect you against any angry shitcurity!"
item = /obj/vehicle/sealed/car/clowncar
cost = 18
restricted_roles = list("Clown")
// Pointless // Pointless
/datum/uplink_item/badass /datum/uplink_item/badass
category = "(Pointless) Badassery" category = "(Pointless) Badassery"

View File

@@ -1,6 +1,3 @@
#define VEHICLE_CONTROL_PERMISSION 1
#define VEHICLE_CONTROL_DRIVE 2
/obj/vehicle /obj/vehicle
name = "generic vehicle" name = "generic vehicle"
desc = "Yell at coderbus." desc = "Yell at coderbus."
@@ -72,8 +69,8 @@
return FALSE return FALSE
occupants[M] = NONE occupants[M] = NONE
add_control_flags(M, control_flags) add_control_flags(M, control_flags)
grant_passenger_actions(M)
after_add_occupant(M) after_add_occupant(M)
grant_passenger_actions(M)
return TRUE return TRUE
/obj/vehicle/proc/after_add_occupant(mob/M) /obj/vehicle/proc/after_add_occupant(mob/M)
@@ -119,8 +116,12 @@
step(trailer, dir_to_move) step(trailer, dir_to_move)
return did_move return did_move
else else
after_move(direction)
return step(src, direction) return step(src, direction)
/obj/vehicle/proc/after_move(direction)
return
/obj/vehicle/proc/add_control_flags(mob/controller, flags) /obj/vehicle/proc/add_control_flags(mob/controller, flags)
if(!istype(controller) || !flags) if(!istype(controller) || !flags)
return FALSE return FALSE
@@ -142,7 +143,7 @@
/obj/vehicle/Bump(atom/movable/M) /obj/vehicle/Bump(atom/movable/M)
. = ..() . = ..()
if(emulate_door_bumps) if(emulate_door_bumps)
if(istype(M, /obj/machinery/door) && has_buckled_mobs()) if(istype(M, /obj/machinery/door))
for(var/m in occupants) for(var/m in occupants)
M.Bumped(m) M.Bumped(m)

View File

@@ -0,0 +1,68 @@
/obj/vehicle/sealed/car
layer = ABOVE_MOB_LAYER
anchored = TRUE
var/car_traits = NONE //Bitflag for special behavior such as kidnapping
var/engine_sound = 'sound/vehicles/carrev.ogg'
var/last_enginesound_time
var/engine_sound_length = 20 //Set this to the length of the engine sound
var/escape_time = 200 //Time it takes to break out of the car
/obj/vehicle/sealed/car/generate_actions()
. = ..()
initialize_controller_action_type(/datum/action/vehicle/sealed/remove_key, VEHICLE_CONTROL_DRIVE)
if(car_traits & CAN_KIDNAP)
initialize_controller_action_type(/datum/action/vehicle/sealed/DumpKidnappedMobs, VEHICLE_CONTROL_DRIVE)
/obj/vehicle/sealed/car/MouseDrop_T(atom/dropping, mob/M)
if(!M.canmove || M.stat || M.restrained())
return FALSE
if(ismob(dropping) && M != dropping)
var/mob/D = dropping
M.visible_message("<span class='warning'>[M] starts forcing [D] into [src]!</span>")
mob_try_forced_enter(M, D)
return ..()
/obj/vehicle/sealed/car/mob_try_exit(mob/M, mob/user, silent = FALSE)
if(M == user && (occupants[M] & VEHICLE_CONTROL_KIDNAPPED))
to_chat(user, "<span class='notice'>You push against the back of [src] trunk to try and get out.</span>")
if(!do_after(user, escape_time, target = src))
return FALSE
to_chat(user,"<span class='danger'>[user] gets out of [src]</span>")
mob_exit(M, silent)
return TRUE
mob_exit(M, silent)
return TRUE
/obj/vehicle/sealed/car/after_move(direction)
if(world.time < last_enginesound_time + engine_sound_length)
return
last_enginesound_time = world.time
playsound(src, engine_sound, 100, TRUE)
/obj/vehicle/sealed/car/attack_hand(mob/living/user)
. = ..()
if(!(car_traits & CAN_KIDNAP))
return
to_chat(user, "<span class='notice'>You start opening [src]'s trunk.</span>")
if(do_after(user, 30))
if(return_amount_of_controllers_with_flag(VEHICLE_CONTROL_KIDNAPPED))
to_chat(user, "<span class='notice'>The people stuck in [src]'s trunk all come tumbling out.</span>")
DumpSpecificMobs(VEHICLE_CONTROL_KIDNAPPED)
else
to_chat(user, "<span class='notice'>It seems [src]'s trunk was empty.</span>")
/obj/vehicle/sealed/car/proc/mob_try_forced_enter(mob/forcer, mob/M, silent = FALSE)
if(!istype(M))
return FALSE
if(occupant_amount() >= max_occupants)
return FALSE
if(do_mob(forcer, get_enter_delay(M), target = src))
mob_forced_enter(M, silent)
return TRUE
return FALSE
/obj/vehicle/sealed/car/proc/mob_forced_enter(mob/M, silent = FALSE)
if(!silent)
M.visible_message("<span class='warning'>[M] is forced into \the [src]!</span>")
M.forceMove(src)
add_occupant(M, VEHICLE_CONTROL_KIDNAPPED)

View File

@@ -0,0 +1,53 @@
/obj/vehicle/sealed/car/clowncar
name = "clown car"
desc = "How someone could even fit in there is beyond me."
icon_state = "clowncar"
max_integrity = 500
armor = list("melee" = 70, "bullet" = 40, "laser" = 40, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
enter_delay = 20
max_occupants = 50
movedelay = 0.6
car_traits = CAN_KIDNAP
key_type = /obj/item/bikehorn
key_type_exact = FALSE
/obj/vehicle/sealed/car/clowncar/generate_actions()
. = ..()
initialize_controller_action_type(/datum/action/vehicle/sealed/horn/clowncar, VEHICLE_CONTROL_DRIVE)
/obj/vehicle/sealed/car/clowncar/auto_assign_occupant_flags(mob/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.mind && H.mind.assigned_role == "Clown") //Ensures only clowns can drive the car. (Including more at once)
add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION)
return
add_control_flags(M, VEHICLE_CONTROL_KIDNAPPED)
/obj/vehicle/sealed/car/clowncar/mob_forced_enter(mob/M, silent = FALSE)
. = ..()
playsound(src, pick('sound/vehicles/clowncar_load1.ogg', 'sound/vehicles/clowncar_load2.ogg'), 75)
/obj/vehicle/sealed/car/clowncar/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
if(prob(33))
visible_message("<span class='danger'>[src] spews out a ton of space lube!/span>/span>")
new /obj/effect/particle_effect/foam(loc) //YEET
/obj/vehicle/sealed/car/clowncar/Bump(atom/movable/M)
..()
if(iscarbon(M))
var/mob/living/carbon/C = M
C.Knockdown(50)
C.visible_message("<span class='warning'>[src] rams into [C] and sucks him up!</span>") //fuck off shezza this isn't ERP.
mob_forced_enter(C)
playsound(src, pick('sound/vehicles/clowncar_ram1.ogg', 'sound/vehicles/clowncar_ram2.ogg', 'sound/vehicles/clowncar_ram3.ogg'), 75)
else if(istype(M, /turf/closed))
visible_message("<span class='warning'>[src] rams into [M] and crashes!</span>")
playsound(src, pick('sound/vehicles/clowncar_crash1.ogg', 'sound/vehicles/clowncar_crash2.ogg'), 75)
playsound(src, 'sound/vehicles/clowncar_crashpins.ogg', 75)
DumpMobs(TRUE)
/obj/vehicle/sealed/car/clowncar/deconstruct(disassembled = TRUE)
. = ..()
playsound(src, 'sound/vehicles/clowncar_fart.ogg', 100)

View File

@@ -35,22 +35,73 @@
if(!istype(M)) if(!istype(M))
return FALSE return FALSE
if(!silent) if(!silent)
M.visible_message("<span class='boldnotice'>[M] climbs into \the [src]!</span>") M.visible_message("<span class='notice'>[M] climbs into \the [src]!</span>")
M.forceMove(src) M.forceMove(src)
add_occupant(M) add_occupant(M)
return TRUE return TRUE
/obj/vehicle/sealed/proc/mob_try_exit(mob/M, mob/user, silent = FALSE) /obj/vehicle/sealed/proc/mob_try_exit(mob/M, mob/user, silent = FALSE, randomstep = FALSE)
mob_exit(M, silent) mob_exit(M, silent, randomstep)
/obj/vehicle/sealed/proc/mob_exit(mob/M, silent = FALSE) /obj/vehicle/sealed/proc/mob_exit(mob/M, silent = FALSE, randomstep = FALSE)
if(!istype(M)) if(!istype(M))
return FALSE return FALSE
remove_occupant(M) remove_occupant(M)
M.forceMove(exit_location(M)) M.forceMove(exit_location(M))
if(randomstep)
var/turf/target_turf = get_step(exit_location(M), pick(GLOB.cardinals))
M.throw_at(target_turf, 5, 10)
if(!silent) if(!silent)
M.visible_message("<span class='boldnotice'>[M] drops out of \the [src]!</span>") M.visible_message("<span class='notice'>[M] drops out of \the [src]!</span>")
return TRUE return TRUE
/obj/vehicle/sealed/proc/exit_location(M) /obj/vehicle/sealed/proc/exit_location(M)
return drop_location() return drop_location()
/obj/vehicle/sealed/attackby(obj/item/I, mob/user, params)
if(key_type && !is_key(inserted_key) && is_key(I))
if(user.transferItemToLoc(I, src))
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
if(inserted_key) //just in case there's an invalid key
inserted_key.forceMove(drop_location())
inserted_key = I
else
to_chat(user, "<span class='notice'>[I] seems to be stuck to your hand!</span>")
return
return ..()
/obj/vehicle/sealed/proc/remove_key(mob/user)
if(!inserted_key)
to_chat(user, "<span class='notice'>There is no key in [src]!</span>")
return
if(!is_occupant(user) || !(occupants[user] & VEHICLE_CONTROL_DRIVE))
to_chat(user, "<span class='notice'>You must be driving [src] to remove [src]'s key!</span>")
return
to_chat(user, "<span class='notice'>You remove [inserted_key] from [src].</span>")
inserted_key.forceMove(drop_location())
user.put_in_hands(inserted_key)
inserted_key = null
/obj/vehicle/sealed/deconstruct(disassembled = TRUE)
. = ..()
DumpMobs()
explosion(loc, 0, 1, 2, 3, 0)
/obj/vehicle/sealed/proc/DumpMobs(randomstep = TRUE)
for(var/i in occupants)
if(iscarbon(i))
var/mob/living/carbon/Carbon = i
mob_exit(Carbon, null, randomstep)
Carbon.Knockdown(40)
/obj/vehicle/sealed/proc/DumpSpecificMobs(flag, randomstep = TRUE)
for(var/i in occupants)
if((occupants[i] & flag) && iscarbon(i))
var/mob/living/carbon/C = i
mob_exit(C, null, randomstep)
C.Knockdown(40)
/obj/vehicle/sealed/AllowDrop()
return FALSE

View File

@@ -103,6 +103,7 @@
/datum/action/vehicle/sealed/climb_out /datum/action/vehicle/sealed/climb_out
name = "Climb Out" name = "Climb Out"
desc = "Climb out of your vehicle!" desc = "Climb out of your vehicle!"
button_icon_state = "car_eject"
/datum/action/vehicle/sealed/climb_out/Trigger() /datum/action/vehicle/sealed/climb_out/Trigger()
if(..() && istype(vehicle_entered_target)) if(..() && istype(vehicle_entered_target))
@@ -110,3 +111,45 @@
/datum/action/vehicle/ridden /datum/action/vehicle/ridden
var/obj/vehicle/ridden/vehicle_ridden_target var/obj/vehicle/ridden/vehicle_ridden_target
/datum/action/vehicle/sealed/remove_key
name = "Remove key"
desc = "Take your key out of the vehicle's ignition"
button_icon_state = "car_removekey"
/datum/action/vehicle/sealed/remove_key/Trigger()
vehicle_entered_target.remove_key(owner)
//CLOWN CAR ACTION DATUMS
/datum/action/vehicle/sealed/horn
name = "Honk Horn"
desc = "Honk your classy horn."
button_icon_state = "car_horn"
var/hornsound = 'sound/items/carhorn.ogg'
var/last_honk_time
/datum/action/vehicle/sealed/horn/Trigger()
if(world.time - last_honk_time > 20)
vehicle_entered_target.visible_message("<span class='danger'>[vehicle_entered_target] loudly honks</span>")
to_chat(owner, "<span class='notice'>You press the vehicle's horn.</span>")
playsound(vehicle_entered_target, hornsound, 75)
last_honk_time = world.time
/datum/action/vehicle/sealed/horn/clowncar/Trigger()
if(world.time - last_honk_time > 20)
vehicle_entered_target.visible_message("<span class='danger'>[vehicle_entered_target] loudly honks</span>")
to_chat(owner, "<span class='notice'>You press the vehicle's horn.</span>")
last_honk_time = world.time
if(vehicle_target.inserted_key)
vehicle_target.inserted_key.attack_self(owner) //The key plays a sound
else
playsound(vehicle_entered_target, hornsound, 75)
/datum/action/vehicle/sealed/DumpKidnappedMobs
name = "Dump kidnapped mobs"
desc = "Dump all objects and people in your car on the floor."
button_icon_state = "car_dump"
/datum/action/vehicle/sealed/DumpKidnappedMobs/Trigger()
vehicle_entered_target.visible_message("<span class='danger'>[vehicle_entered_target] starts dumping the people inside of it.</span>")
vehicle_entered_target.DumpSpecificMobs(VEHICLE_CONTROL_KIDNAPPED)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
sound/vehicles/carrev.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -97,6 +97,7 @@
#include "code\__DEFINES\traits.dm" #include "code\__DEFINES\traits.dm"
#include "code\__DEFINES\turf_flags.dm" #include "code\__DEFINES\turf_flags.dm"
#include "code\__DEFINES\typeids.dm" #include "code\__DEFINES\typeids.dm"
#include "code\__DEFINES\vehicles.dm"
#include "code\__DEFINES\vv.dm" #include "code\__DEFINES\vv.dm"
#include "code\__DEFINES\wall_dents.dm" #include "code\__DEFINES\wall_dents.dm"
#include "code\__DEFINES\wires.dm" #include "code\__DEFINES\wires.dm"
@@ -2653,6 +2654,8 @@
#include "code\modules\vehicles\speedbike.dm" #include "code\modules\vehicles\speedbike.dm"
#include "code\modules\vehicles\vehicle_actions.dm" #include "code\modules\vehicles\vehicle_actions.dm"
#include "code\modules\vehicles\vehicle_key.dm" #include "code\modules\vehicles\vehicle_key.dm"
#include "code\modules\vehicles\cars\car.dm"
#include "code\modules\vehicles\cars\clowncar.dm"
#include "code\modules\vending\_vending.dm" #include "code\modules\vending\_vending.dm"
#include "code\modules\vending\assist.dm" #include "code\modules\vending\assist.dm"
#include "code\modules\vending\autodrobe.dm" #include "code\modules\vending\autodrobe.dm"