diff --git a/code/__DEFINES/cinematics.dm b/code/__DEFINES/cinematics.dm index 4bfc8dd3c4..22e0943802 100644 --- a/code/__DEFINES/cinematics.dm +++ b/code/__DEFINES/cinematics.dm @@ -8,4 +8,5 @@ #define CINEMATIC_CULT 8 #define CINEMATIC_NUKE_FAKE 9 #define CINEMATIC_NUKE_NO_CORE 10 -#define CINEMATIC_NUKE_FAR 11 \ No newline at end of file +#define CINEMATIC_NUKE_FAR 11 +#define CINEMATIC_NUKE_CLOWNOP 12 \ No newline at end of file diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index b67c084e10..750c107980 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -142,3 +142,7 @@ #define EMP_HEAVY 1 #define EMP_LIGHT 2 + +#define GRENADE_CLUMSY_FUMBLE 1 +#define GRENADE_NONCLUMSY_FUMBLE 2 +#define GRENADE_NO_FUMBLE 3 diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index f33f38cb70..2d088552bd 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -85,3 +85,16 @@ #define SUPERMATTER_DANGER 4 // Integrity < 50% #define SUPERMATTER_EMERGENCY 5 // Integrity < 25% #define SUPERMATTER_DELAMINATING 6 // Pretty obvious. + +//Nuclear bomb stuff +#define NUKESTATE_INTACT 5 +#define NUKESTATE_UNSCREWED 4 +#define NUKESTATE_PANEL_REMOVED 3 +#define NUKESTATE_WELDED 2 +#define NUKESTATE_CORE_EXPOSED 1 +#define NUKESTATE_CORE_REMOVED 0 + +#define NUKE_OFF_LOCKED 0 +#define NUKE_OFF_UNLOCKED 1 +#define NUKE_ON_TIMING 2 +#define NUKE_ON_EXPLODING 3 diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm index be7e6360aa..f5d65df110 100644 --- a/code/datums/cinematic.dm +++ b/code/datums/cinematic.dm @@ -51,7 +51,7 @@ GLOBAL_LIST_EMPTY(cinematics) for(var/A in GLOB.cinematics) var/datum/cinematic/C = A if(C == src) - continue + continue if(C.is_global || !is_global) return //Can't play two global or local cinematics at the same time @@ -73,7 +73,7 @@ GLOBAL_LIST_EMPTY(cinematics) if(is_global) M.notransform = TRUE locked += M - + //Actually play it content() //Cleanup @@ -209,6 +209,17 @@ GLOBAL_LIST_EMPTY(cinematics) cinematic_sound(sound('sound/effects/explosion_distant.ogg')) special() +/datum/cinematic/clownop + id = CINEMATIC_NUKE_CLOWNOP + cleanup_time = 100 + +/datum/cinematic/clownop/content() + flick("intro_nuke",screen) + sleep(35) + cinematic_sound(sound('sound/items/airhorn.ogg')) + flick("summary_selfdes",screen) //??? + special() + /* Intended usage. Nuke.Explosion() -> Cinematic(NUKE_BOOM,world) diff --git a/code/game/gamemodes/clown_ops/bananium_bomb.dm b/code/game/gamemodes/clown_ops/bananium_bomb.dm new file mode 100644 index 0000000000..86db2e94f9 --- /dev/null +++ b/code/game/gamemodes/clown_ops/bananium_bomb.dm @@ -0,0 +1,59 @@ +/obj/machinery/nuclearbomb/syndicate/bananium + name = "bananium fission explosive" + desc = "You probably shouldn't stick around to see if this is armed." + icon = 'icons/obj/machines/nuke.dmi' + icon_state = "bananiumbomb_base" + +/obj/machinery/nuclearbomb/syndicate/bananium/update_icon() + if(deconstruction_state == NUKESTATE_INTACT) + switch(get_nuke_state()) + if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED) + icon_state = "bananiumbomb_base" + update_icon_interior() + update_icon_lights() + if(NUKE_ON_TIMING) + cut_overlays() + icon_state = "bananiumbomb_timing" + if(NUKE_ON_EXPLODING) + cut_overlays() + icon_state = "bananiumbomb_exploding" + else + icon_state = "bananiumbomb_base" + update_icon_interior() + update_icon_lights() + +/obj/machinery/nuclearbomb/syndicate/bananium/get_cinematic_type(off_station) + switch(off_station) + if(0) + return CINEMATIC_NUKE_CLOWNOP + if(1) + return CINEMATIC_NUKE_MISS + if(2) + return CINEMATIC_NUKE_FAKE //it is farther away, so just a bikehorn instead of an airhorn + return CINEMATIC_NUKE_FAKE + +/obj/machinery/nuclearbomb/syndicate/bananium/really_actually_explode(off_station) + Cinematic(get_cinematic_type(off_station), world) + for(var/mob/living/carbon/human/H in GLOB.carbon_list) + var/turf/T = get_turf(H) + if(!T || T.z != z) + continue + H.Stun(10) + var/obj/item/clothing/C + if(!H.w_uniform || H.dropItemToGround(H.w_uniform)) + C = new /obj/item/clothing/under/rank/clown(H) + C.flags_1 |= NODROP_1 //mwahaha + H.equip_to_slot_or_del(C, slot_w_uniform) + + if(!H.shoes || H.dropItemToGround(H.shoes)) + C = new /obj/item/clothing/shoes/clown_shoes(H) + C.flags_1 |= NODROP_1 + H.equip_to_slot_or_del(C, slot_shoes) + + if(!H.wear_mask || H.dropItemToGround(H.wear_mask)) + C = new /obj/item/clothing/mask/gas/clown_hat(H) + C.flags_1 |= NODROP_1 + H.equip_to_slot_or_del(C, slot_wear_mask) + + H.dna.add_mutation(CLOWNMUT) + H.gain_trauma(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_LOBOTOMY, "clowns") //MWA HA HA diff --git a/code/game/gamemodes/clown_ops/clown_ops.dm b/code/game/gamemodes/clown_ops/clown_ops.dm new file mode 100644 index 0000000000..6b96cefa13 --- /dev/null +++ b/code/game/gamemodes/clown_ops/clown_ops.dm @@ -0,0 +1,66 @@ +/datum/game_mode/nuclear/clown_ops + name = "clown ops" + config_tag = "clownops" + + announce_span = "danger" + announce_text = "Clown empire forces are approaching the station in an attempt to HONK it!\n\ + Operatives: Secure the nuclear authentication disk and use your bananium fission explosive to HONK the station.\n\ + Crew: Defend the nuclear authentication disk and ensure that it leaves with you on the emergency shuttle." + + operative_antag_datum_type = /datum/antagonist/nukeop/clownop + leader_antag_datum_type = /datum/antagonist/nukeop/leader/clownop + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +/datum/game_mode/nuclear/clown_ops/pre_setup() + . = ..() + if(.) + for(var/obj/machinery/nuclearbomb/syndicate/S in GLOB.nuke_list) + var/turf/T = get_turf(S) + if(T) + qdel(S) + new /obj/machinery/nuclearbomb/syndicate/bananium(T) + for(var/V in pre_nukeops) + var/datum/mind/the_op = V + the_op.assigned_role = "Clown Operative" + the_op.special_role = "Clown Operative" + +/datum/game_mode/nuclear/clown_ops/generate_report() + return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ + transport containing a bananium fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \ + can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." + + +/datum/outfit/syndicate/clownop + name = "Clown Operative - Basic" + uniform = /obj/item/clothing/under/syndicate + shoes = /obj/item/clothing/shoes/clown_shoes/combat + mask = /obj/item/clothing/mask/gas/clown_hat + gloves = /obj/item/clothing/gloves/combat + back = /obj/item/storage/backpack/clown + ears = /obj/item/device/radio/headset/syndicate/alt + l_pocket = /obj/item/pinpointer/nuke/syndicate + r_pocket = /obj/item/bikehorn + id = /obj/item/card/id/syndicate + backpack_contents = list(/obj/item/storage/box/syndie=1,\ + /obj/item/kitchen/knife/combat/survival, + /obj/item/reagent_containers/spray/waterflower/lube) + implants = list(/obj/item/implant/sad_trombone) + + uplink_type = /obj/item/device/radio/uplink/clownop + +/datum/outfit/syndicate/clownop/no_crystals + tc = 0 + +/datum/outfit/syndicate/clownop/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + ..() + if(visualsOnly) + return + H.dna.add_mutation(CLOWNMUT) + +/datum/outfit/syndicate/clownop/leader + name = "Clown Operative Leader - Basic" + id = /obj/item/card/id/syndicate/nuke_leader + r_hand = /obj/item/device/nuclear_challenge/clownops + command_radio = TRUE diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm new file mode 100644 index 0000000000..3b74d796be --- /dev/null +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -0,0 +1,298 @@ +/obj/item/reagent_containers/spray/waterflower/lube + name = "water flower" + desc = "A seemingly innocent sunflower...with a twist. A slippery twist." + icon = 'icons/obj/hydroponics/harvest.dmi' + icon_state = "sunflower" + item_state = "sunflower" + amount_per_transfer_from_this = 3 + spray_range = 1 + stream_range = 1 + volume = 30 + list_reagents = list("lube" = 30) + +//COMBAT CLOWN SHOES +//Clown shoes with combat stats and noslip. Of course they still squeek. +/obj/item/clothing/shoes/clown_shoes/combat + name = "combat clown shoes" + desc = "advanced clown shoes that protect the wearer and render them nearly immune to slipping on their own peels. They also squeek at 100% capacity." + flags_1 = NOSLIP_1 + slowdown = SHOES_SLOWDOWN + armor = list("melee" = 25, "bullet" = 25, "laser" = 25, "energy" = 25, "bomb" = 50, "bio" = 10, "rad" = 0, "fire" = 70, "acid" = 50) + strip_delay = 70 + resistance_flags = NONE + permeability_coefficient = 0.05 + pockets = /obj/item/storage/internal/pocket/shoes + +//The super annoying version +/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat + name = "mk-honk combat shoes" + desc = "The culmination of years of clown combat research, these shoes leave a trail of chaos in their wake. They will slowly recharge themselves over time, or can be manually charged with bananium." + slowdown = SHOES_SLOWDOWN + armor = list("melee" = 25, "bullet" = 25, "laser" = 25, "energy" = 25, "bomb" = 50, "bio" = 10, "rad" = 0, "fire" = 70, "acid" = 50) + strip_delay = 70 + resistance_flags = NONE + permeability_coefficient = 0.05 + pockets = /obj/item/storage/internal/pocket/shoes + always_noslip = TRUE + var/max_recharge = 3000 //30 peels worth + var/recharge_rate = 34 //about 1/3 of a peel per tick + +/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/Initialize() + . = ..() + GET_COMPONENT(bananium, /datum/component/material_container) + bananium.insert_amount(max_recharge, MAT_BANANIUM) + START_PROCESSING(SSobj, src) + +/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/process() + GET_COMPONENT(bananium, /datum/component/material_container) + var/bananium_amount = bananium.amount(MAT_BANANIUM) + if(bananium_amount < max_recharge) + bananium.insert_amount(min(recharge_rate, max_recharge - bananium_amount), MAT_BANANIUM) + +/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/attack_self(mob/user) + ui_action_click(user) + +//BANANIUM SWORD + +/obj/item/melee/transforming/energy/sword/bananium + name = "bananium sword" + desc = "An elegant weapon, for a more civilized age." + force = 0 + throwforce = 0 + force_on = 0 + throwforce_on = 0 + hitsound = null + attack_verb_on = list("slipped") + clumsy_check = FALSE + sharpness = IS_BLUNT + item_color = "yellow" + heat = 0 + light_color = "#ffff00" + var/next_trombone_allowed = 0 + +/obj/item/melee/transforming/energy/sword/bananium/Initialize() + . = ..() + AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.enabled = active + +/obj/item/melee/transforming/energy/sword/bananium/attack(mob/living/M, mob/living/user) + ..() + if(active) + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.Slip(M) + +/obj/item/melee/transforming/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum) + . = ..() + if(active) + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.Slip(hit_atom) + +/obj/item/melee/transforming/energy/sword/bananium/attackby(obj/item/I, mob/living/user, params) + if((world.time > next_trombone_allowed) && istype(I, /obj/item/melee/transforming/energy/sword/bananium)) + next_trombone_allowed = world.time + 50 + to_chat(user, "You slap the two swords together. Sadly, they do not seem to fit.") + playsound(src, 'sound/misc/sadtrombone.ogg', 50) + return TRUE + return ..() + +/obj/item/melee/transforming/energy/sword/bananium/transform_weapon(mob/living/user, supress_message_text) + ..() + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.enabled = active + +/obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user) + return "" + +/obj/item/melee/transforming/energy/sword/bananium/suicide_act(mob/user) + if(!active) + transform_weapon(user, TRUE) + user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku, but the blade slips off of them harmlessly!") + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.Slip(user) + return SHAME + +//BANANIUM SHIELD + +/obj/item/shield/energy/bananium + name = "bananium energy shield" + desc = "A shield that stops most melee attacks, protects user from almost all energy projectiles, and can be thrown to slip opponents." + throw_speed = 1 + clumsy_check = 0 + base_icon_state = "bananaeshield" + force = 0 + throwforce = 0 + throw_range = 5 + on_force = 0 + on_throwforce = 0 + on_throw_speed = 1 + +/obj/item/shield/energy/bananium/Initialize() + . = ..() + AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.enabled = active + +/obj/item/shield/energy/bananium/attack_self(mob/living/carbon/human/user) + ..() + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.enabled = active + +/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1) + if(active) + if(iscarbon(thrower)) + var/mob/living/carbon/C = thrower + C.throw_mode_on() //so they can catch it on the return. + return ..() + +/obj/item/shield/energy/bananium/throw_impact(atom/hit_atom) + if(active) + var/caught = hit_atom.hitby(src, 0, 0) + if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it + GET_COMPONENT(slipper, /datum/component/slippery) + slipper.Slip(hit_atom) + if(thrownby && !caught) + throw_at(thrownby, throw_range+2, throw_speed, null, 1) + else + return ..() + + +//BOMBANANA + +/obj/item/reagent_containers/food/snacks/grown/banana/bombanana + trash = /obj/item/grown/bananapeel/bombanana + bitesize = 1 + customfoodfilling = FALSE + seed = null + tastes = list("explosives" = 10) + list_reagents = list("vitamin" = 1) + +/obj/item/grown/bananapeel/bombanana + desc = "A peel from a banana. Why is it beeping?" + seed = null + var/det_time = 50 + var/obj/item/grenade/syndieminibomb/bomb + +/obj/item/grown/bananapeel/bombanana/Initialize() + . = ..() + AddComponent(/datum/component/slippery, det_time) + bomb = new /obj/item/grenade/syndieminibomb(src) + bomb.det_time = det_time + if(iscarbon(loc)) + to_chat(loc, "[src] begins to beep.") + var/mob/living/carbon/C = loc + C.throw_mode_on() + bomb.preprime(loc, null, FALSE) + +/obj/item/grown/bananapeel/bombanana/Destroy() + . = ..() + QDEL_NULL(bomb) + +/obj/item/grown/bananapeel/bombanana/suicide_act(mob/user) + user.visible_message("[user] is deliberately slipping on the [src.name]! It looks like \he's trying to commit suicide.") + playsound(loc, 'sound/misc/slip.ogg', 50, 1, -1) + bomb.preprime(user, 0, FALSE) + return (BRUTELOSS) + +//TEARSTACHE GRENADE + +/obj/item/grenade/chem_grenade/teargas/moustache + name = "tear-stache grenade" + desc = "A handsomely-attired teargas grenade." + icon_state = "moustacheg" + clumsy_check = GRENADE_NONCLUMSY_FUMBLE + +/obj/item/grenade/chem_grenade/teargas/moustache/prime() + var/myloc = get_turf(src) + . = ..() + for(var/mob/living/carbon/M in view(6, myloc)) + if(!istype(M.wear_mask, /obj/item/clothing/mask/gas/clown_hat) && !istype(M.wear_mask, /obj/item/clothing/mask/gas/mime) ) + if(!M.wear_mask || M.dropItemToGround(M.wear_mask)) + var/obj/item/clothing/mask/fakemoustache/sticky/the_stash = new /obj/item/clothing/mask/fakemoustache/sticky() + M.equip_to_slot_or_del(the_stash, slot_wear_mask, TRUE, TRUE, TRUE, TRUE) + +/obj/item/clothing/mask/fakemoustache/sticky + var/unstick_time = 600 + +/obj/item/clothing/mask/fakemoustache/sticky/Initialize() + . = ..() + flags_1 |= NODROP_1 + addtimer(CALLBACK(src, .proc/unstick), unstick_time) + +/obj/item/clothing/mask/fakemoustache/sticky/proc/unstick() + flags_1 &= ~NODROP_1 + +//DARK H.O.N.K. AND CLOWN MECH WEAPONS + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/bombanana + name = "bombanana mortar" + desc = "Equipment for clown exosuits. Launches exploding banana peels." + icon_state = "mecha_bananamrtr" + projectile = /obj/item/grown/bananapeel/bombanana + projectiles = 8 + projectile_energy_cost = 1000 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/bombanana/can_attach(obj/mecha/combat/honker/M) + if(..()) + if(istype(M)) + return TRUE + return FALSE + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/tearstache + name = "\improper HONKeR-6 grenade launcher" + desc = "A weapon for combat exosuits. Launches primed tear-stache grenades." + icon_state = "mecha_grenadelnchr" + projectile = /obj/item/grenade/chem_grenade/teargas/moustache + fire_sound = 'sound/weapons/grenadelaunch.ogg' + projectiles = 6 + missile_speed = 1.5 + projectile_energy_cost = 800 + equip_cooldown = 60 + det_time = 20 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/tearstache/can_attach(obj/mecha/combat/honker/M) + if(..()) + if(istype(M)) + return TRUE + return FALSE + +/obj/mecha/combat/honker/dark + desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. This one has been painted black for maximum fun. HONK!" + name = "\improper Dark H.O.N.K" + icon_state = "darkhonker" + max_integrity = 300 + deflect_chance = 15 + armor = list("melee" = 40, "bullet" = 40, "laser" = 50, "energy" = 35, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + max_temperature = 35000 + operation_req_access = list(ACCESS_SYNDICATE) + wreckage = /obj/structure/mecha_wreckage/honker/dark + max_equip = 3 + +/obj/mecha/combat/honker/dark/GrantActions(mob/living/user, human_occupant = 0) + ..() + thrusters_action.Grant(user, src) + + +/obj/mecha/combat/honker/dark/RemoveActions(mob/living/user, human_occupant = 0) + ..() + thrusters_action.Remove(user) + +/obj/mecha/combat/honker/dark/add_cell(obj/item/stock_parts/cell/C) + if(C) + C.forceMove(src) + cell = C + return + cell = new /obj/item/stock_parts/cell/hyper(src) + +/obj/mecha/combat/honker/dark/loaded/Initialize() + . = ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/honker() + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/bombanana()//Needed more offensive weapons. + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/tearstache()//The mousetrap mortar was not up-to-snuff. + ME.attach(src) + +/obj/structure/mecha_wreckage/honker/dark + name = "\improper Dark H.O.N.K wreckage" + icon_state = "darkhonker-broken" diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index c6857cd222..11e4815722 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -19,6 +19,9 @@ var/datum/team/nuclear/nuke_team + var/operative_antag_datum_type = /datum/antagonist/nukeop + var/leader_antag_datum_type = /datum/antagonist/nukeop/leader + /datum/game_mode/nuclear/pre_setup() var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible) if(n_agents >= required_enemies) @@ -37,12 +40,12 @@ /datum/game_mode/nuclear/post_setup() //Assign leader var/datum/mind/leader_mind = pre_nukeops[1] - var/datum/antagonist/nukeop/L = leader_mind.add_antag_datum(/datum/antagonist/nukeop/leader) + var/datum/antagonist/nukeop/L = leader_mind.add_antag_datum(leader_antag_datum_type) nuke_team = L.nuke_team //Assign the remaining operatives for(var/i = 2 to pre_nukeops.len) var/datum/mind/nuke_mind = pre_nukeops[i] - nuke_mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team) + nuke_mind.add_antag_datum(operative_antag_datum_type) return ..() /datum/game_mode/nuclear/OnNukeExplosion(off_station) @@ -131,6 +134,7 @@ var/tc = 25 var/command_radio = FALSE + var/uplink_type = /obj/item/device/radio/uplink/nuclear /datum/outfit/syndicate/leader @@ -150,7 +154,7 @@ R.command = TRUE if(tc) - var/obj/item/device/radio/uplink/nuclear/U = new(H, H.key, tc) + var/obj/item/device/radio/uplink/U = new uplink_type(H, H.key, tc) H.equip_to_slot_or_del(U, slot_in_backpack) var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H) diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 15c532d378..97b8a95277 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -11,7 +11,7 @@ var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff) var/energy_drain = 0 var/obj/mecha/chassis = null - var/range = MELEE //bitflags + var/range = MELEE //bitFflags var/salvageable = 1 var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates var/pacifist_safe = TRUE //Controls if equipment can be used to attack by a pacifist. diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm index d3b7a19ba6..93349a6b3b 100644 --- a/code/game/objects/items/grenades/grenade.dm +++ b/code/game/objects/items/grenades/grenade.dm @@ -16,6 +16,7 @@ var/active = 0 var/det_time = 50 var/display_timer = 1 + var/clumsy_check = GRENADE_CLUMSY_FUMBLE /obj/item/grenade/suicide_act(mob/living/carbon/user) user.visible_message("[user] primes [src], then eats it! It looks like [user.p_theyre()] trying to commit suicide!") @@ -32,8 +33,14 @@ qdel(src) /obj/item/grenade/proc/clown_check(mob/living/carbon/human/user) - if(user.has_trait(TRAIT_CLUMSY) && prob(50)) - to_chat(user, "Huh? How does this thing work?") + var/clumsy = user.has_trait(TRAIT_CLUMSY) + if(clumsy && (clumsy_check == GRENADE_CLUMSY_FUMBLE)) + if(prob(50)) + to_chat(user, "Huh? How does this thing work?") + preprime(user, 5, FALSE) + return FALSE + else if(!clumsy && (clumsy_check == GRENADE_NONCLUMSY_FUMBLE)) + to_chat(user, "You pull the pin on [src]. Attached to it is a pink ribbon that says, \"HONK\"") preprime(user, 5, FALSE) return FALSE return TRUE diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index 74ac616646..c25a9a2852 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -17,6 +17,8 @@ return ..() /obj/item/melee/transforming/energy/suicide_act(mob/user) + if(!active) + transform_weapon(user, TRUE) user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku!") return (BRUTELOSS|FIRELOSS) diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm index db8e791700..74eb048d8a 100644 --- a/code/game/objects/items/melee/transforming.dm +++ b/code/game/objects/items/melee/transforming.dm @@ -1,4 +1,5 @@ /obj/item/melee/transforming + sharpness = IS_SHARP var/active = FALSE var/force_on = 30 //force when active var/faction_bonus_force = 0 //Bonus force dealt against certain factions @@ -8,10 +9,10 @@ var/list/attack_verb_on = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") var/list/attack_verb_off = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") w_class = WEIGHT_CLASS_SMALL - sharpness = IS_SHARP var/bonus_active = FALSE //If the faction damage bonus is active var/list/nemesis_factions //Any mob with a faction that exists in this list will take bonus damage/effects var/w_class_on = WEIGHT_CLASS_BULKY + var/clumsy_check = TRUE /obj/item/melee/transforming/Initialize() . = ..() @@ -81,6 +82,6 @@ to_chat(user, "[src] [active ? "is now active":"can now be concealed"].") /obj/item/melee/transforming/proc/clumsy_transform_effect(mob/living/user) - if(user.has_trait(TRAIT_CLUMSY) && prob(50)) + if(clumsy_check && user.has_trait(TRAIT_CLUMSY) && prob(50)) to_chat(user, "You accidentally cut yourself with [src], like a doofus!") user.take_bodypart_damage(5,5) diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 628ffe4de0..dd8d8f8a10 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -60,16 +60,24 @@ name = "energy combat shield" desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere." icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "eshield0" // eshield1 for expanded lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' + w_class = WEIGHT_CLASS_TINY + attack_verb = list("shoved", "bashed") + throw_range = 5 force = 3 throwforce = 3 throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_TINY - attack_verb = list("shoved", "bashed") + var/base_icon_state = "eshield" // [base_icon_state]1 for expanded, [base_icon_state]0 for contracted + var/on_force = 10 + var/on_throwforce = 8 + var/on_throw_speed = 2 var/active = 0 + var/clumsy_check = TRUE + +/obj/item/shield/energy/Initialize() + . = ..() + icon_state = "[base_icon_state]0" /obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) return 0 @@ -78,23 +86,23 @@ return (active) /obj/item/shield/energy/attack_self(mob/living/carbon/human/user) - if(user.has_trait(TRAIT_CLUMSY) && prob(50)) + if(clumsy_check && user.has_trait(TRAIT_CLUMSY) && prob(50)) to_chat(user, "You beat yourself in the head with [src].") user.take_bodypart_damage(5) active = !active - icon_state = "eshield[active]" + icon_state = "[base_icon_state][active]" if(active) - force = 10 - throwforce = 8 - throw_speed = 2 + force = on_force + throwforce = on_throwforce + throw_speed = on_throw_speed w_class = WEIGHT_CLASS_BULKY playsound(user, 'sound/weapons/saberon.ogg', 35, 1) to_chat(user, "[src] is now active.") else - force = 3 - throwforce = 3 - throw_speed = 3 + force = initial(force) + throwforce = initial(throwforce) + throw_speed = initial(throw_speed) w_class = WEIGHT_CLASS_TINY playsound(user, 'sound/weapons/saberoff.ogg', 35, 1) to_chat(user, "[src] can now be concealed.") diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index 6c723e96ec..0a000c4bf0 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -73,7 +73,7 @@ C.prefs.copy_to(M) M.key = C.key var/datum/mind/app_mind = M.mind - + var/datum/antagonist/wizard/apprentice/app = new() app.master = user app.school = kind @@ -145,6 +145,26 @@ M.mind.add_antag_datum(new_op,creator_op.nuke_team) M.mind.special_role = "Nuclear Operative" +//////CLOWN OP +/obj/item/antag_spawner/nuke_ops/clown + name = "clown operative teleporter" + desc = "A single-use teleporter designed to quickly reinforce clown operatives in the field." + +/obj/item/antag_spawner/nuke_ops/clown/spawn_antag(client/C, turf/T, kind, datum/mind/user) + var/mob/living/carbon/human/M = new/mob/living/carbon/human(T) + C.prefs.copy_to(M) + M.key = C.key + + var/datum/antagonist/nukeop/clownop/new_op = new /datum/antagonist/nukeop/clownop() + new_op.send_to_spawnpoint = FALSE + new_op.nukeop_outfit = /datum/outfit/syndicate/clownop/no_crystals + + var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop/clownop,TRUE) + if(creator_op) + M.mind.add_antag_datum(new_op, creator_op.nuke_team) + M.mind.special_role = "Clown Operative" + + //////SYNDICATE BORG /obj/item/antag_spawner/nuke_ops/borg_tele name = "syndicate cyborg teleporter" @@ -187,7 +207,7 @@ R.real_name = R.name R.key = C.key - + var/datum/antagonist/nukeop/new_borg = new() new_borg.send_to_spawnpoint = FALSE R.mind.add_antag_datum(new_borg,creator_op.nuke_team) diff --git a/code/modules/antagonists/nukeop/clownop.dm b/code/modules/antagonists/nukeop/clownop.dm new file mode 100644 index 0000000000..43e62c4638 --- /dev/null +++ b/code/modules/antagonists/nukeop/clownop.dm @@ -0,0 +1,25 @@ + +/datum/antagonist/nukeop/clownop + name = "Clown Operative" + roundend_category = "clown operatives" + antagpanel_category = "ClownOp" + nukeop_outfit = /datum/outfit/syndicate/clownop + +/datum/antagonist/nukeop/leader/clownop + name = "Clown Operative Leader" + roundend_category = "clown operatives" + antagpanel_category = "ClownOp" + nukeop_outfit = /datum/outfit/syndicate/clownop/leader + +/datum/antagonist/nukeop/leader/clownop/give_alias() + title = pick("Head Honker", "Slipmaster", "Clown King", "Honkbearer") + if(nuke_team && nuke_team.syndicate_name) + owner.current.real_name = "[nuke_team.syndicate_name] [title]" + else + owner.current.real_name = "Syndicate [title]" + +/datum/antagonist/nukeop/clownop/admin_add(datum/mind/new_owner,mob/admin) + new_owner.assigned_role = "Clown Operative" + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has clown op'ed [new_owner.current].") + log_admin("[key_name(admin)] has clown op'ed [new_owner.current].") diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm index 03a76f19a1..931c38d7b9 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm @@ -15,6 +15,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) Such a brazen move will attract the attention of powerful benefactors within the Syndicate, who will supply your team with a massive amount of bonus telecrystals. \ Must be used within five minutes, or your benefactors will lose interest." var/declaring_war = FALSE + var/uplink_type = /obj/item/device/radio/uplink/nuclear /obj/item/device/nuclear_challenge/attack_self(mob/living/user) if(!check_allowed(user)) @@ -59,7 +60,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec) D.jammed = TRUE - new /obj/item/device/radio/uplink/nuclear(get_turf(user), user.key, CHALLENGE_TELECRYSTALS) + new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS) CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY)) SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1) @@ -85,6 +86,9 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) return FALSE return TRUE +/obj/item/device/nuclear_challenge/clownops + uplink_type = /obj/item/device/radio/uplink/clownop + #undef CHALLENGE_TELECRYSTALS #undef CHALLENGE_TIME_LIMIT #undef CHALLENGE_MIN_PLAYERS diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index e540525405..3a4d200c59 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -1,16 +1,3 @@ -#define NUKESTATE_INTACT 5 -#define NUKESTATE_UNSCREWED 4 -#define NUKESTATE_PANEL_REMOVED 3 -#define NUKESTATE_WELDED 2 -#define NUKESTATE_CORE_EXPOSED 1 -#define NUKESTATE_CORE_REMOVED 0 - -#define NUKE_OFF_LOCKED 0 -#define NUKE_OFF_UNLOCKED 1 -#define NUKE_ON_TIMING 2 -#define NUKE_ON_EXPLODING 3 - - /obj/machinery/nuclearbomb name = "nuclear fission explosive" desc = "You probably shouldn't stick around to see if this is armed." @@ -59,9 +46,8 @@ set_safety() GLOB.poi_list -= src GLOB.nuke_list -= src - if(countdown) - qdel(countdown) - countdown = null + QDEL_NULL(countdown) + QDEL_NULL(core) . = ..() /obj/machinery/nuclearbomb/examine(mob/user) @@ -459,11 +445,13 @@ //Cinematic SSticker.mode.OnNukeExplosion(off_station) - var/bombz = z - Cinematic(get_cinematic_type(off_station),world,CALLBACK(SSticker,/datum/controller/subsystem/ticker/proc/station_explosion_detonation,src)) - INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel,bombz) + really_actually_explode(off_station) SSticker.roundend_check_paused = FALSE +/obj/machinery/nuclearbomb/proc/really_actually_explode(off_station) + Cinematic(get_cinematic_type(off_station),world,CALLBACK(SSticker,/datum/controller/subsystem/ticker/proc/station_explosion_detonation,src)) + INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel, z) + /obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station) if(off_station < 2) return CINEMATIC_SELFDESTRUCT diff --git a/code/modules/clothing/shoes/bananashoes.dm b/code/modules/clothing/shoes/bananashoes.dm index 561b0c15d7..7ffd9c1f40 100644 --- a/code/modules/clothing/shoes/bananashoes.dm +++ b/code/modules/clothing/shoes/bananashoes.dm @@ -4,25 +4,30 @@ name = "mk-honk prototype shoes" desc = "Lost prototype of advanced clown tech. Powered by bananium, these shoes leave a trail of chaos in their wake." icon_state = "clown_prototype_off" - var/on = FALSE actions_types = list(/datum/action/item_action/toggle) + var/on = FALSE + var/always_noslip = FALSE /obj/item/clothing/shoes/clown_shoes/banana_shoes/Initialize() . = ..() AddComponent(/datum/component/material_container, list(MAT_BANANIUM), 200000, TRUE) AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 75) + if(always_noslip) + flags_1 |= NOSLIP_1 /obj/item/clothing/shoes/clown_shoes/banana_shoes/step_action() . = ..() + GET_COMPONENT(bananium, /datum/component/material_container) if(on) - new/obj/item/grown/bananapeel/specialpeel(get_step(src,turn(usr.dir, 180))) //honk - GET_COMPONENT(bananium, /datum/component/material_container) - bananium.use_amount_type(100, MAT_BANANIUM) if(bananium.amount(MAT_BANANIUM) < 100) on = !on - flags_1 &= ~NOSLIP_1 + if(!always_noslip) + flags_1 &= ~NOSLIP_1 update_icon() to_chat(loc, "You ran out of bananium!") + else + new /obj/item/grown/bananapeel/specialpeel(get_step(src,turn(usr.dir, 180))) //honk + bananium.use_amount_type(100, MAT_BANANIUM) /obj/item/clothing/shoes/clown_shoes/banana_shoes/attack_self(mob/user) GET_COMPONENT(bananium, /datum/component/material_container) @@ -42,10 +47,11 @@ on = !on update_icon() to_chat(user, "You [on ? "activate" : "deactivate"] the prototype shoes.") - if(on) - flags_1 |= NOSLIP_1 - else - flags_1 &= ~NOSLIP_1 + if(!always_noslip) + if(on) + flags_1 |= NOSLIP_1 + else + flags_1 &= ~NOSLIP_1 else to_chat(user, "You need bananium to turn the prototype shoes on!") diff --git a/code/modules/projectiles/guns/ballistic/toy.dm b/code/modules/projectiles/guns/ballistic/toy.dm index 93a210879e..44b0a70dd5 100644 --- a/code/modules/projectiles/guns/ballistic/toy.dm +++ b/code/modules/projectiles/guns/ballistic/toy.dm @@ -54,7 +54,7 @@ force = 0 throwforce = 0 mag_type = /obj/item/ammo_box/magazine/internal/shot/toy - clumsy_check = 0 + clumsy_check = FALSE item_flags = NONE casing_ejector = FALSE can_suppress = FALSE @@ -87,6 +87,7 @@ item_flags = NONE mag_type = /obj/item/ammo_box/magazine/toy/smgm45/riot casing_ejector = FALSE + clumsy_check = FALSE /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted //Use this for actual toys pin = /obj/item/device/firing_pin @@ -103,6 +104,7 @@ item_flags = NONE mag_type = /obj/item/ammo_box/magazine/toy/m762/riot casing_ejector = FALSE + clumsy_check = FALSE /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted //Use this for actual toys pin = /obj/item/device/firing_pin diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm index 737f92a9ef..0220c4d179 100644 --- a/code/modules/uplink/uplink_devices.dm +++ b/code/modules/uplink/uplink_devices.dm @@ -12,6 +12,11 @@ GET_COMPONENT(hidden_uplink, /datum/component/uplink) hidden_uplink.set_gamemode(/datum/game_mode/nuclear) +/obj/item/device/radio/uplink/clownop/Initialize() + . = ..() + GET_COMPONENT(hidden_uplink, /datum/component/uplink) + hidden_uplink.set_gamemode(/datum/game_mode/nuclear/clown_ops) + /obj/item/device/multitool/uplink/Initialize(mapload, _owner, _tc_amount = 20) . = ..() AddComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount) diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index e3da5aba80..cc1d1d2a47 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -157,6 +157,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) with suppressors." item = /obj/item/gun/ballistic/automatic/pistol cost = 7 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/revolver name = "Syndicate Revolver" @@ -164,6 +165,15 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/gun/ballistic/revolver cost = 13 surplus = 50 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + +/datum/uplink_item/dangerous/pie_cannon + name = "Banana Cream Pie Cannon" + desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!" + cost = 10 + item = /obj/item/pneumatic_cannon/pie/selfcharge + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/shotgun name = "Bulldog Shotgun" @@ -243,6 +253,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) pocketed when inactive. Activating it produces a loud, distinctive noise." item = /obj/item/melee/transforming/energy/sword/saber cost = 8 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + +/datum/uplink_item/dangerous/clownsword + name = "Bananium Energy Sword" + desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \ + impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it." + item = /obj/item/melee/transforming/energy/sword/bananium + cost = 3 + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/doublesword name = "Double-Bladed Energy Sword" @@ -251,6 +271,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/twohanded/dualsaber player_minimum = 25 cost = 16 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/doublesword/get_discount() return pick(4;0.8,2;0.65,1;0.5) @@ -277,6 +298,25 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) in addition to dealing high amounts of damage to nearby personnel." item = /obj/item/grenade/syndieminibomb cost = 6 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + +/datum/uplink_item/dangerous/bombanana + name = "Bombanana" + desc = "A banana with an explosive taste! discard the peel quickly, as it will explode with the force of a syndicate minibomb \ + a few seconds after the banana is eaten." + item = /obj/item/reagent_containers/food/snacks/grown/banana/bombanana + cost = 4 //it is a bit cheaper than a minibomb because you have to take off your helmet to eat it, which is how you arm it + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) + +/datum/uplink_item/dangerous/tearstache + name = "Teachstache Grenade" + desc = "A teargas grenade that launches sticky moustaches onto the face of anyone not wearing a clown or mime mask. The moustaches will \ + remain attached to the face of all targets for one minute, preventing the use of breath masks and other such devices." + item = /obj/item/grenade/chem_grenade/teargas/moustache + cost = 3 + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/foamsmg name = "Toy Submachine Gun" @@ -284,7 +324,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/gun/ballistic/automatic/c20r/toy cost = 5 surplus = 0 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/foammachinegun name = "Toy Machine Gun" @@ -293,7 +333,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/gun/ballistic/automatic/l6_saw/toy cost = 10 surplus = 0 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/viscerators name = "Viscerator Delivery Grenade" @@ -302,7 +342,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/grenade/spawnergrenade/manhacks cost = 5 surplus = 35 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/bioterrorfoam name = "Chemical Foam Grenade" @@ -312,7 +352,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/grenade/chem_grenade/bioterrorfoam cost = 5 surplus = 35 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/bioterror name = "Biohazardous Chemical Sprayer" @@ -322,7 +362,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/reagent_containers/spray/chemsprayer/bioterror cost = 20 surplus = 0 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/stealthy_weapons/virus_grenade name = "Fungal Tuberculosis Grenade" @@ -332,7 +372,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/storage/box/syndie_kit/tuberculosisgrenade cost = 12 surplus = 35 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/guardian name = "Holoparasites" @@ -341,7 +381,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/storage/box/syndie_kit/guardian cost = 18 surplus = 0 - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) player_minimum = 25 // Ammunition @@ -355,24 +395,28 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) are dirt cheap but are half as effective as .357 rounds." item = /obj/item/ammo_box/magazine/m10mm cost = 1 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/ammo/pistolap name = "10mm Armour Piercing Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. These rounds are less effective at injuring the target but penetrate protective gear." item = /obj/item/ammo_box/magazine/m10mm/ap cost = 2 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/ammo/pistolfire name = "10mm Incendiary Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with incendiary rounds which ignite the target." item = /obj/item/ammo_box/magazine/m10mm/fire cost = 2 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/ammo/pistolhp name = "10mm Hollow Point Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. These rounds are more damaging but ineffective against armour." item = /obj/item/ammo_box/magazine/m10mm/hp cost = 3 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/ammo/pistolaps name = "9mm Handgun Magazine" @@ -394,6 +438,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) For when you really need a lot of things dead." item = /obj/item/ammo_box/a357 cost = 4 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/ammo/shotgun cost = 2 @@ -517,7 +562,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) and broca systems, making it impossible for them to move or speak for some time." item = /obj/item/storage/box/syndie_kit/bioterror cost = 6 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) //Support and Mechs /datum/uplink_item/support @@ -532,6 +577,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/antag_spawner/nuke_ops cost = 25 refundable = TRUE + include_modes = list(/datum/game_mode/nuclear) /datum/uplink_item/support/reinforcement/assault_borg name = "Syndicate Assault Cyborg" @@ -562,6 +608,20 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/mecha/combat/marauder/mauler/loaded cost = 140 +/datum/uplink_item/support/honker + name = "Dark H.O.N.K." + desc = "A clown combat mech equipped with bombanana peel and tearstache grenade launchers, as well as the ubiquitous HoNkER BlAsT 5000." + item = /obj/mecha/combat/honker/dark/loaded + cost = 80 + include_modes = list(/datum/game_mode/nuclear/clown_ops) + +/datum/uplink_item/support/clown_reinforcement + name = "Clown Reinforcements" + desc = "Call in an additional clown to share the fun, equipped with full starting gear, but no telecrystals." + item = /obj/item/antag_spawner/nuke_ops/clown + cost = 20 + include_modes = list(/datum/game_mode/nuclear/clown_ops) + // Stealthy Weapons /datum/uplink_item/stealthy_weapons category = "Stealthy and Inconspicuous Weapons" @@ -573,13 +633,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/sleeping_carp_scroll cost = 17 surplus = 0 - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/stealthy_weapons/cqc name = "CQC Manual" desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing." item = /obj/item/cqc_manual - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) cost = 13 surplus = 0 @@ -661,6 +721,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/suppressor cost = 3 surplus = 10 + exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/stealthy_weapons/pizza_bomb name = "Pizza Bomb" @@ -700,7 +761,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) They do not work on heavily lubricated surfaces." item = /obj/item/clothing/shoes/chameleon/noslip cost = 2 - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) player_minimum = 20 /datum/uplink_item/stealthy_tools/syndigaloshes/nuke @@ -709,6 +770,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) exclude_modes = list() include_modes = list(/datum/game_mode/nuclear) +/datum/uplink_item/stealthy_tools/combatbananashoes + name = "Combat Banana Shoes" + desc = "While making the wearer immune to most slipping attacks like regular combat clown shoes, these shoes \ + can generate a large number of synthetic banana peels as the wearer walks, slipping up would-be pursuers. They also \ + squeek significantly louder." + item = /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat + cost = 6 + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) + /datum/uplink_item/stealthy_tools/frame name = "F.R.A.M.E. PDA Cartridge" desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \ @@ -767,7 +838,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/reagent_containers/syringe/mulligan cost = 4 surplus = 30 - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/stealthy_tools/emplight name = "EMP Flashlight" @@ -823,7 +894,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) provides the user with superior armor and mobility compared to the standard syndicate hardsuit." item = /obj/item/clothing/suit/space/hardsuit/syndi/elite cost = 8 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) exclude_modes = list() /datum/uplink_item/suits/hardsuit/shielded @@ -832,7 +903,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) The shields can handle up to three impacts within a short duration and will rapidly recharge while not under fire." item = /obj/item/clothing/suit/space/hardsuit/shielded/syndi cost = 30 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) exclude_modes = list() // Devices and Tools @@ -882,7 +953,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) and other supplies helpful for a field medic." item = /obj/item/storage/firstaid/tactical cost = 4 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/syndietome name = "Syndicate Tome" @@ -952,7 +1023,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) 'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety." item = /obj/item/clothing/shoes/magboots/syndie cost = 2 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/c4 name = "Composition C-4" @@ -1004,6 +1075,18 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/device/sbeacondrop/bomb cost = 11 +/datum/uplink_item/device_tools/clown_bomb_clownops + name = "Clown Bomb" + desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \ + with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \ + movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \ + transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \ + be defused, and some crew may attempt to do so." + item = /obj/item/device/sbeacondrop/clownbomb + cost = 15 + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) + /datum/uplink_item/device_tools/syndicate_detonator name = "Syndicate Detonator" desc = "The Syndicate detonator is a companion device to the Syndicate bomb. Simply press the included button \ @@ -1012,7 +1095,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) the blast radius before using the detonator." item = /obj/item/device/syndicatedetonator cost = 3 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/rad_laser name = "Radioactive Microlaser" @@ -1029,7 +1112,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/device/assault_pod cost = 30 surplus = 0 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/shield name = "Energy Shield" @@ -1040,20 +1123,30 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) surplus = 20 include_modes = list(/datum/game_mode/nuclear) +/datum/uplink_item/device_tools/shield + name = "Bananium Energy Shield" + desc = "A clown's most powerful defensive weapon, this personal shield provides near immunity to ranged energy attacks \ + by bouncing them back at the ones who fired them. It can also be thrown to bounce off of people, slipping them, \ + and returning to you even if you miss. WARNING: DO NOT ATTEMPT TO STAND ON SHIELD WHILE DEPLOYED, EVEN IF WEARING ANTI-SLIP SHOES." + item = /obj/item/shield/energy/bananium + cost = 16 + surplus = 0 + include_modes = list(/datum/game_mode/nuclear/clown_ops) + /datum/uplink_item/device_tools/medgun name = "Medbeam Gun" desc = "A wonder of Syndicate engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \ operatives in the fight, even while under fire." item = /obj/item/gun/medbeam cost = 15 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/potion name = "Syndicate Sentience Potion" item = /obj/item/slimepotion/slime/sentience/nuclear desc = "A potion recovered at great risk by undercover syndicate operatives and then subsequently modified with syndicate technology. Using it will make any animal sentient, and bound to serve you, as well as implanting an internal radio for communication and an internal ID card for opening doors." cost = 4 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/telecrystal name = "Raw Telecrystal" @@ -1189,7 +1282,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) // Role-specific items /datum/uplink_item/role_restricted category = "Role-Restricted" - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) surplus = 0 /datum/uplink_item/role_restricted/reverse_revolver @@ -1346,7 +1439,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/badass/costumes surplus = 0 - include_modes = list(/datum/game_mode/nuclear) + include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) cost = 4 cant_discount = TRUE @@ -1382,7 +1475,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/structure/closet/crate cost = 20 player_minimum = 25 - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) cant_discount = TRUE var/starting_crate_value = 50 diff --git a/config/game_options.txt b/config/game_options.txt index d056fb7569..ee080b6014 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -91,6 +91,7 @@ PROBABILITY EXTENDED 0 PROBABILITY SECRET_EXTENDED 0 PROBABILITY DEVIL 0 PROBABILITY DEVIL_AGENTS 0 +PROBABILITY CLOWNOPS 0 ## You probably want to keep sandbox off by default for secret and random. PROBABILITY SANDBOX 0 diff --git a/icons/mob/inhands/equipment/shields_lefthand.dmi b/icons/mob/inhands/equipment/shields_lefthand.dmi index 6b5ca3857d..e9d0dd0d2b 100644 Binary files a/icons/mob/inhands/equipment/shields_lefthand.dmi and b/icons/mob/inhands/equipment/shields_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_righthand.dmi b/icons/mob/inhands/equipment/shields_righthand.dmi index e3de91087a..dda17156fe 100644 Binary files a/icons/mob/inhands/equipment/shields_righthand.dmi and b/icons/mob/inhands/equipment/shields_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi index 5e7b04a25a..d6950f4e1e 100644 Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi index b330dc8f95..9655829113 100644 Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi index c003cf238e..d6dd4c1b00 100644 Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index 8e930e1ee7..03cf226b84 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/icons/obj/machines/nuke.dmi b/icons/obj/machines/nuke.dmi index ceace5c250..c98e4c1cf6 100644 Binary files a/icons/obj/machines/nuke.dmi and b/icons/obj/machines/nuke.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 344b7926d6..443d286b4d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -482,6 +482,9 @@ #include "code\game\gamemodes\changeling\changeling.dm" #include "code\game\gamemodes\changeling\traitor_chan.dm" #include "code\game\gamemodes\clock_cult\clock_cult.dm" +#include "code\game\gamemodes\clown_ops\bananium_bomb.dm" +#include "code\game\gamemodes\clown_ops\clown_ops.dm" +#include "code\game\gamemodes\clown_ops\clown_weapons.dm" #include "code\game\gamemodes\cult\cult.dm" #include "code\game\gamemodes\devil\devil_game_mode.dm" #include "code\game\gamemodes\devil\game_mode.dm" @@ -1211,6 +1214,7 @@ #include "code\modules\antagonists\morph\morph_antag.dm" #include "code\modules\antagonists\nightmare\nightmare.dm" #include "code\modules\antagonists\ninja\ninja.dm" +#include "code\modules\antagonists\nukeop\clownop.dm" #include "code\modules\antagonists\nukeop\nukeop.dm" #include "code\modules\antagonists\nukeop\equipment\nuclear_challenge.dm" #include "code\modules\antagonists\nukeop\equipment\nuclearbomb.dm"