Merge pull request #15180 from LetterN/achives-

Achivement & Clowncar update
This commit is contained in:
silicons
2021-09-28 00:15:52 -07:00
committed by GitHub
29 changed files with 513 additions and 180 deletions

View File

@@ -226,16 +226,16 @@
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shed_human_form)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
H.physiology.brute_mod *= 0.5
H.physiology.burn_mod *= 0.5
var/datum/antagonist/heretic/heretic = user.mind.has_antag_datum(/datum/antagonist/heretic)
var/datum/eldritch_knowledge/flesh_grasp/ghoul1 = heretic.get_knowledge(/datum/eldritch_knowledge/flesh_grasp)
ghoul1.ghoul_amt *= 3
var/datum/eldritch_knowledge/flesh_ghoul/ghoul2 = heretic.get_knowledge(/datum/eldritch_knowledge/flesh_ghoul)
ghoul2.max_amt *= 3
var/mob/living/carbon/human/lord_of_arms = user
lord_of_arms.physiology.brute_mod *= 0.5
lord_of_arms.physiology.burn_mod *= 0.5
lord_of_arms.client?.give_award(/datum/award/achievement/misc/flesh_ascension, lord_of_arms)
var/datum/antagonist/heretic/heretic_datum = user.mind.has_antag_datum(/datum/antagonist/heretic)
var/datum/eldritch_knowledge/flesh_grasp/grasp_ghoul = heretic_datum.get_knowledge(/datum/eldritch_knowledge/flesh_grasp)
grasp_ghoul.ghoul_amt *= 3
var/datum/eldritch_knowledge/flesh_ghoul/better_ghoul = heretic_datum.get_knowledge(/datum/eldritch_knowledge/flesh_ghoul)
better_ghoul.max_amt *= 3
return ..()
/datum/eldritch_knowledge/flesh_blade_upgrade_2
name = "Remembrance"

View File

@@ -181,13 +181,13 @@
var/mob/living/carbon/human/H = user
H.physiology.brute_mod *= 0.5
H.physiology.burn_mod *= 0.5
H.client?.give_award(/datum/award/achievement/misc/rust_ascension, H)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the decay, for the Rustbringer, [user.real_name] has ascended! None shall escape the corrosion! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
new /datum/rust_spread(loc)
var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
ascension.ascended = TRUE
return ..()
/datum/eldritch_knowledge/final/rust_final/on_life(mob/user)
. = ..()
if(!finished)

View File

@@ -183,14 +183,14 @@
var/datum/weather/void_storm/storm
/datum/eldritch_knowledge/final/void_final/on_finished_recipe(mob/living/user, list/atoms, loc)
var/mob/living/carbon/human/H = user
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch)
H.physiology.brute_mod *= 0.5
H.physiology.burn_mod *= 0.5
ADD_TRAIT(H, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# The nobleman of void [H.real_name] has arrived, step along the Waltz that ends worlds! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
sound_loop = new(list(user),TRUE,TRUE)
var/mob/living/carbon/human/waltzing = user
waltzing.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch)
waltzing.physiology.brute_mod *= 0.5
waltzing.physiology.burn_mod *= 0.5
ADD_TRAIT(waltzing, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT)
waltzing.client?.give_award(/datum/award/achievement/misc/void_ascension, waltzing)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# The nobleman of void [waltzing.real_name] has arrived, step along the Waltz that ends worlds! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
sound_loop = new(user, TRUE, TRUE)
return ..()
/datum/eldritch_knowledge/final/void_final/on_death()

View File

@@ -50,6 +50,14 @@
A.death()
return ..()
/obj/item/soulstone/proc/hot_potato(mob/living/user)
to_chat(user, span_userdanger("Holy magics residing in \the [src] burn your hand!"))
var/obj/item/bodypart/affecting = user.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
affecting.receive_damage( 0, 10 ) // 10 burn damage
user.emote("scream")
user.update_damage_overlays()
user.dropItemToGround(src)
//////////////////////////////Capturing////////////////////////////////////////////////////////
/obj/item/soulstone/attack(mob/living/carbon/human/M, mob/living/user)
@@ -94,6 +102,35 @@
to_chat(A, "<b>You have been released from your prison, but you are still bound to the cult's will. Help them succeed in their goals at all costs.</b>")
was_used()
/obj/item/soulstone/pre_attack(atom/A, mob/living/user, params)
var/mob/living/simple_animal/hostile/construct/shade/occupant = (locate() in src)
var/obj/item/storage/toolbox/mechanical/target_toolbox = A
if(!occupant || !istype(target_toolbox) || target_toolbox.has_soul)
return ..()
if(iscultist(user))
hot_potato(user)
return
if(!iscultist(user, TRUE) && !iswizard(user) && !usability)
user.Unconscious(10 SECONDS)
to_chat(user, span_userdanger("Your body is wracked with debilitating pain!"))
return
user.visible_message("<span class='notice'>[user] holds [src] above [user.p_their()] head and forces it into [target_toolbox] with a flash of light!", \
span_notice("You hold [src] above your head briefly, then force it into [target_toolbox], transferring the [occupant]'s soul!"), ignored_mobs = occupant)
to_chat(occupant, span_userdanger("[user] holds you up briefly, then forces you into [target_toolbox]!"))
to_chat(occupant, span_deadsay("<b>Your eternal soul has been sacrificed to restore the soul of a toolbox. Them's the breaks!</b>"))
occupant.client?.give_award(/datum/award/achievement/misc/toolbox_soul, occupant)
occupant.deathmessage = "shrieks out in unholy pain as [occupant.p_their()] soul is absorbed into [target_toolbox]!"
release_shades(user, TRUE)
occupant.death()
target_toolbox.name = "soulful toolbox"
target_toolbox.icon_state = "toolbox_blue_old"
target_toolbox.has_soul = TRUE
target_toolbox.has_latches = FALSE
///////////////////////////Transferring to constructs/////////////////////////////////////////////////////
/obj/structure/constructshell
name = "empty shell"

View File

@@ -95,20 +95,78 @@
/mob/living/simple_animal/hostile/carp/cayenne
name = "Cayenne"
real_name = "Cayenne"
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
gender = FEMALE
regen_amount = 8
speak_emote = list("squeaks")
maxHealth = 90
health = 90
gold_core_spawnable = NO_SPAWN
faction = list(ROLE_SYNDICATE, "carp") //They are still a carp
AIStatus = AI_OFF
gold_core_spawnable = NO_SPAWN
faction = list(ROLE_SYNDICATE)
/// Keeping track of the nuke disk for the functionality of storing it.
var/obj/item/disk/nuclear/disky
/// Location of the file storing disk overlays
// var/icon/disk_overlay_file = 'icons/mob/carp.dmi'
/// Colored disk mouth appearance for adding it as a mouth overlay
var/mutable_appearance/colored_disk_mouth
harm_intent_damage = 12
obj_damage = 70
melee_damage_lower = 15
melee_damage_upper = 18
/mob/living/simple_animal/hostile/carp/cayenne/Initialize()
. = ..()
// AddElement(/datum/element/pet_bonus, "bloops happily!")
// colored_disk_mouth = mutable_appearance(SSgreyscale.GetColoredIconByType(/datum/greyscale_config/carp/disk_mouth, greyscale_colors), "disk_mouth")
ADD_TRAIT(src, TRAIT_DISK_VERIFIER, INNATE_TRAIT) //carp can verify disky
/mob/living/simple_animal/hostile/carp/cayenne/IsAdvancedToolUser()
return TRUE //carp SMART
/mob/living/simple_animal/hostile/carp/cayenne/death(gibbed)
if(disky)
disky.forceMove(drop_location())
disky = null
return ..()
/mob/living/simple_animal/hostile/carp/cayenne/Destroy(force)
QDEL_NULL(disky)
return ..()
/mob/living/simple_animal/hostile/carp/cayenne/examine(mob/user)
. = ..()
if(disky)
. += span_notice("Wait... is that [disky] in [p_their()] mouth?")
/mob/living/simple_animal/hostile/carp/cayenne/AttackingTarget(atom/attacked_target)
if(istype(attacked_target, /obj/item/disk/nuclear))
var/obj/item/disk/nuclear/potential_disky = attacked_target
if(potential_disky.anchored)
return
potential_disky.forceMove(src)
disky = potential_disky
to_chat(src, span_nicegreen("YES!! You manage to pick up [disky]. (Click anywhere to place it back down.)"))
update_icon()
if(!disky.fake)
client.give_award(/datum/award/achievement/misc/cayenne_disk, src)
return
if(disky)
if(isopenturf(attacked_target))
to_chat(src, span_notice("You place [disky] on [attacked_target]"))
disky.forceMove(attacked_target.drop_location())
disky = null
update_icon()
else
disky.melee_attack_chain(src, attacked_target)
return
return ..()
/mob/living/simple_animal/hostile/carp/cayenne/Exited(atom/movable/gone, direction)
. = ..()
if(disky == gone)
disky = null
update_icon()
/mob/living/simple_animal/hostile/carp/cayenne/update_overlays()
. = ..()
if(!disky || stat == DEAD)
return
// . += colored_disk_mouth
// . += mutable_appearance(disk_overlay_file, "disk_overlay")
#undef REGENERATION_DELAY

View File

@@ -32,6 +32,9 @@ Difficulty: Hard
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
achievement_type = /datum/award/achievement/boss/wendigo_kill
crusher_achievement_type = /datum/award/achievement/boss/wendigo_crusher
score_achievement_type = /datum/award/score/wendigo_score
deathmessage = "falls, shaking the ground around it"
deathsound = 'sound/effects/gravhit.ogg'
attack_action_types = list(/datum/action/innate/megafauna_attack/heavy_stomp,

View File

@@ -91,9 +91,9 @@
/obj/vehicle/proc/after_add_occupant(mob/M)
auto_assign_occupant_flags(M)
/obj/vehicle/proc/auto_assign_occupant_flags(mob/M) //override for each type that needs it. Default is assign driver if drivers is not at max.
/obj/vehicle/proc/auto_assign_occupant_flags(mob/M) //override for each type that needs it. Default is assign driver if drivers is not at max.
if(driver_amount() < max_drivers)
add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION)
add_control_flags(M, VEHICLE_CONTROL_DRIVE)
/obj/vehicle/proc/remove_occupant(mob/M)
if(!istype(M))

View File

@@ -16,7 +16,7 @@
. = ..()
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)
initialize_controller_action_type(/datum/action/vehicle/sealed/dump_kidnapped_mobs, VEHICLE_CONTROL_DRIVE)
/obj/vehicle/sealed/car/driver_move(mob/user, direction)
if(key_type && !is_key(inserted_key))

View File

@@ -1,6 +1,6 @@
/obj/vehicle/sealed/car/clowncar
name = "clown car"
desc = "How someone could even fit in there is beyond me."
desc = "How someone could even fit in there is byond me."
icon_state = "clowncar"
max_integrity = 150
armor = list("melee" = 70, "bullet" = 40, "laser" = 40, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
@@ -10,25 +10,36 @@
car_traits = CAN_KIDNAP
key_type = /obj/item/bikehorn
key_type_exact = FALSE
var/droppingoil = FALSE
var/RTDcooldown = 150
var/lastRTDtime = 0
///list of headlight colors we use to pick through when we have party mode due to emag
var/headlight_colors = list(COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_LIME, COLOR_BRIGHT_BLUE, COLOR_CYAN, COLOR_PURPLE)
///Cooldown time inbetween [/obj/vehicle/sealed/car/clowncar/proc/roll_the_dice()] usages
var/dice_cooldown_time = 150
///How many times kidnappers in the clown car said thanks
var/thankscount = 0
///Current status of the cannon, alternates between CLOWN_CANNON_INACTIVE, CLOWN_CANNON_BUSY and CLOWN_CANNON_READY
var/cannonmode = CLOWN_CANNON_INACTIVE
var/light_on = TRUE
/obj/vehicle/sealed/car/clowncar/Initialize()
. = ..()
START_PROCESSING(SSobj,src)
/obj/vehicle/sealed/car/clowncar/process()
if(light_on && (obj_flags & EMAGGED))
set_light_color(pick(headlight_colors))
/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/driver_move(mob/user, direction) //Prevent it from moving onto space
if(isspaceturf(get_step(src, direction)))
return FALSE
else
return ..()
initialize_controller_action_type(/datum/action/vehicle/sealed/horn, VEHICLE_CONTROL_DRIVE)
initialize_controller_action_type(/datum/action/vehicle/sealed/thank, VEHICLE_CONTROL_KIDNAPPED)
/obj/vehicle/sealed/car/clowncar/auto_assign_occupant_flags(mob/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.mind && HAS_TRAIT(H.mind, TRAIT_CLOWN_MENTALITY)) //Ensures only clowns can drive the car. (Including more at once)
add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION)
add_control_flags(H, VEHICLE_CONTROL_DRIVE)
RegisterSignal(H, COMSIG_MOB_CLICKON, .proc/fire_cannon_at)
M.log_message("has entered [src] as a possible driver", LOG_ATTACK)
return
add_control_flags(M, VEHICLE_CONTROL_KIDNAPPED)
@@ -36,106 +47,195 @@
. = ..()
playsound(src, pick('sound/vehicles/clowncar_load1.ogg', 'sound/vehicles/clowncar_load2.ogg'), 75)
/obj/vehicle/sealed/car/clowncar/after_add_occupant(mob/M, control_flags)
. = ..()
if(return_controllers_with_flag(VEHICLE_CONTROL_KIDNAPPED).len >= 30)
for(var/mob/voreman as anything in return_drivers())
voreman.client.give_award(/datum/award/achievement/misc/round_and_full, voreman)
/obj/vehicle/sealed/car/clowncar/attack_animal(mob/living/simple_animal/user, list/modifiers)
if((user.loc != src) || user.environment_smash & (ENVIRONMENT_SMASH_WALLS|ENVIRONMENT_SMASH_RWALLS))
return ..()
/obj/vehicle/sealed/car/clowncar/mob_exit(mob/M, silent = FALSE, randomstep = FALSE)
. = ..()
UnregisterSignal(M, COMSIG_MOB_CLICKON)
/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>")
visible_message(span_danger("[src] spews out a ton of space lube!"))
new /obj/effect/particle_effect/foam(loc) //YEET
/obj/vehicle/sealed/car/clowncar/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
/obj/vehicle/sealed/car/clowncar/attacked_by(obj/item/I, mob/living/user)
. = ..()
if(istype(I, /obj/item/reagent_containers/food/snacks/grown/banana))
var/obj/item/reagent_containers/food/snacks/grown/banana/banana = I
obj_integrity += min(banana.seed.potency, max_integrity-obj_integrity)
to_chat(user, "<span class='danger'>You use the [banana] to repair the [src]!</span>")
qdel(banana)
if(!istype(I, /obj/item/reagent_containers/food/snacks/grown/banana))
return
var/obj/item/reagent_containers/food/snacks/grown/banana/banana = I
obj_integrity += min(banana.seed.potency, max_integrity-obj_integrity)
to_chat(user, span_danger("You use the [banana] to repair the [src]!"))
qdel(banana)
/obj/vehicle/sealed/car/clowncar/Bump(atom/movable/M)
/obj/vehicle/sealed/car/clowncar/Bump(atom/bumped)
. = ..()
if(isliving(M))
if(ismegafauna(M))
if(isliving(bumped))
if(ismegafauna(bumped))
return
var/mob/living/L = M
if(iscarbon(L))
var/mob/living/carbon/C = L
C.DefaultCombatKnockdown(40) //I play to make sprites go horizontal
L.visible_message("<span class='warning'>[src] rams into [L] and sucks him up!</span>") //fuck off shezza this isn't ERP.
mob_forced_enter(L)
var/mob/living/hittarget_living = bumped
if(iscarbon(hittarget_living))
var/mob/living/carbon/carb = hittarget_living
carb.DefaultCombatKnockdown(40) //I play to make sprites go horizontal
hittarget_living.visible_message(span_warning("[src] rams into [hittarget_living] and sucks [hittarget_living.p_them()] up!")) //fuck off shezza this isn't ERP.
mob_forced_enter(hittarget_living)
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) || istype(M, /obj/machinery/door/airlock/external))
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)
log_combat(src, hittarget_living, "sucked up")
return
if(!istype(bumped, /turf/closed))
return
visible_message(span_warning("[src] rams into [bumped] and crashes!"))
playsound(src, pick('sound/vehicles/clowncar_crash1.ogg', 'sound/vehicles/clowncar_crash2.ogg'), 75)
playsound(src, 'sound/vehicles/clowncar_crashpins.ogg', 75)
DumpMobs(TRUE)
log_combat(src, bumped, "crashed into", null, "dumping all passengers")
/obj/vehicle/sealed/car/clowncar/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
to_chat(user, "<span class='danger'>You scramble the clowncar child safety lock and a panel with 6 colorful buttons appears!</span>")
initialize_controller_action_type(/datum/action/vehicle/sealed/RollTheDice, VEHICLE_CONTROL_DRIVE)
to_chat(user, span_danger("You scramble \the [src]'s child safety lock, and a panel with six colorful buttons appears!"))
initialize_controller_action_type(/datum/action/vehicle/sealed/roll_the_dice, VEHICLE_CONTROL_DRIVE)
initialize_controller_action_type(/datum/action/vehicle/sealed/cannon, VEHICLE_CONTROL_DRIVE)
return TRUE
/obj/vehicle/sealed/car/clowncar/Destroy()
/obj/vehicle/sealed/car/clowncar/obj_destruction(damage_flag)
playsound(src, 'sound/vehicles/clowncar_fart.ogg', 100)
STOP_PROCESSING(SSobj,src)
return ..()
/obj/vehicle/sealed/car/clowncar/after_move(direction)
. = ..()
if(droppingoil)
new /obj/effect/decal/cleanable/oil/slippery(loc)
/obj/vehicle/sealed/car/clowncar/proc/RollTheDice(mob/user)
if(world.time - lastRTDtime < RTDcooldown)
to_chat(user, "<span class='notice'>The button panel is currently recharging.</span>")
/**
* Plays a random funky effect
* Only available while car is emagged
* Possible effects:
* * Spawn bananapeel
* * Spawn random reagent foam
* * Make the clown car look like a singulo temporarily
* * Spawn Laughing chem gas
* * Drop oil
* * Fart and make everyone nearby laugh
*/
/obj/vehicle/sealed/car/clowncar/proc/roll_the_dice(mob/user)
if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_CLOWNCAR_RANDOMNESS))
to_chat(user, span_notice("The button panel is currently recharging."))
return
lastRTDtime = world.time
var/randomnum = rand(1,6)
switch(randomnum)
TIMER_COOLDOWN_START(src, COOLDOWN_CLOWNCAR_RANDOMNESS, dice_cooldown_time)
switch(rand(1,6))
if(1)
visible_message("<span class='danger'>[user] has pressed one of the colorful buttons on [src] and a special banana peel drops out of it.</span>")
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and a special banana peel drops out of it."))
new /obj/item/grown/bananapeel/specialpeel(loc)
if(2)
visible_message("<span class='danger'>[user] has pressed one of the colorful buttons on [src] and unknown chemicals flood out of it.</span>")
var/datum/reagents/R = new/datum/reagents(300)
R.my_atom = src
R.add_reagent(get_random_reagent_id(), 100)
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and unknown chemicals flood out of it."))
var/datum/reagents/randomchems = new/datum/reagents(300)
randomchems.my_atom = src
randomchems.add_reagent(get_random_reagent_id(), 100)
var/datum/effect_system/foam_spread/foam = new
foam.set_up(200, loc, R)
foam.set_up(200, loc, randomchems)
foam.start()
if(3)
visible_message("<span class='danger'>[user] has pressed one of the colorful buttons on [src] and the clown car turns on its singularity disguise system.</span>")
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and the clown car turns on its singularity disguise system."))
icon = 'icons/obj/singularity.dmi'
icon_state = "singularity_s1"
addtimer(CALLBACK(src, .proc/ResetIcon), 100)
addtimer(CALLBACK(src, .proc/reset_icon), 10 SECONDS)
if(4)
visible_message("<span class='danger'>[user] has pressed one of the colorful buttons on [src] and the clown car spews out a cloud of laughing gas.</span>")
var/datum/reagents/R = new/datum/reagents(300)
R.my_atom = src
R.add_reagent(/datum/reagent/consumable/superlaughter, 50)
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and the clown car spews out a cloud of laughing gas."))
var/datum/reagents/funnychems = new/datum/reagents(300)
funnychems.my_atom = src
funnychems.add_reagent(/datum/reagent/consumable/superlaughter, 50)
var/datum/effect_system/smoke_spread/chem/smoke = new()
smoke.set_up(R, 4)
smoke.set_up(funnychems, 4)
smoke.attach(src)
smoke.start()
if(5)
visible_message("<span class='danger'>[user] has pressed one of the colorful buttons on [src] and the clown car starts dropping an oil trail.</span>")
droppingoil = TRUE
addtimer(CALLBACK(src, .proc/StopDroppingOil), 30)
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and the clown car starts dropping an oil trail."))
RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/cover_in_oil)
addtimer(CALLBACK(src, .proc/stop_dropping_oil), 3 SECONDS)
if(6)
visible_message("<span class='danger'>[user] has pressed one of the colorful buttons on [src] and the clown car lets out a comedic toot.</span>")
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and the clown car lets out a comedic toot."))
playsound(src, 'sound/vehicles/clowncar_fart.ogg', 100)
for(var/mob/living/L in orange(loc, 6))
L.emote("laughs")
for(var/mob/living/L in occupants)
for(var/mob/living/L as anything in occupants)
L.emote("laughs")
/obj/vehicle/sealed/car/clowncar/proc/ResetIcon()
///resets the icon and iconstate of the clowncar after it was set to singulo states
/obj/vehicle/sealed/car/clowncar/proc/reset_icon()
icon = initial(icon)
icon_state = initial(icon_state)
/obj/vehicle/sealed/car/clowncar/proc/StopDroppingOil()
droppingoil = FALSE
///Deploys oil when the clowncar moves in oil deploy mode
/obj/vehicle/sealed/car/clowncar/proc/cover_in_oil()
SIGNAL_HANDLER
new /obj/effect/decal/cleanable/oil/slippery(loc)
///Stops dropping oil after the time has run up
/obj/vehicle/sealed/car/clowncar/proc/stop_dropping_oil()
UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
///Toggles the on and off state of the clown cannon that shoots random kidnapped people
/obj/vehicle/sealed/car/clowncar/proc/toggle_cannon(mob/user)
if(cannonmode == CLOWN_CANNON_BUSY)
to_chat(user, span_notice("Please wait for the vehicle to finish its current action first."))
return
if(cannonmode) //canon active, deactivate
flick("clowncar_fromfire", src)
icon_state = "clowncar"
addtimer(CALLBACK(src, .proc/deactivate_cannon), 2 SECONDS)
playsound(src, 'sound/vehicles/clowncar_cannonmode2.ogg', 75)
visible_message(span_danger("The [src] starts going back into mobile mode."))
else
canmove = FALSE //anchor and activate canon
flick("clowncar_tofire", src)
icon_state = "clowncar_fire"
visible_message(span_danger("The [src] opens up and reveals a large cannon."))
addtimer(CALLBACK(src, .proc/activate_cannon), 2 SECONDS)
playsound(src, 'sound/vehicles/clowncar_cannonmode1.ogg', 75)
cannonmode = CLOWN_CANNON_BUSY
///Finalizes canon activation
/obj/vehicle/sealed/car/clowncar/proc/activate_cannon()
// mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi'
cannonmode = CLOWN_CANNON_READY
for(var/mob/living/driver as anything in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))
driver.update_mouse_pointer()
///Finalizes canon deactivation
/obj/vehicle/sealed/car/clowncar/proc/deactivate_cannon()
canmove = TRUE
// mouse_pointer = null
cannonmode = CLOWN_CANNON_INACTIVE
for(var/mob/living/driver as anything in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))
driver.update_mouse_pointer()
///Fires the cannon where the user clicks
/obj/vehicle/sealed/car/clowncar/proc/fire_cannon_at(mob/user, atom/A, params)
SIGNAL_HANDLER
if(cannonmode != CLOWN_CANNON_READY || !length(return_controllers_with_flag(VEHICLE_CONTROL_KIDNAPPED)))
return NONE
var/mob/living/unlucky_sod = pick(return_controllers_with_flag(VEHICLE_CONTROL_KIDNAPPED))
mob_exit(unlucky_sod, TRUE)
flick("clowncar_recoil", src)
playsound(src, pick('sound/vehicles/carcannon1.ogg', 'sound/vehicles/carcannon2.ogg', 'sound/vehicles/carcannon3.ogg'), 75)
unlucky_sod.throw_at(A, 10, 2)
log_combat(user, unlucky_sod, "fired", src, "towards [A]") //this doesn't catch if the mob hits something between the car and the target
return COMSIG_MOB_CANCEL_CLICKON
///Increments the thanks counter every time someone thats been kidnapped thanks the driver
/obj/vehicle/sealed/car/clowncar/proc/increment_thanks_counter()
thankscount++
if(thankscount < 100)
return
for(var/mob/busdriver as anything in return_drivers())
busdriver.client.give_award(/datum/award/achievement/misc/the_best_driver, busdriver)
/obj/vehicle/sealed/car/clowncar/twitch_plays
key_type = null
@@ -144,12 +244,10 @@
/obj/vehicle/sealed/car/clowncar/twitch_plays/Initialize()
. = ..()
AddComponent(/datum/component/twitch_plays/simple_movement)
START_PROCESSING(SSfastprocess, src)
GLOB.poi_list |= src
notify_ghosts("Twitch Plays: Clown Car")
/obj/vehicle/sealed/car/clowncar/twitch_plays/Destroy()
STOP_PROCESSING(SSfastprocess, src)
GLOB.poi_list -= src
return ..()
@@ -158,3 +256,4 @@
if(!dir)
return
driver_move(null, dir)
..()

View File

@@ -126,44 +126,70 @@
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
if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_CAR_HONK))
return
TIMER_COOLDOWN_START(src, COOLDOWN_CAR_HONK, 2 SECONDS)
vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] loudly honks!"))
to_chat(owner, span_notice("You press [vehicle_entered_target]'s horn."))
if(istype(vehicle_target.inserted_key, /obj/item/bikehorn))
vehicle_target.inserted_key.attack_self(owner) //The bikehorn plays a sound instead
return
playsound(vehicle_entered_target, hornsound, 75)
/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"
/datum/action/vehicle/sealed/dump_kidnapped_mobs
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>")
/datum/action/vehicle/sealed/dump_kidnapped_mobs/Trigger()
vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] starts dumping the people inside of it."))
vehicle_entered_target.DumpSpecificMobs(VEHICLE_CONTROL_KIDNAPPED)
/datum/action/vehicle/sealed/RollTheDice
name = "Press a colorful button"
/datum/action/vehicle/sealed/roll_the_dice
name = "Press Colorful Button"
desc = "Press one of those colorful buttons on your display panel!"
button_icon_state = "car_rtd"
/datum/action/vehicle/sealed/RollTheDice/Trigger()
if(istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target
C.RollTheDice(owner)
/datum/action/vehicle/sealed/roll_the_dice/Trigger()
if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
return
var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target
C.roll_the_dice(owner)
/datum/action/vehicle/sealed/cannon
name = "Toggle Siege Mode"
desc = "Destroy them with their own fodder!"
button_icon_state = "car_cannon"
/datum/action/vehicle/sealed/cannon/Trigger()
if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
return
var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target
C.toggle_cannon(owner)
/datum/action/vehicle/sealed/thank
name = "Thank the Clown Car Driver"
desc = "They're just doing their job."
button_icon_state = "car_thanktheclown"
COOLDOWN_DECLARE(thank_time_cooldown)
/datum/action/vehicle/sealed/thank/Trigger()
if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
return
if(!COOLDOWN_FINISHED(src, thank_time_cooldown))
return
COOLDOWN_START(src, thank_time_cooldown, 6 SECONDS)
var/obj/vehicle/sealed/car/clowncar/clown_car = vehicle_entered_target
var/mob/living/carbon/human/clown = pick(clown_car.return_drivers())
if(!clown)
return
owner.say("Thank you for the fun ride, [clown.name]!")
clown_car.increment_thanks_counter()
/datum/action/vehicle/ridden/scooter/skateboard/ollie
@@ -197,7 +223,9 @@
L.Move(landing_turf, vehicle_target.dir)
passtable_off(L, VEHICLE_TRAIT)
V.pass_flags &= ~PASSTABLE
if(locate(/obj/structure/table) in V.loc.contents)
if((locate(/obj/structure/table) in V.loc.contents) || (locate(/obj/structure/fluff/railing) in V.loc.contents))
if(locate(/obj/structure/fluff/railing) in V.loc.contents)
L.client.give_award(/datum/award/achievement/misc/tram_surfer, L)
V.grinding = TRUE
V.icon_state = "[V.board_icon]-grind"
addtimer(CALLBACK(V, /obj/vehicle/ridden/scooter/skateboard/.proc/grind), 2)