diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index 94d1d2135..b08a5a213 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -144,7 +144,8 @@
#define NO_AUTO_WAG (1<<12)
#define GENITAL_EXAMINE (1<<13)
#define VORE_EXAMINE (1<<14)
-#define NO_UWU (1<<15)
+#define TRASH_FORCEFEED (1<<15)
+#define NO_UWU (1<<16)
#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES|BREAST_ENLARGEMENT|PENIS_ENLARGEMENT)
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 905e6c950..349af6d3c 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -188,8 +188,8 @@
#define TRAIT_CUM_PLUS "cum_plus"
#define TRAIT_NEVER_CLONE "donotclone"
#define TRAIT_COLDBLOODED "coldblooded" // Your body is literal room temperature. Does not make you immune to the temp.
-#define TRAIT_FLIMSY "flimsy" //you have 20% less maxhealth
-
+#define TRAIT_FLIMSY "flimsy" //you have 20% less maxhealth
+#define TRAIT_TRASHCAN "trashcan"
//Hyper
#define TRAIT_VIRILE "virile" //you have 20% more chance of impreg
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index 19e8b77bd..cb3e676d0 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -120,7 +120,8 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/autosurgeon/breasts = 1,
/obj/item/autosurgeon/womb = 1,
/obj/item/toy/plush/random = 1,
- /obj/item/grenade/spawnergrenade/clustaur = 1
+ /obj/item/grenade/spawnergrenade/clustaur = 1,
+ /obj/effect/spawner/lootdrop/grille_or_trash = 5
))
GLOBAL_LIST_INIT(ratking_trash, list(//Garbage: used by the regal rat mob when spawning garbage.
diff --git a/code/datums/elements/trash.dm b/code/datums/elements/trash.dm
new file mode 100644
index 000000000..8538ce317
--- /dev/null
+++ b/code/datums/elements/trash.dm
@@ -0,0 +1,23 @@
+/datum/element/trash
+ element_flags = ELEMENT_DETACH
+
+/datum/element/trash/Attach(datum/target)
+ . = ..()
+ RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/UseFromHand)
+
+/datum/element/trash/proc/UseFromHand(obj/item/source, mob/living/M, mob/living/user)
+ if((M == user || M.client?.prefs.cit_toggles & TRASH_FORCEFEED) && ishuman(user))
+ var/mob/living/carbon/human/H = M
+ if(HAS_TRAIT(H, TRAIT_TRASHCAN))
+ playsound(H.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
+ if(H.vore_selected)
+ if(M != user)
+ H.visible_message("[user] forces the [source] into [H]'s [H.vore_selected]",
+ "[user] forces the [source] into your [H.vore_selected]")
+ else
+ H.visible_message("[H] [H.vore_selected.vore_verb]s the [source] into their [H.vore_selected]",
+ "You [H.vore_selected.vore_verb] the [source] into your [H.vore_selected]")
+ source.forceMove(H.vore_selected)
+ else
+ H.visible_message("[H] consumes the [source].")
+ qdel(source)
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index b79351e6e..cfe3e1c49 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -171,3 +171,11 @@
var/mob/living/carbon/human/H = quirk_holder
SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
to_chat(quirk_holder, "You brought some extra dye with you! It's in your bag if you forgot.")
+
+/datum/quirk/trashcan
+ name = "Trashcan"
+ desc = "You are able to consume and digest trash."
+ value = 0
+ gain_text = "You feel like munching on a can of soda."
+ lose_text = "You no longer feel like you should be eating trash."
+ mob_trait = TRAIT_TRASHCAN
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 3d56fdb6b..135781f1c 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -1,1091 +1,1095 @@
-//cleansed 9/15/2012 17:48
-
-/*
-CONTAINS:
-MATCHES
-CIGARETTES
-CIGARS
-SMOKING PIPES
-CHEAP LIGHTERS
-ZIPPO
-
-CIGARETTE PACKETS ARE IN FANCY.DM
-*/
-
-///////////
-//MATCHES//
-///////////
-/obj/item/match
- name = "match"
- desc = "A simple match stick, used for lighting fine smokables."
- icon = 'icons/obj/cigarettes.dmi'
- icon_state = "match_unlit"
- var/lit = FALSE
- var/burnt = FALSE
- var/smoketime = 5
- w_class = WEIGHT_CLASS_TINY
- heat = 1000
- grind_results = list(/datum/reagent/phosphorus = 2)
-
-/obj/item/match/process()
- smoketime--
- if(smoketime < 1)
- matchburnout()
- else
- open_flame(heat)
-
-/obj/item/match/fire_act(exposed_temperature, exposed_volume)
- matchignite()
-
-/obj/item/match/proc/matchignite()
- if(!lit && !burnt)
- lit = TRUE
- icon_state = "match_lit"
- damtype = "fire"
- force = 3
- hitsound = 'sound/items/welder.ogg'
- item_state = "cigon"
- name = "lit match"
- desc = "A match. This one is lit."
- attack_verb = list("burnt","singed")
- START_PROCESSING(SSobj, src)
- update_icon()
- playsound(src, 'sound/items/match.ogg', 50, 1, -1)
-
-/obj/item/match/proc/matchburnout()
- if(lit)
- lit = FALSE
- burnt = TRUE
- damtype = "brute"
- force = initial(force)
- icon_state = "match_burnt"
- item_state = "cigoff"
- name = "burnt match"
- desc = "A match. This one has seen better days."
- attack_verb = list("flicked")
- STOP_PROCESSING(SSobj, src)
-
-/obj/item/match/dropped(mob/user)
- matchburnout()
- . = ..()
-
-/obj/item/match/attack(mob/living/carbon/M, mob/living/carbon/user)
- if(!isliving(M))
- return
- if(lit && M.IgniteMob())
- message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
- log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
- var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
- if(lit && cig && user.a_intent == INTENT_HELP)
- if(cig.lit)
- to_chat(user, "[cig] is already lit.")
- if(M == user)
- cig.attackby(src, user)
- else
- cig.light("[user] holds [src] out for [M], and lights [cig].")
- else
- ..()
-
-/obj/item/proc/help_light_cig(mob/living/M)
- var/mask_item = M.get_item_by_slot(SLOT_WEAR_MASK)
- if(istype(mask_item, /obj/item/clothing/mask/cigarette))
- return mask_item
-
-/obj/item/match/is_hot()
- return lit * heat
-
-//////////////////
-//FINE SMOKABLES//
-//////////////////
-/obj/item/clothing/mask/cigarette
- name = "cigarette"
- desc = "A roll of tobacco and nicotine."
- icon_state = "cigoff"
- throw_speed = 0.5
- item_state = "cigoff"
- w_class = WEIGHT_CLASS_TINY
- body_parts_covered = null
- grind_results = list()
- var/lit = FALSE
- var/starts_lit = FALSE
- var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi
- var/icon_off = "cigoff"
- var/type_butt = /obj/item/cigbutt
- var/lastHolder = null
- var/smoketime = 300
- var/chem_volume = 30
- var/list/list_reagents = list(/datum/reagent/drug/nicotine = 15)
- heat = 1000
-
-/obj/item/clothing/mask/cigarette/suicide_act(mob/user)
- user.visible_message("[user] is huffing [src] as quickly as [user.p_they()] can! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer.")
- return (TOXLOSS|OXYLOSS)
-
-/obj/item/clothing/mask/cigarette/Initialize()
- . = ..()
- create_reagents(chem_volume, INJECTABLE | NO_REACT) // so it doesn't react until you light it
- if(list_reagents)
- reagents.add_reagent_list(list_reagents)
- if(starts_lit)
- light()
- AddComponent(/datum/component/knockoff,90,list(BODY_ZONE_PRECISE_MOUTH),list(SLOT_WEAR_MASK))//90% to knock off when wearing a mask
-
-/obj/item/clothing/mask/cigarette/Destroy()
- STOP_PROCESSING(SSobj, src)
- . = ..()
-
-/obj/item/clothing/mask/cigarette/attackby(obj/item/W, mob/user, params)
- if(!lit && smoketime > 0)
- var/lighting_text = W.ignition_effect(src, user)
- if(lighting_text)
- light(lighting_text)
- else
- return ..()
-
-/obj/item/clothing/mask/cigarette/afterattack(obj/item/reagent_containers/glass/glass, mob/user, proximity)
- . = ..()
- if(!proximity || lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead)
- return
- if(istype(glass)) //you can dip cigarettes into beakers
- if(glass.reagents.trans_to(src, chem_volume)) //if reagents were transfered, show the message
- to_chat(user, "You dip \the [src] into \the [glass].")
- else //if not, either the beaker was empty, or the cigarette was full
- if(!glass.reagents.total_volume)
- to_chat(user, "[glass] is empty.")
- else
- to_chat(user, "[src] is full.")
-
-
-/obj/item/clothing/mask/cigarette/proc/light(flavor_text = null)
- if(lit)
- return
- if(!(flags_1 & INITIALIZED_1))
- icon_state = icon_on
- item_state = icon_on
- return
-
- lit = TRUE
- name = "lit [name]"
- attack_verb = list("burnt", "singed")
- hitsound = 'sound/items/welder.ogg'
- damtype = "fire"
- force = 4
- if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
- var/datum/effect_system/reagents_explosion/e = new()
- e.set_up(round(reagents.get_reagent_amount(/datum/reagent/toxin/plasma) / 2.5, 1), get_turf(src), 0, 0)
- e.start()
- qdel(src)
- return
- if(reagents.get_reagent_amount(/datum/reagent/fuel)) // the fuel explodes, too, but much less violently
- var/datum/effect_system/reagents_explosion/e = new()
- e.set_up(round(reagents.get_reagent_amount(/datum/reagent/fuel) / 5, 1), get_turf(src), 0, 0)
- e.start()
- qdel(src)
- return
- // allowing reagents to react after being lit
- DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
- reagents.handle_reactions()
- icon_state = icon_on
- item_state = icon_on
- if(flavor_text)
- var/turf/T = get_turf(src)
- T.visible_message(flavor_text)
- START_PROCESSING(SSobj, src)
-
- //can't think of any other way to update the overlays :<
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_wear_mask()
- M.update_inv_hands()
-
-
-/obj/item/clothing/mask/cigarette/proc/handle_reagents()
- if(reagents.total_volume)
- if(iscarbon(loc))
- var/mob/living/carbon/C = loc
- if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob
- var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1)
- reagents.reaction(C, INGEST, fraction)
- if(!reagents.trans_to(C, REAGENTS_METABOLISM))
- reagents.remove_any(REAGENTS_METABOLISM)
- return
- reagents.remove_any(REAGENTS_METABOLISM)
-
-
-/obj/item/clothing/mask/cigarette/process()
- var/turf/location = get_turf(src)
- var/mob/living/M = loc
- if(isliving(loc))
- M.IgniteMob()
- smoketime--
- if(smoketime < 1)
- new type_butt(location)
- if(ismob(loc))
- to_chat(M, "Your [name] goes out.")
- qdel(src)
- return
- open_flame()
- if(reagents && reagents.total_volume)
- handle_reagents()
-
-/obj/item/clothing/mask/cigarette/attack_self(mob/user)
- if(lit)
- user.visible_message("[user] calmly drops and treads on \the [src], putting it out instantly.")
- new type_butt(user.loc)
- qdel(src)
- . = ..()
-
-/obj/item/clothing/mask/cigarette/attack(mob/living/carbon/M, mob/living/carbon/user)
- if(!istype(M))
- return ..()
- if(M.on_fire && !lit)
- light("[user] lights [src] with [M]'s burning body. What a cold-blooded badass.")
- return
- var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
- if(lit && cig && user.a_intent == INTENT_HELP)
- if(cig.lit)
- to_chat(user, "The [cig.name] is already lit.")
- if(M == user)
- cig.attackby(src, user)
- else
- cig.light("[user] holds the [name] out for [M], and lights [M.p_their()] [cig.name].")
- else
- return ..()
-
-/obj/item/clothing/mask/cigarette/fire_act(exposed_temperature, exposed_volume)
- light()
-
-/obj/item/clothing/mask/cigarette/is_hot()
- return lit * heat
-
-// Cigarette brands.
-
-/obj/item/clothing/mask/cigarette/space_cigarette
- desc = "A Space Cigarette brand cigarette."
-
-/obj/item/clothing/mask/cigarette/dromedary
- desc = "A DromedaryCo brand cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/silicon = 7.5)
-
-/obj/item/clothing/mask/cigarette/smokekins
- desc = "A Kinaris Corp brand cigarette"
- list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/gold = 1)
-
-/obj/item/clothing/mask/cigarette/uplift
- desc = "An Uplift Smooth brand cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/consumable/menthol = 7.5)
-
-/obj/item/clothing/mask/cigarette/robust
- desc = "A Robust brand cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/consumable/grenadine = 7.5)
-
-/obj/item/clothing/mask/cigarette/robustgold
- desc = "A Robust Gold brand cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/gold = 1)
-
-/obj/item/clothing/mask/cigarette/carp
- desc = "A Carp Classic brand cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/consumable/sodiumchloride = 7.5)
-
-/obj/item/clothing/mask/cigarette/syndicate
- desc = "An unknown brand cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/medicine/omnizine = 15)
-
-/obj/item/clothing/mask/cigarette/shadyjims
- desc = "A Shady Jim's Super Slims cigarette."
- list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/toxin/lipolicide = 4, /datum/reagent/ammonia = 2, /datum/reagent/toxin/plantbgone = 1, /datum/reagent/toxin = 1.5)
-
-/obj/item/clothing/mask/cigarette/xeno
- desc = "A Xeno Filtered brand cigarette."
- list_reagents = list (/datum/reagent/drug/nicotine = 20, /datum/reagent/medicine/regen_jelly = 15, /datum/reagent/drug/krokodil = 4)
-
-// Rollies.
-
-/obj/item/clothing/mask/cigarette/rollie
- name = "rollie"
- desc = "A roll of dried plant matter wrapped in thin paper."
- icon_state = "spliffoff"
- icon_on = "spliffon"
- icon_off = "spliffoff"
- type_butt = /obj/item/cigbutt/roach
- throw_speed = 0.5
- item_state = "spliffoff"
- smoketime = 180
- chem_volume = 50
- list_reagents = null
-
-/obj/item/clothing/mask/cigarette/rollie/New()
- ..()
- src.pixel_x = rand(-5, 5)
- src.pixel_y = rand(-5, 5)
-
-/obj/item/clothing/mask/cigarette/rollie/nicotine
- list_reagents = list(/datum/reagent/drug/nicotine = 15)
-
-/obj/item/clothing/mask/cigarette/rollie/trippy
- list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/drug/mushroomhallucinogen = 35)
- starts_lit = TRUE
-
-/obj/item/clothing/mask/cigarette/rollie/cannabis
- list_reagents = list(/datum/reagent/drug/space_drugs = 15, /datum/reagent/toxin/lipolicide = 35)
-
-/obj/item/clothing/mask/cigarette/rollie/mindbreaker
- list_reagents = list(/datum/reagent/toxin/mindbreaker = 35, /datum/reagent/toxin/lipolicide = 15)
-
-/obj/item/cigbutt/roach
- name = "roach"
- desc = "A manky old roach, or for non-stoners, a used rollup."
- icon_state = "roach"
-
-/obj/item/cigbutt/roach/New()
- ..()
- src.pixel_x = rand(-5, 5)
- src.pixel_y = rand(-5, 5)
-
-
-////////////
-// CIGARS //
-////////////
-/obj/item/clothing/mask/cigarette/cigar
- name = "premium cigar"
- desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!"
- icon_state = "cigaroff"
- icon_on = "cigaron"
- icon_off = "cigaroff" //make sure to add positional sprites in icons/obj/cigarettes.dmi if you add more.
- type_butt = /obj/item/cigbutt/cigarbutt
- throw_speed = 0.5
- item_state = "cigaroff"
- smoketime = 1500
- chem_volume = 40
-
-/obj/item/clothing/mask/cigarette/cigar/cohiba
- name = "\improper Cohiba Robusto cigar"
- desc = "There's little more you could want from a cigar."
- icon_state = "cigar2off"
- icon_on = "cigar2on"
- icon_off = "cigar2off"
- smoketime = 2000
- chem_volume = 80
-
-
-/obj/item/clothing/mask/cigarette/cigar/havana
- name = "premium Havanian cigar"
- desc = "A cigar fit for only the best of the best."
- icon_state = "cigar2off"
- icon_on = "cigar2on"
- icon_off = "cigar2off"
- smoketime = 7200
- chem_volume = 50
-
-/obj/item/cigbutt
- name = "cigarette butt"
- desc = "A manky old cigarette butt."
- icon = 'icons/obj/clothing/masks.dmi'
- icon_state = "cigbutt"
- w_class = WEIGHT_CLASS_TINY
- throwforce = 0
- grind_results = list(/datum/reagent/carbon = 2)
-
-/obj/item/cigbutt/cigarbutt
- name = "cigar butt"
- desc = "A manky old cigar butt."
- icon_state = "cigarbutt"
-
-/////////////////
-//SMOKING PIPES//
-/////////////////
-/obj/item/clothing/mask/cigarette/pipe
- name = "smoking pipe"
- desc = "A pipe, for smoking. Probably made of meerschaum or something."
- icon_state = "pipeoff"
- item_state = "pipeoff"
- icon_on = "pipeon" //Note - these are in masks.dmi
- icon_off = "pipeoff"
- smoketime = 0
- chem_volume = 100
- list_reagents = null
- var/packeditem = 0
-
-/obj/item/clothing/mask/cigarette/pipe/Initialize()
- . = ..()
- name = "empty [initial(name)]"
-
-/obj/item/clothing/mask/cigarette/pipe/Destroy()
- STOP_PROCESSING(SSobj, src)
- . = ..()
-
-/obj/item/clothing/mask/cigarette/pipe/process()
- var/turf/location = get_turf(src)
- smoketime--
- if(smoketime < 1)
- new /obj/effect/decal/cleanable/ash(location)
- if(ismob(loc))
- var/mob/living/M = loc
- to_chat(M, "Your [name] goes out.")
- lit = 0
- icon_state = icon_off
- item_state = icon_off
- M.update_inv_wear_mask()
- packeditem = 0
- name = "empty [initial(name)]"
- STOP_PROCESSING(SSobj, src)
- return
- open_flame()
- if(reagents && reagents.total_volume) // check if it has any reagents at all
- handle_reagents()
-
-
-/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/O, mob/user, params)
- if(istype(O, /obj/item/reagent_containers/food/snacks/grown))
- var/obj/item/reagent_containers/food/snacks/grown/G = O
- if(!packeditem)
- if(G.dry == 1)
- to_chat(user, "You stuff [O] into [src].")
- smoketime = 400
- packeditem = 1
- name = "[O.name]-packed [initial(name)]"
- if(O.reagents)
- O.reagents.trans_to(src, O.reagents.total_volume)
- qdel(O)
- else
- to_chat(user, "It has to be dried first!")
- else
- to_chat(user, "It is already packed!")
- else
- var/lighting_text = O.ignition_effect(src,user)
- if(lighting_text)
- if(smoketime > 0)
- light(lighting_text)
- else
- to_chat(user, "There is nothing to smoke!")
- else
- return ..()
-
-/obj/item/clothing/mask/cigarette/pipe/attack_self(mob/user)
- var/turf/location = get_turf(user)
- if(lit)
- user.visible_message("[user] puts out [src].", "You put out [src].")
- lit = 0
- icon_state = icon_off
- item_state = icon_off
- STOP_PROCESSING(SSobj, src)
- return
- if(!lit && smoketime > 0)
- to_chat(user, "You empty [src] onto [location].")
- new /obj/effect/decal/cleanable/ash(location)
- packeditem = 0
- smoketime = 0
- reagents.clear_reagents()
- name = "empty [initial(name)]"
- return
-
-/obj/item/clothing/mask/cigarette/pipe/cobpipe
- name = "corn cob pipe"
- desc = "A nicotine delivery system popularized by folksy backwoodsmen and kept popular in the modern age and beyond by space hipsters. Can be loaded with objects."
- icon_state = "cobpipeoff"
- item_state = "cobpipeoff"
- icon_on = "cobpipeon" //Note - these are in masks.dmi
- icon_off = "cobpipeoff"
- smoketime = 0
-
-
-/////////
-//ZIPPO//
-/////////
-/obj/item/lighter
- name = "\improper Zippo lighter"
- desc = "The zippo."
- icon = 'icons/obj/cigarettes.dmi'
- icon_state = "zippo"
- item_state = "zippo"
- w_class = WEIGHT_CLASS_TINY
- flags_1 = CONDUCT_1
- slot_flags = ITEM_SLOT_BELT
- price = 1
- var/lit = 0
- var/fancy = TRUE
- var/overlay_state
- var/overlay_list = list(
- "plain",
- "dame",
- "thirteen",
- "snake"
- )
- heat = 1500
- resistance_flags = FIRE_PROOF
- light_color = LIGHT_COLOR_FIRE
- grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5)
-
-/obj/item/lighter/Initialize()
- . = ..()
- if(!overlay_state)
- overlay_state = pick(overlay_list)
- update_icon()
-
-/obj/item/lighter/AltClick(mob/living/user)
- . = ..()
- if(GLOB.lighter_reskins && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
- reskin_obj(user)
-
-/obj/item/lighter/reskin_obj(mob/M)
- if(lit)
- return to_chat(M, "You need to close the lighter before changing the engraving!")
- if(!LAZYLEN(GLOB.lighter_reskins))
- return
-
- var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.lighter_reskins
- var/new_icon = GLOB.lighter_reskins[choice]
- if(QDELETED(src) || isnull(new_icon) || new_icon == icon || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
- return
- overlay_state = new_icon
- update_icon()
- to_chat(M, "[src] is now skinned as '[choice]'.")
-
-/obj/item/lighter/suicide_act(mob/living/carbon/user)
- if (lit)
- user.visible_message("[user] begins holding \the [src]'s flame up to [user.p_their()] face! It looks like [user.p_theyre()] trying to commit suicide!")
- playsound(src, 'sound/items/welder.ogg', 50, 1)
- return FIRELOSS
- else
- user.visible_message("[user] begins whacking [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return BRUTELOSS
-
-/obj/item/lighter/update_icon()
- cut_overlays()
- var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
- icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
- add_overlay(lighter_overlay)
-
-/obj/item/lighter/ignition_effect(atom/A, mob/user)
- if(is_hot())
- . = "With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool."
-
-/obj/item/lighter/proc/set_lit(new_lit)
- lit = new_lit
- if(lit)
- force = 5
- damtype = "fire"
- hitsound = 'sound/items/welder.ogg'
- attack_verb = list("burnt", "singed")
- set_light(2, 0.6, LIGHT_COLOR_FIRE)
- START_PROCESSING(SSobj, src)
- else
- hitsound = "swing_hit"
- force = 0
- attack_verb = null //human_defense.dm takes care of it
- set_light(0)
- STOP_PROCESSING(SSobj, src)
- update_icon()
-
-/obj/item/lighter/attack_self(mob/living/user)
- if(user.is_holding(src))
- if(!lit)
- set_lit(TRUE)
- if(fancy)
- user.visible_message("[user] flips open and lights [src].", "You flip open and light [src] in one smooth movement.")
- playsound(user, 'sound/items/zippoopen.ogg', 50, 1, -1)
- else
- playsound(user, 'sound/items/lighter.ogg', 50, 1, -1)
- var/prot = FALSE
- var/mob/living/carbon/human/H = user
-
- if(istype(H) && H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- if(G.max_heat_protection_temperature)
- prot = (G.max_heat_protection_temperature > 360)
- else
- prot = TRUE
-
- if(prot || prob(75))
- user.visible_message("After a few attempts, [user] manages to light [src].", "After a few attempts, you manage to light [src].")
- else
- var/hitzone = user.held_index_to_dir(user.active_hand_index) == "r" ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND
- user.apply_damage(5, BURN, hitzone)
- user.visible_message("After a few attempts, [user] manages to light [src] - however, [user.p_they()] burn [user.p_their()] finger in the process.", "You burn yourself while lighting the lighter!")
- SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "burnt_thumb", /datum/mood_event/burnt_thumb)
-
- else
- set_lit(FALSE)
- if(fancy)
- user.visible_message("You hear a quiet click, as [user] shuts off [src].", "You quietly shut off [src].")
- playsound(user, 'sound/items/zippoclose.ogg', 50, 1, -1)
- else
- user.visible_message("[user] quietly shuts off [src].", "You quietly shut off [src].")
- else
- . = ..()
-
-/obj/item/lighter/attack(mob/living/carbon/M, mob/living/carbon/user)
- if(lit && M.IgniteMob())
- message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
- log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
- var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
- if(lit && cig && user.a_intent == INTENT_HELP)
- if(cig.lit)
- to_chat(user, "The [cig.name] is already lit.")
- if(M == user)
- cig.attackby(src, user)
- else
- if(fancy)
- cig.light("[user] whips the [name] out and holds it for [M]. [user.p_their(TRUE)] arm is as steady as the unflickering flame [user.p_they()] light[user.p_s()] \the [cig] with.")
- else
- cig.light("[user] holds the [name] out for [M], and lights [M.p_their()] [cig.name].")
- else
- ..()
-
-/obj/item/lighter/process()
- open_flame()
-
-/obj/item/lighter/is_hot()
- return lit * heat
-
-
-/obj/item/lighter/greyscale
- name = "cheap lighter"
- desc = "A cheap-as-free lighter."
- icon_state = "lighter"
- fancy = FALSE
- overlay_list = list(
- "transp",
- "tall",
- "matte",
- "zoppo" //u cant stoppo th zoppo
- )
- var/lighter_color
- var/list/color_list = list( //Same 16 color selection as electronic assemblies
- COLOR_ASSEMBLY_BLACK,
- COLOR_FLOORTILE_GRAY,
- COLOR_ASSEMBLY_BGRAY,
- COLOR_ASSEMBLY_WHITE,
- COLOR_ASSEMBLY_RED,
- COLOR_ASSEMBLY_ORANGE,
- COLOR_ASSEMBLY_BEIGE,
- COLOR_ASSEMBLY_BROWN,
- COLOR_ASSEMBLY_GOLD,
- COLOR_ASSEMBLY_YELLOW,
- COLOR_ASSEMBLY_GURKHA,
- COLOR_ASSEMBLY_LGREEN,
- COLOR_ASSEMBLY_GREEN,
- COLOR_ASSEMBLY_LBLUE,
- COLOR_ASSEMBLY_BLUE,
- COLOR_ASSEMBLY_PURPLE
- )
-
-/obj/item/lighter/greyscale/Initialize()
- . = ..()
- if(!lighter_color)
- lighter_color = pick(color_list)
- update_icon()
-
-/obj/item/lighter/greyscale/update_icon()
- cut_overlays()
- var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
- icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
- lighter_overlay.color = lighter_color
- add_overlay(lighter_overlay)
-
-/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user)
- if(is_hot())
- . = "After some fiddling, [user] manages to light [A] with [src]."
-
-
-/obj/item/lighter/slime
- name = "slime zippo"
- desc = "A specialty zippo made from slimes and industry. Has a much hotter flame than normal."
- icon_state = "slighter"
- heat = 3000 //Blue flame!
- light_color = LIGHT_COLOR_CYAN
- overlay_state = "slime"
- grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/medicine/pyroxadone = 5)
-
-
-///////////
-//ROLLING//
-///////////
-/obj/item/rollingpaper
- name = "rolling paper"
- desc = "A thin piece of paper used to make fine smokeables."
- icon = 'icons/obj/cigarettes.dmi'
- icon_state = "cig_paper"
- w_class = WEIGHT_CLASS_TINY
-
-/obj/item/rollingpaper/afterattack(atom/target, mob/user, proximity)
- . = ..()
- if(!proximity)
- return
- if(istype(target, /obj/item/reagent_containers/food/snacks/grown))
- var/obj/item/reagent_containers/food/snacks/grown/O = target
- if(O.dry)
- var/obj/item/clothing/mask/cigarette/rollie/R = new /obj/item/clothing/mask/cigarette/rollie(user.loc)
- R.chem_volume = target.reagents.total_volume
- target.reagents.trans_to(R, R.chem_volume)
- qdel(target)
- qdel(src)
- user.put_in_active_hand(R)
- to_chat(user, "You roll the [target.name] into a rolling paper.")
- R.desc = "Dried [target.name] rolled up in a thin piece of paper."
- else
- to_chat(user, "You need to dry this first!")
-
-///////////////
-//VAPE NATION//
-///////////////
-/obj/item/clothing/mask/vape
- name = "\improper E-Cigarette"
- desc = "A classy and highly sophisticated electronic cigarette, for classy and dignified gentlemen. A warning label reads \"Warning: Do not fill with flammable materials.\""//<<< i'd vape to that.
- icon = 'icons/obj/clothing/masks.dmi'
- icon_state = null
- item_state = null
- w_class = WEIGHT_CLASS_TINY
- var/chem_volume = 100
- var/vapetime = FALSE //this so it won't puff out clouds every tick
- var/screw = FALSE // kinky
- var/super = FALSE //for the fattest vapes dude.
-
-/obj/item/clothing/mask/vape/suicide_act(mob/user)
- user.visible_message("[user] is puffin hard on dat vape, [user.p_they()] trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer
- return (TOXLOSS|OXYLOSS)
-
-
-/obj/item/clothing/mask/vape/Initialize(mapload, param_color)
- . = ..()
- create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
- reagents.add_reagent(/datum/reagent/drug/nicotine, 50)
- if(!icon_state)
- if(!param_color)
- param_color = pick("red","blue","black","white","green","purple","yellow","orange")
- icon_state = "[param_color]_vape"
- item_state = "[param_color]_vape"
-
-/obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params)
- if(O.tool_behaviour == TOOL_SCREWDRIVER)
- if(!screw)
- screw = TRUE
- to_chat(user, "You open the cap on [src].")
- ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
- if(obj_flags & EMAGGED)
- add_overlay("vapeopen_high")
- else if(super)
- add_overlay("vapeopen_med")
- else
- add_overlay("vapeopen_low")
- else
- screw = FALSE
- to_chat(user, "You close the cap on [src].")
- DISABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
- cut_overlays()
-
- if(O.tool_behaviour == TOOL_MULTITOOL)
- if(screw && !(obj_flags & EMAGGED))//also kinky
- if(!super)
- cut_overlays()
- super = TRUE
- to_chat(user, "You increase the voltage of [src].")
- add_overlay("vapeopen_med")
- else
- cut_overlays()
- super = FALSE
- to_chat(user, "You decrease the voltage of [src].")
- add_overlay("vapeopen_low")
-
- if(screw && (obj_flags & EMAGGED))
- to_chat(user, "[src] can't be modified!")
-
- else
- ..()
-
-/obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY.
- if(screw)
- if(!(obj_flags & EMAGGED))
- cut_overlays()
- obj_flags |= EMAGGED
- super = FALSE
- to_chat(user, "You maximize the voltage of [src].")
- add_overlay("vapeopen_high")
- var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect
- sp.set_up(5, 1, src)
- sp.start()
- else
- to_chat(user, "[src] is already emagged!")
- else
- to_chat(user, "You need to open the cap to do that.")
-
-/obj/item/clothing/mask/vape/attack_self(mob/user)
- if(reagents.total_volume > 0)
- to_chat(user, "You empty [src] of all reagents.")
- reagents.clear_reagents()
-
-/obj/item/clothing/mask/vape/equipped(mob/user, slot)
- if(slot == SLOT_WEAR_MASK)
- if(!screw)
- to_chat(user, "You start puffing on the vape.")
- DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
- START_PROCESSING(SSobj, src)
- else //it will not start if the vape is opened.
- to_chat(user, "You need to close the cap first!")
-
-/obj/item/clothing/mask/vape/dropped(mob/user)
- var/mob/living/carbon/C = user
- if(C.get_item_by_slot(SLOT_WEAR_MASK) == src)
- ENABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
- STOP_PROCESSING(SSobj, src)
-
-/obj/item/clothing/mask/vape/proc/hand_reagents()//had to rename to avoid duplicate error
- if(reagents.total_volume)
- if(iscarbon(loc))
- var/mob/living/carbon/C = loc
- if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob
- var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1) //this will react instantly, making them a little more dangerous than cigarettes
- reagents.reaction(C, INGEST, fraction)
- if(!reagents.trans_to(C, REAGENTS_METABOLISM))
- reagents.remove_any(REAGENTS_METABOLISM)
- if(reagents.get_reagent_amount(/datum/reagent/fuel))
- //HOT STUFF
- C.fire_stacks = 2
- C.IgniteMob()
-
- if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
- var/datum/effect_system/reagents_explosion/e = new()
- e.set_up(round(reagents.get_reagent_amount(/datum/reagent/toxin/plasma) / 2.5, 1), get_turf(src), 0, 0)
- e.start()
- qdel(src)
- return
- reagents.remove_any(REAGENTS_METABOLISM)
-
-/obj/item/clothing/mask/vape/process()
- var/mob/living/M = loc
-
- if(isliving(loc))
- M.IgniteMob()
-
- vapetime++
-
- if(!reagents.total_volume)
- if(ismob(loc))
- to_chat(M, "[src] is empty!")
- STOP_PROCESSING(SSobj, src)
- //it's reusable so it won't unequip when empty
- return
- //open flame removed because vapes are a closed system, they wont light anything on fire
-
- if(super && vapetime > 3)//Time to start puffing those fat vapes, yo.
- var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
- s.set_up(reagents, 1, 24, loc)
- s.start()
- vapetime = 0
-
- if((obj_flags & EMAGGED) && vapetime > 3)
- var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
- s.set_up(reagents, 4, 24, loc)
- s.start()
- vapetime = 0
- if(prob(5))//small chance for the vape to break and deal damage if it's emagged
- playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, 0)
- M.apply_damage(20, BURN, BODY_ZONE_HEAD)
- M.Knockdown(300, 1, 0)
- var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread
- sp.set_up(5, 1, src)
- sp.start()
- to_chat(M, "[src] suddenly explodes in your mouth!")
- qdel(src)
- return
-
- if(reagents && reagents.total_volume)
- hand_reagents()
-
-///////////////
-/////BONGS/////
-///////////////
-
-/obj/item/bong
- name = "bong"
- desc = "A water bong used for smoking dried plants."
- icon = 'icons/obj/bongs.dmi'
- icon_state = null
- item_state = null
- w_class = WEIGHT_CLASS_NORMAL
- light_color = "#FFCC66"
- var/icon_off = "bong"
- var/icon_on = "bong_lit"
- var/chem_volume = 100
- var/last_used_time //for cooldown
- var/firecharges = 0 //used for counting how many hits can be taken before the flame goes out
- var/list/list_reagents = list() //For the base reagents bongs could get
-
-
-/obj/item/bong/Initialize()
- . = ..()
- create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
- reagents.add_reagent_list(list_reagents)
- icon_state = icon_off
-
-/obj/item/bong/attackby(obj/item/O, mob/user, params)
- . = ..()
- //If we're using a dried plant..
- if(istype(O,/obj/item/reagent_containers/food/snacks))
- var/obj/item/reagent_containers/food/snacks/DP = O
- if (DP.dry)
- //Nothing if our bong is full
- if (reagents.holder_full())
- user.show_message("The bowl is full!", 1)
- return
-
- //Transfer reagents and remove the plant
- user.show_message("You stuff the [DP] into the [src]'s bowl.", 1)
- DP.reagents.trans_to(src, 100)
- qdel(DP)
- return
- else
- user.show_message("[DP] must be dried first!", 1)
- return
-
- if (O.heat > 500)
- if (reagents && reagents.total_volume) //if there's stuff in the bong
- var/lighting_text = O.ignition_effect(src, user)
- if(lighting_text)
- //Logic regarding igniting it on
- if (firecharges == 0)
- user.show_message("You light the [src] with the [O]!", 1)
- bongturnon()
- else
- user.show_message("You rekindle [src]'s flame with the [O]!", 1)
-
- firecharges = 1
- return
- else
- user.show_message("There's nothing to light up in the bowl.", 1)
- return
-
-/obj/item/bong/CtrlShiftClick(mob/user) //empty reagents on alt click
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- return
-
- if (reagents && reagents.total_volume)
- user.show_message("You empty the [src].", 1)
- reagents.clear_reagents()
- if(firecharges)
- firecharges = 0
- bongturnoff()
- else
- user.show_message("The [src] is already empty.", 1)
-
-/obj/item/bong/AltClick(mob/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- return
-
- if(firecharges)
- firecharges = 0
- bongturnoff()
- user.show_message("You quench the flame.", 1)
-
-/obj/item/bong/examine(mob/user)
- . = ..()
- if(!reagents.total_volume)
- . += "The bowl is empty."
- else if (reagents.total_volume > 80)
- . += "The bowl is filled to the brim."
- else if (reagents.total_volume > 40)
- . += "The bowl has plenty weed in it."
- else
- . += "The bowl has some weed in it."
-
- . += "Ctrl+Shift-click to empty."
- . += "Alt-click to extinguish."
-
-/obj/item/bong/ignition_effect(atom/A, mob/user)
- if(firecharges)
- . = "[user] lights [A] off of the [src]."
- else
- . = ""
-
-/obj/item/bong/attack(mob/living/carbon/M, mob/living/carbon/user, obj/target)
- //if it's lit up, some stuff in the bowl and the user is a target, and we're not on cooldown
- if (!reagents)
- return
-
- if (M ==! user)
- return
-
- if(user.is_mouth_covered(head_only = 1))
- to_chat(user, "Remove your headgear first.")
- return
-
- if(user.is_mouth_covered(mask_only = 1))
- to_chat(user, "Remove your mask first.")
- return
-
- if (!reagents.total_volume)
- to_chat(user, "There's nothing in the bowl.")
- return
-
- if (!firecharges)
- to_chat(user, "You have to light it up first.")
- return
-
- if (last_used_time + 30 < world.time)
- var/hit_strength
- var/noise
- var/hittext = ""
- //if the intent is help then you take a small hit, else a big one
- if (user.a_intent == INTENT_HARM)
- hit_strength = 2
- noise = 100
- hittext = "big hit"
- else
- hit_strength = 1
- noise = 70
- hittext = "hit"
- //bubbling sound
- playsound(user.loc,'sound/effects/bonghit.ogg', noise, 1)
-
- last_used_time = world.time
-
- //message
- user.visible_message("[user] begins to take a "+ hittext +" from the [src]!", \
- "You begin to take a "+ hittext +" from [src].")
-
- //we take a hit here, after an uninterrupted delay
- if(do_after(user, 25, target = user))
- if (reagents && reagents.total_volume)
- var/fraction = 12 * hit_strength
-
- var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
- s.set_up(reagents, hit_strength, 18, user.loc)
- s.start()
-
- reagents.reaction(user, INGEST, fraction)
- if(!reagents.trans_to(user, fraction))
- reagents.remove_any(fraction)
-
- if (hit_strength == 2 && prob(15))
- user.emote("cough")
- user.adjustOxyLoss(15)
-
- //playsound(user.loc, 'sound/effects/smoke.ogg', 10, 1, -3)
-
- user.visible_message("[user] takes a "+ hittext +" from the [src]!", \
- "You take a "+ hittext +" from [src].")
-
- firecharges = firecharges - 1
- if (firecharges == 0)
- bongturnoff()
- if (!reagents.total_volume)
- firecharges = 0
- bongturnoff()
-
-
-
-/obj/item/bong/proc/bongturnon()
- icon_state = icon_on
- set_light(3, 0.8)
-
-/obj/item/bong/proc/bongturnoff()
- icon_state = icon_off
- set_light(0, 0.0)
-
-
-
-/obj/item/bong/coconut
- name = "coconut bong"
- icon_off = "coconut_bong"
- icon_on = "coconut_bong_lit"
- desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo"
+//cleansed 9/15/2012 17:48
+
+/*
+CONTAINS:
+MATCHES
+CIGARETTES
+CIGARS
+SMOKING PIPES
+CHEAP LIGHTERS
+ZIPPO
+
+CIGARETTE PACKETS ARE IN FANCY.DM
+*/
+
+///////////
+//MATCHES//
+///////////
+/obj/item/match
+ name = "match"
+ desc = "A simple match stick, used for lighting fine smokables."
+ icon = 'icons/obj/cigarettes.dmi'
+ icon_state = "match_unlit"
+ var/lit = FALSE
+ var/burnt = FALSE
+ var/smoketime = 5
+ w_class = WEIGHT_CLASS_TINY
+ heat = 1000
+ grind_results = list(/datum/reagent/phosphorus = 2)
+
+/obj/item/match/process()
+ smoketime--
+ if(smoketime < 1)
+ matchburnout()
+ else
+ open_flame(heat)
+
+/obj/item/match/fire_act(exposed_temperature, exposed_volume)
+ matchignite()
+
+/obj/item/match/proc/matchignite()
+ if(!lit && !burnt)
+ lit = TRUE
+ icon_state = "match_lit"
+ damtype = "fire"
+ force = 3
+ hitsound = 'sound/items/welder.ogg'
+ item_state = "cigon"
+ name = "lit match"
+ desc = "A match. This one is lit."
+ attack_verb = list("burnt","singed")
+ START_PROCESSING(SSobj, src)
+ update_icon()
+ playsound(src, 'sound/items/match.ogg', 50, 1, -1)
+
+/obj/item/match/proc/matchburnout()
+ if(lit)
+ lit = FALSE
+ burnt = TRUE
+ damtype = "brute"
+ force = initial(force)
+ icon_state = "match_burnt"
+ item_state = "cigoff"
+ name = "burnt match"
+ desc = "A match. This one has seen better days."
+ attack_verb = list("flicked")
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/match/dropped(mob/user)
+ matchburnout()
+ . = ..()
+
+/obj/item/match/attack(mob/living/carbon/M, mob/living/carbon/user)
+ if(!isliving(M))
+ return
+ if(lit && M.IgniteMob())
+ message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
+ log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
+ var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
+ if(lit && cig && user.a_intent == INTENT_HELP)
+ if(cig.lit)
+ to_chat(user, "[cig] is already lit.")
+ if(M == user)
+ cig.attackby(src, user)
+ else
+ cig.light("[user] holds [src] out for [M], and lights [cig].")
+ else
+ ..()
+
+/obj/item/proc/help_light_cig(mob/living/M)
+ var/mask_item = M.get_item_by_slot(SLOT_WEAR_MASK)
+ if(istype(mask_item, /obj/item/clothing/mask/cigarette))
+ return mask_item
+
+/obj/item/match/is_hot()
+ return lit * heat
+
+//////////////////
+//FINE SMOKABLES//
+//////////////////
+/obj/item/clothing/mask/cigarette
+ name = "cigarette"
+ desc = "A roll of tobacco and nicotine."
+ icon_state = "cigoff"
+ throw_speed = 0.5
+ item_state = "cigoff"
+ w_class = WEIGHT_CLASS_TINY
+ body_parts_covered = null
+ grind_results = list()
+ var/lit = FALSE
+ var/starts_lit = FALSE
+ var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi
+ var/icon_off = "cigoff"
+ var/type_butt = /obj/item/cigbutt
+ var/lastHolder = null
+ var/smoketime = 300
+ var/chem_volume = 30
+ var/list/list_reagents = list(/datum/reagent/drug/nicotine = 15)
+ heat = 1000
+
+/obj/item/clothing/mask/cigarette/suicide_act(mob/user)
+ user.visible_message("[user] is huffing [src] as quickly as [user.p_they()] can! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer.")
+ return (TOXLOSS|OXYLOSS)
+
+/obj/item/clothing/mask/cigarette/Initialize()
+ . = ..()
+ create_reagents(chem_volume, INJECTABLE | NO_REACT) // so it doesn't react until you light it
+ if(list_reagents)
+ reagents.add_reagent_list(list_reagents)
+ if(starts_lit)
+ light()
+ AddComponent(/datum/component/knockoff,90,list(BODY_ZONE_PRECISE_MOUTH),list(SLOT_WEAR_MASK))//90% to knock off when wearing a mask
+
+/obj/item/clothing/mask/cigarette/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ . = ..()
+
+/obj/item/clothing/mask/cigarette/attackby(obj/item/W, mob/user, params)
+ if(!lit && smoketime > 0)
+ var/lighting_text = W.ignition_effect(src, user)
+ if(lighting_text)
+ light(lighting_text)
+ else
+ return ..()
+
+/obj/item/clothing/mask/cigarette/afterattack(obj/item/reagent_containers/glass/glass, mob/user, proximity)
+ . = ..()
+ if(!proximity || lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead)
+ return
+ if(istype(glass)) //you can dip cigarettes into beakers
+ if(glass.reagents.trans_to(src, chem_volume)) //if reagents were transfered, show the message
+ to_chat(user, "You dip \the [src] into \the [glass].")
+ else //if not, either the beaker was empty, or the cigarette was full
+ if(!glass.reagents.total_volume)
+ to_chat(user, "[glass] is empty.")
+ else
+ to_chat(user, "[src] is full.")
+
+
+/obj/item/clothing/mask/cigarette/proc/light(flavor_text = null)
+ if(lit)
+ return
+ if(!(flags_1 & INITIALIZED_1))
+ icon_state = icon_on
+ item_state = icon_on
+ return
+
+ lit = TRUE
+ name = "lit [name]"
+ attack_verb = list("burnt", "singed")
+ hitsound = 'sound/items/welder.ogg'
+ damtype = "fire"
+ force = 4
+ if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
+ var/datum/effect_system/reagents_explosion/e = new()
+ e.set_up(round(reagents.get_reagent_amount(/datum/reagent/toxin/plasma) / 2.5, 1), get_turf(src), 0, 0)
+ e.start()
+ qdel(src)
+ return
+ if(reagents.get_reagent_amount(/datum/reagent/fuel)) // the fuel explodes, too, but much less violently
+ var/datum/effect_system/reagents_explosion/e = new()
+ e.set_up(round(reagents.get_reagent_amount(/datum/reagent/fuel) / 5, 1), get_turf(src), 0, 0)
+ e.start()
+ qdel(src)
+ return
+ // allowing reagents to react after being lit
+ DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
+ reagents.handle_reactions()
+ icon_state = icon_on
+ item_state = icon_on
+ if(flavor_text)
+ var/turf/T = get_turf(src)
+ T.visible_message(flavor_text)
+ START_PROCESSING(SSobj, src)
+
+ //can't think of any other way to update the overlays :<
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_wear_mask()
+ M.update_inv_hands()
+
+
+/obj/item/clothing/mask/cigarette/proc/handle_reagents()
+ if(reagents.total_volume)
+ if(iscarbon(loc))
+ var/mob/living/carbon/C = loc
+ if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob
+ var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1)
+ reagents.reaction(C, INGEST, fraction)
+ if(!reagents.trans_to(C, REAGENTS_METABOLISM))
+ reagents.remove_any(REAGENTS_METABOLISM)
+ return
+ reagents.remove_any(REAGENTS_METABOLISM)
+
+
+/obj/item/clothing/mask/cigarette/process()
+ var/turf/location = get_turf(src)
+ var/mob/living/M = loc
+ if(isliving(loc))
+ M.IgniteMob()
+ smoketime--
+ if(smoketime < 1)
+ new type_butt(location)
+ if(ismob(loc))
+ to_chat(M, "Your [name] goes out.")
+ qdel(src)
+ return
+ open_flame()
+ if(reagents && reagents.total_volume)
+ handle_reagents()
+
+/obj/item/clothing/mask/cigarette/attack_self(mob/user)
+ if(lit)
+ user.visible_message("[user] calmly drops and treads on \the [src], putting it out instantly.")
+ new type_butt(user.loc)
+ qdel(src)
+ . = ..()
+
+/obj/item/clothing/mask/cigarette/attack(mob/living/carbon/M, mob/living/carbon/user)
+ if(!istype(M))
+ return ..()
+ if(M.on_fire && !lit)
+ light("[user] lights [src] with [M]'s burning body. What a cold-blooded badass.")
+ return
+ var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
+ if(lit && cig && user.a_intent == INTENT_HELP)
+ if(cig.lit)
+ to_chat(user, "The [cig.name] is already lit.")
+ if(M == user)
+ cig.attackby(src, user)
+ else
+ cig.light("[user] holds the [name] out for [M], and lights [M.p_their()] [cig.name].")
+ else
+ return ..()
+
+/obj/item/clothing/mask/cigarette/fire_act(exposed_temperature, exposed_volume)
+ light()
+
+/obj/item/clothing/mask/cigarette/is_hot()
+ return lit * heat
+
+// Cigarette brands.
+
+/obj/item/clothing/mask/cigarette/space_cigarette
+ desc = "A Space Cigarette brand cigarette."
+
+/obj/item/clothing/mask/cigarette/dromedary
+ desc = "A DromedaryCo brand cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/silicon = 7.5)
+
+/obj/item/clothing/mask/cigarette/smokekins
+ desc = "A Kinaris Corp brand cigarette"
+ list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/gold = 1)
+
+/obj/item/clothing/mask/cigarette/uplift
+ desc = "An Uplift Smooth brand cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/consumable/menthol = 7.5)
+
+/obj/item/clothing/mask/cigarette/robust
+ desc = "A Robust brand cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/consumable/grenadine = 7.5)
+
+/obj/item/clothing/mask/cigarette/robustgold
+ desc = "A Robust Gold brand cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/gold = 1)
+
+/obj/item/clothing/mask/cigarette/carp
+ desc = "A Carp Classic brand cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 7.5, /datum/reagent/consumable/sodiumchloride = 7.5)
+
+/obj/item/clothing/mask/cigarette/syndicate
+ desc = "An unknown brand cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/medicine/omnizine = 15)
+
+/obj/item/clothing/mask/cigarette/shadyjims
+ desc = "A Shady Jim's Super Slims cigarette."
+ list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/toxin/lipolicide = 4, /datum/reagent/ammonia = 2, /datum/reagent/toxin/plantbgone = 1, /datum/reagent/toxin = 1.5)
+
+/obj/item/clothing/mask/cigarette/xeno
+ desc = "A Xeno Filtered brand cigarette."
+ list_reagents = list (/datum/reagent/drug/nicotine = 20, /datum/reagent/medicine/regen_jelly = 15, /datum/reagent/drug/krokodil = 4)
+
+// Rollies.
+
+/obj/item/clothing/mask/cigarette/rollie
+ name = "rollie"
+ desc = "A roll of dried plant matter wrapped in thin paper."
+ icon_state = "spliffoff"
+ icon_on = "spliffon"
+ icon_off = "spliffoff"
+ type_butt = /obj/item/cigbutt/roach
+ throw_speed = 0.5
+ item_state = "spliffoff"
+ smoketime = 180
+ chem_volume = 50
+ list_reagents = null
+
+/obj/item/clothing/mask/cigarette/rollie/New()
+ ..()
+ src.pixel_x = rand(-5, 5)
+ src.pixel_y = rand(-5, 5)
+
+/obj/item/clothing/mask/cigarette/rollie/nicotine
+ list_reagents = list(/datum/reagent/drug/nicotine = 15)
+
+/obj/item/clothing/mask/cigarette/rollie/trippy
+ list_reagents = list(/datum/reagent/drug/nicotine = 15, /datum/reagent/drug/mushroomhallucinogen = 35)
+ starts_lit = TRUE
+
+/obj/item/clothing/mask/cigarette/rollie/cannabis
+ list_reagents = list(/datum/reagent/drug/space_drugs = 15, /datum/reagent/toxin/lipolicide = 35)
+
+/obj/item/clothing/mask/cigarette/rollie/mindbreaker
+ list_reagents = list(/datum/reagent/toxin/mindbreaker = 35, /datum/reagent/toxin/lipolicide = 15)
+
+/obj/item/cigbutt/roach
+ name = "roach"
+ desc = "A manky old roach, or for non-stoners, a used rollup."
+ icon_state = "roach"
+
+/obj/item/cigbutt/roach/New()
+ ..()
+ src.pixel_x = rand(-5, 5)
+ src.pixel_y = rand(-5, 5)
+
+
+////////////
+// CIGARS //
+////////////
+/obj/item/clothing/mask/cigarette/cigar
+ name = "premium cigar"
+ desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!"
+ icon_state = "cigaroff"
+ icon_on = "cigaron"
+ icon_off = "cigaroff" //make sure to add positional sprites in icons/obj/cigarettes.dmi if you add more.
+ type_butt = /obj/item/cigbutt/cigarbutt
+ throw_speed = 0.5
+ item_state = "cigaroff"
+ smoketime = 1500
+ chem_volume = 40
+
+/obj/item/clothing/mask/cigarette/cigar/cohiba
+ name = "\improper Cohiba Robusto cigar"
+ desc = "There's little more you could want from a cigar."
+ icon_state = "cigar2off"
+ icon_on = "cigar2on"
+ icon_off = "cigar2off"
+ smoketime = 2000
+ chem_volume = 80
+
+
+/obj/item/clothing/mask/cigarette/cigar/havana
+ name = "premium Havanian cigar"
+ desc = "A cigar fit for only the best of the best."
+ icon_state = "cigar2off"
+ icon_on = "cigar2on"
+ icon_off = "cigar2off"
+ smoketime = 7200
+ chem_volume = 50
+
+/obj/item/cigbutt
+ name = "cigarette butt"
+ desc = "A manky old cigarette butt."
+ icon = 'icons/obj/clothing/masks.dmi'
+ icon_state = "cigbutt"
+ w_class = WEIGHT_CLASS_TINY
+ throwforce = 0
+ grind_results = list(/datum/reagent/carbon = 2)
+
+/obj/item/cigbutt/Initialize()
+ . = ..()
+ AddElement(/datum/element/trash)
+
+/obj/item/cigbutt/cigarbutt
+ name = "cigar butt"
+ desc = "A manky old cigar butt."
+ icon_state = "cigarbutt"
+
+/////////////////
+//SMOKING PIPES//
+/////////////////
+/obj/item/clothing/mask/cigarette/pipe
+ name = "smoking pipe"
+ desc = "A pipe, for smoking. Probably made of meerschaum or something."
+ icon_state = "pipeoff"
+ item_state = "pipeoff"
+ icon_on = "pipeon" //Note - these are in masks.dmi
+ icon_off = "pipeoff"
+ smoketime = 0
+ chem_volume = 100
+ list_reagents = null
+ var/packeditem = 0
+
+/obj/item/clothing/mask/cigarette/pipe/Initialize()
+ . = ..()
+ name = "empty [initial(name)]"
+
+/obj/item/clothing/mask/cigarette/pipe/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ . = ..()
+
+/obj/item/clothing/mask/cigarette/pipe/process()
+ var/turf/location = get_turf(src)
+ smoketime--
+ if(smoketime < 1)
+ new /obj/effect/decal/cleanable/ash(location)
+ if(ismob(loc))
+ var/mob/living/M = loc
+ to_chat(M, "Your [name] goes out.")
+ lit = 0
+ icon_state = icon_off
+ item_state = icon_off
+ M.update_inv_wear_mask()
+ packeditem = 0
+ name = "empty [initial(name)]"
+ STOP_PROCESSING(SSobj, src)
+ return
+ open_flame()
+ if(reagents && reagents.total_volume) // check if it has any reagents at all
+ handle_reagents()
+
+
+/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/O, mob/user, params)
+ if(istype(O, /obj/item/reagent_containers/food/snacks/grown))
+ var/obj/item/reagent_containers/food/snacks/grown/G = O
+ if(!packeditem)
+ if(G.dry == 1)
+ to_chat(user, "You stuff [O] into [src].")
+ smoketime = 400
+ packeditem = 1
+ name = "[O.name]-packed [initial(name)]"
+ if(O.reagents)
+ O.reagents.trans_to(src, O.reagents.total_volume)
+ qdel(O)
+ else
+ to_chat(user, "It has to be dried first!")
+ else
+ to_chat(user, "It is already packed!")
+ else
+ var/lighting_text = O.ignition_effect(src,user)
+ if(lighting_text)
+ if(smoketime > 0)
+ light(lighting_text)
+ else
+ to_chat(user, "There is nothing to smoke!")
+ else
+ return ..()
+
+/obj/item/clothing/mask/cigarette/pipe/attack_self(mob/user)
+ var/turf/location = get_turf(user)
+ if(lit)
+ user.visible_message("[user] puts out [src].", "You put out [src].")
+ lit = 0
+ icon_state = icon_off
+ item_state = icon_off
+ STOP_PROCESSING(SSobj, src)
+ return
+ if(!lit && smoketime > 0)
+ to_chat(user, "You empty [src] onto [location].")
+ new /obj/effect/decal/cleanable/ash(location)
+ packeditem = 0
+ smoketime = 0
+ reagents.clear_reagents()
+ name = "empty [initial(name)]"
+ return
+
+/obj/item/clothing/mask/cigarette/pipe/cobpipe
+ name = "corn cob pipe"
+ desc = "A nicotine delivery system popularized by folksy backwoodsmen and kept popular in the modern age and beyond by space hipsters. Can be loaded with objects."
+ icon_state = "cobpipeoff"
+ item_state = "cobpipeoff"
+ icon_on = "cobpipeon" //Note - these are in masks.dmi
+ icon_off = "cobpipeoff"
+ smoketime = 0
+
+
+/////////
+//ZIPPO//
+/////////
+/obj/item/lighter
+ name = "\improper Zippo lighter"
+ desc = "The zippo."
+ icon = 'icons/obj/cigarettes.dmi'
+ icon_state = "zippo"
+ item_state = "zippo"
+ w_class = WEIGHT_CLASS_TINY
+ flags_1 = CONDUCT_1
+ slot_flags = ITEM_SLOT_BELT
+ price = 1
+ var/lit = 0
+ var/fancy = TRUE
+ var/overlay_state
+ var/overlay_list = list(
+ "plain",
+ "dame",
+ "thirteen",
+ "snake"
+ )
+ heat = 1500
+ resistance_flags = FIRE_PROOF
+ light_color = LIGHT_COLOR_FIRE
+ grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5)
+
+/obj/item/lighter/Initialize()
+ . = ..()
+ if(!overlay_state)
+ overlay_state = pick(overlay_list)
+ update_icon()
+
+/obj/item/lighter/AltClick(mob/living/user)
+ . = ..()
+ if(GLOB.lighter_reskins && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
+ reskin_obj(user)
+
+/obj/item/lighter/reskin_obj(mob/M)
+ if(lit)
+ return to_chat(M, "You need to close the lighter before changing the engraving!")
+ if(!LAZYLEN(GLOB.lighter_reskins))
+ return
+
+ var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.lighter_reskins
+ var/new_icon = GLOB.lighter_reskins[choice]
+ if(QDELETED(src) || isnull(new_icon) || new_icon == icon || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ return
+ overlay_state = new_icon
+ update_icon()
+ to_chat(M, "[src] is now skinned as '[choice]'.")
+
+/obj/item/lighter/suicide_act(mob/living/carbon/user)
+ if (lit)
+ user.visible_message("[user] begins holding \the [src]'s flame up to [user.p_their()] face! It looks like [user.p_theyre()] trying to commit suicide!")
+ playsound(src, 'sound/items/welder.ogg', 50, 1)
+ return FIRELOSS
+ else
+ user.visible_message("[user] begins whacking [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return BRUTELOSS
+
+/obj/item/lighter/update_icon()
+ cut_overlays()
+ var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
+ icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
+ add_overlay(lighter_overlay)
+
+/obj/item/lighter/ignition_effect(atom/A, mob/user)
+ if(is_hot())
+ . = "With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool."
+
+/obj/item/lighter/proc/set_lit(new_lit)
+ lit = new_lit
+ if(lit)
+ force = 5
+ damtype = "fire"
+ hitsound = 'sound/items/welder.ogg'
+ attack_verb = list("burnt", "singed")
+ set_light(2, 0.6, LIGHT_COLOR_FIRE)
+ START_PROCESSING(SSobj, src)
+ else
+ hitsound = "swing_hit"
+ force = 0
+ attack_verb = null //human_defense.dm takes care of it
+ set_light(0)
+ STOP_PROCESSING(SSobj, src)
+ update_icon()
+
+/obj/item/lighter/attack_self(mob/living/user)
+ if(user.is_holding(src))
+ if(!lit)
+ set_lit(TRUE)
+ if(fancy)
+ user.visible_message("[user] flips open and lights [src].", "You flip open and light [src] in one smooth movement.")
+ playsound(user, 'sound/items/zippoopen.ogg', 50, 1, -1)
+ else
+ playsound(user, 'sound/items/lighter.ogg', 50, 1, -1)
+ var/prot = FALSE
+ var/mob/living/carbon/human/H = user
+
+ if(istype(H) && H.gloves)
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.max_heat_protection_temperature)
+ prot = (G.max_heat_protection_temperature > 360)
+ else
+ prot = TRUE
+
+ if(prot || prob(75))
+ user.visible_message("After a few attempts, [user] manages to light [src].", "After a few attempts, you manage to light [src].")
+ else
+ var/hitzone = user.held_index_to_dir(user.active_hand_index) == "r" ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND
+ user.apply_damage(5, BURN, hitzone)
+ user.visible_message("After a few attempts, [user] manages to light [src] - however, [user.p_they()] burn [user.p_their()] finger in the process.", "You burn yourself while lighting the lighter!")
+ SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "burnt_thumb", /datum/mood_event/burnt_thumb)
+
+ else
+ set_lit(FALSE)
+ if(fancy)
+ user.visible_message("You hear a quiet click, as [user] shuts off [src].", "You quietly shut off [src].")
+ playsound(user, 'sound/items/zippoclose.ogg', 50, 1, -1)
+ else
+ user.visible_message("[user] quietly shuts off [src].", "You quietly shut off [src].")
+ else
+ . = ..()
+
+/obj/item/lighter/attack(mob/living/carbon/M, mob/living/carbon/user)
+ if(lit && M.IgniteMob())
+ message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
+ log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
+ var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
+ if(lit && cig && user.a_intent == INTENT_HELP)
+ if(cig.lit)
+ to_chat(user, "The [cig.name] is already lit.")
+ if(M == user)
+ cig.attackby(src, user)
+ else
+ if(fancy)
+ cig.light("[user] whips the [name] out and holds it for [M]. [user.p_their(TRUE)] arm is as steady as the unflickering flame [user.p_they()] light[user.p_s()] \the [cig] with.")
+ else
+ cig.light("[user] holds the [name] out for [M], and lights [M.p_their()] [cig.name].")
+ else
+ ..()
+
+/obj/item/lighter/process()
+ open_flame()
+
+/obj/item/lighter/is_hot()
+ return lit * heat
+
+
+/obj/item/lighter/greyscale
+ name = "cheap lighter"
+ desc = "A cheap-as-free lighter."
+ icon_state = "lighter"
+ fancy = FALSE
+ overlay_list = list(
+ "transp",
+ "tall",
+ "matte",
+ "zoppo" //u cant stoppo th zoppo
+ )
+ var/lighter_color
+ var/list/color_list = list( //Same 16 color selection as electronic assemblies
+ COLOR_ASSEMBLY_BLACK,
+ COLOR_FLOORTILE_GRAY,
+ COLOR_ASSEMBLY_BGRAY,
+ COLOR_ASSEMBLY_WHITE,
+ COLOR_ASSEMBLY_RED,
+ COLOR_ASSEMBLY_ORANGE,
+ COLOR_ASSEMBLY_BEIGE,
+ COLOR_ASSEMBLY_BROWN,
+ COLOR_ASSEMBLY_GOLD,
+ COLOR_ASSEMBLY_YELLOW,
+ COLOR_ASSEMBLY_GURKHA,
+ COLOR_ASSEMBLY_LGREEN,
+ COLOR_ASSEMBLY_GREEN,
+ COLOR_ASSEMBLY_LBLUE,
+ COLOR_ASSEMBLY_BLUE,
+ COLOR_ASSEMBLY_PURPLE
+ )
+
+/obj/item/lighter/greyscale/Initialize()
+ . = ..()
+ if(!lighter_color)
+ lighter_color = pick(color_list)
+ update_icon()
+
+/obj/item/lighter/greyscale/update_icon()
+ cut_overlays()
+ var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
+ icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
+ lighter_overlay.color = lighter_color
+ add_overlay(lighter_overlay)
+
+/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user)
+ if(is_hot())
+ . = "After some fiddling, [user] manages to light [A] with [src]."
+
+
+/obj/item/lighter/slime
+ name = "slime zippo"
+ desc = "A specialty zippo made from slimes and industry. Has a much hotter flame than normal."
+ icon_state = "slighter"
+ heat = 3000 //Blue flame!
+ light_color = LIGHT_COLOR_CYAN
+ overlay_state = "slime"
+ grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/medicine/pyroxadone = 5)
+
+
+///////////
+//ROLLING//
+///////////
+/obj/item/rollingpaper
+ name = "rolling paper"
+ desc = "A thin piece of paper used to make fine smokeables."
+ icon = 'icons/obj/cigarettes.dmi'
+ icon_state = "cig_paper"
+ w_class = WEIGHT_CLASS_TINY
+
+/obj/item/rollingpaper/afterattack(atom/target, mob/user, proximity)
+ . = ..()
+ if(!proximity)
+ return
+ if(istype(target, /obj/item/reagent_containers/food/snacks/grown))
+ var/obj/item/reagent_containers/food/snacks/grown/O = target
+ if(O.dry)
+ var/obj/item/clothing/mask/cigarette/rollie/R = new /obj/item/clothing/mask/cigarette/rollie(user.loc)
+ R.chem_volume = target.reagents.total_volume
+ target.reagents.trans_to(R, R.chem_volume)
+ qdel(target)
+ qdel(src)
+ user.put_in_active_hand(R)
+ to_chat(user, "You roll the [target.name] into a rolling paper.")
+ R.desc = "Dried [target.name] rolled up in a thin piece of paper."
+ else
+ to_chat(user, "You need to dry this first!")
+
+///////////////
+//VAPE NATION//
+///////////////
+/obj/item/clothing/mask/vape
+ name = "\improper E-Cigarette"
+ desc = "A classy and highly sophisticated electronic cigarette, for classy and dignified gentlemen. A warning label reads \"Warning: Do not fill with flammable materials.\""//<<< i'd vape to that.
+ icon = 'icons/obj/clothing/masks.dmi'
+ icon_state = null
+ item_state = null
+ w_class = WEIGHT_CLASS_TINY
+ var/chem_volume = 100
+ var/vapetime = FALSE //this so it won't puff out clouds every tick
+ var/screw = FALSE // kinky
+ var/super = FALSE //for the fattest vapes dude.
+
+/obj/item/clothing/mask/vape/suicide_act(mob/user)
+ user.visible_message("[user] is puffin hard on dat vape, [user.p_they()] trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer
+ return (TOXLOSS|OXYLOSS)
+
+
+/obj/item/clothing/mask/vape/Initialize(mapload, param_color)
+ . = ..()
+ create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
+ reagents.add_reagent(/datum/reagent/drug/nicotine, 50)
+ if(!icon_state)
+ if(!param_color)
+ param_color = pick("red","blue","black","white","green","purple","yellow","orange")
+ icon_state = "[param_color]_vape"
+ item_state = "[param_color]_vape"
+
+/obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params)
+ if(O.tool_behaviour == TOOL_SCREWDRIVER)
+ if(!screw)
+ screw = TRUE
+ to_chat(user, "You open the cap on [src].")
+ ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
+ if(obj_flags & EMAGGED)
+ add_overlay("vapeopen_high")
+ else if(super)
+ add_overlay("vapeopen_med")
+ else
+ add_overlay("vapeopen_low")
+ else
+ screw = FALSE
+ to_chat(user, "You close the cap on [src].")
+ DISABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
+ cut_overlays()
+
+ if(O.tool_behaviour == TOOL_MULTITOOL)
+ if(screw && !(obj_flags & EMAGGED))//also kinky
+ if(!super)
+ cut_overlays()
+ super = TRUE
+ to_chat(user, "You increase the voltage of [src].")
+ add_overlay("vapeopen_med")
+ else
+ cut_overlays()
+ super = FALSE
+ to_chat(user, "You decrease the voltage of [src].")
+ add_overlay("vapeopen_low")
+
+ if(screw && (obj_flags & EMAGGED))
+ to_chat(user, "[src] can't be modified!")
+
+ else
+ ..()
+
+/obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY.
+ if(screw)
+ if(!(obj_flags & EMAGGED))
+ cut_overlays()
+ obj_flags |= EMAGGED
+ super = FALSE
+ to_chat(user, "You maximize the voltage of [src].")
+ add_overlay("vapeopen_high")
+ var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect
+ sp.set_up(5, 1, src)
+ sp.start()
+ else
+ to_chat(user, "[src] is already emagged!")
+ else
+ to_chat(user, "You need to open the cap to do that.")
+
+/obj/item/clothing/mask/vape/attack_self(mob/user)
+ if(reagents.total_volume > 0)
+ to_chat(user, "You empty [src] of all reagents.")
+ reagents.clear_reagents()
+
+/obj/item/clothing/mask/vape/equipped(mob/user, slot)
+ if(slot == SLOT_WEAR_MASK)
+ if(!screw)
+ to_chat(user, "You start puffing on the vape.")
+ DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
+ START_PROCESSING(SSobj, src)
+ else //it will not start if the vape is opened.
+ to_chat(user, "You need to close the cap first!")
+
+/obj/item/clothing/mask/vape/dropped(mob/user)
+ var/mob/living/carbon/C = user
+ if(C.get_item_by_slot(SLOT_WEAR_MASK) == src)
+ ENABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/clothing/mask/vape/proc/hand_reagents()//had to rename to avoid duplicate error
+ if(reagents.total_volume)
+ if(iscarbon(loc))
+ var/mob/living/carbon/C = loc
+ if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob
+ var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1) //this will react instantly, making them a little more dangerous than cigarettes
+ reagents.reaction(C, INGEST, fraction)
+ if(!reagents.trans_to(C, REAGENTS_METABOLISM))
+ reagents.remove_any(REAGENTS_METABOLISM)
+ if(reagents.get_reagent_amount(/datum/reagent/fuel))
+ //HOT STUFF
+ C.fire_stacks = 2
+ C.IgniteMob()
+
+ if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
+ var/datum/effect_system/reagents_explosion/e = new()
+ e.set_up(round(reagents.get_reagent_amount(/datum/reagent/toxin/plasma) / 2.5, 1), get_turf(src), 0, 0)
+ e.start()
+ qdel(src)
+ return
+ reagents.remove_any(REAGENTS_METABOLISM)
+
+/obj/item/clothing/mask/vape/process()
+ var/mob/living/M = loc
+
+ if(isliving(loc))
+ M.IgniteMob()
+
+ vapetime++
+
+ if(!reagents.total_volume)
+ if(ismob(loc))
+ to_chat(M, "[src] is empty!")
+ STOP_PROCESSING(SSobj, src)
+ //it's reusable so it won't unequip when empty
+ return
+ //open flame removed because vapes are a closed system, they wont light anything on fire
+
+ if(super && vapetime > 3)//Time to start puffing those fat vapes, yo.
+ var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
+ s.set_up(reagents, 1, 24, loc)
+ s.start()
+ vapetime = 0
+
+ if((obj_flags & EMAGGED) && vapetime > 3)
+ var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
+ s.set_up(reagents, 4, 24, loc)
+ s.start()
+ vapetime = 0
+ if(prob(5))//small chance for the vape to break and deal damage if it's emagged
+ playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, 0)
+ M.apply_damage(20, BURN, BODY_ZONE_HEAD)
+ M.Knockdown(300, 1, 0)
+ var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread
+ sp.set_up(5, 1, src)
+ sp.start()
+ to_chat(M, "[src] suddenly explodes in your mouth!")
+ qdel(src)
+ return
+
+ if(reagents && reagents.total_volume)
+ hand_reagents()
+
+///////////////
+/////BONGS/////
+///////////////
+
+/obj/item/bong
+ name = "bong"
+ desc = "A water bong used for smoking dried plants."
+ icon = 'icons/obj/bongs.dmi'
+ icon_state = null
+ item_state = null
+ w_class = WEIGHT_CLASS_NORMAL
+ light_color = "#FFCC66"
+ var/icon_off = "bong"
+ var/icon_on = "bong_lit"
+ var/chem_volume = 100
+ var/last_used_time //for cooldown
+ var/firecharges = 0 //used for counting how many hits can be taken before the flame goes out
+ var/list/list_reagents = list() //For the base reagents bongs could get
+
+
+/obj/item/bong/Initialize()
+ . = ..()
+ create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
+ reagents.add_reagent_list(list_reagents)
+ icon_state = icon_off
+
+/obj/item/bong/attackby(obj/item/O, mob/user, params)
+ . = ..()
+ //If we're using a dried plant..
+ if(istype(O,/obj/item/reagent_containers/food/snacks))
+ var/obj/item/reagent_containers/food/snacks/DP = O
+ if (DP.dry)
+ //Nothing if our bong is full
+ if (reagents.holder_full())
+ user.show_message("The bowl is full!", 1)
+ return
+
+ //Transfer reagents and remove the plant
+ user.show_message("You stuff the [DP] into the [src]'s bowl.", 1)
+ DP.reagents.trans_to(src, 100)
+ qdel(DP)
+ return
+ else
+ user.show_message("[DP] must be dried first!", 1)
+ return
+
+ if (O.heat > 500)
+ if (reagents && reagents.total_volume) //if there's stuff in the bong
+ var/lighting_text = O.ignition_effect(src, user)
+ if(lighting_text)
+ //Logic regarding igniting it on
+ if (firecharges == 0)
+ user.show_message("You light the [src] with the [O]!", 1)
+ bongturnon()
+ else
+ user.show_message("You rekindle [src]'s flame with the [O]!", 1)
+
+ firecharges = 1
+ return
+ else
+ user.show_message("There's nothing to light up in the bowl.", 1)
+ return
+
+/obj/item/bong/CtrlShiftClick(mob/user) //empty reagents on alt click
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+
+ if (reagents && reagents.total_volume)
+ user.show_message("You empty the [src].", 1)
+ reagents.clear_reagents()
+ if(firecharges)
+ firecharges = 0
+ bongturnoff()
+ else
+ user.show_message("The [src] is already empty.", 1)
+
+/obj/item/bong/AltClick(mob/user)
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+
+ if(firecharges)
+ firecharges = 0
+ bongturnoff()
+ user.show_message("You quench the flame.", 1)
+
+/obj/item/bong/examine(mob/user)
+ . = ..()
+ if(!reagents.total_volume)
+ . += "The bowl is empty."
+ else if (reagents.total_volume > 80)
+ . += "The bowl is filled to the brim."
+ else if (reagents.total_volume > 40)
+ . += "The bowl has plenty weed in it."
+ else
+ . += "The bowl has some weed in it."
+
+ . += "Ctrl+Shift-click to empty."
+ . += "Alt-click to extinguish."
+
+/obj/item/bong/ignition_effect(atom/A, mob/user)
+ if(firecharges)
+ . = "[user] lights [A] off of the [src]."
+ else
+ . = ""
+
+/obj/item/bong/attack(mob/living/carbon/M, mob/living/carbon/user, obj/target)
+ //if it's lit up, some stuff in the bowl and the user is a target, and we're not on cooldown
+ if (!reagents)
+ return
+
+ if (M ==! user)
+ return
+
+ if(user.is_mouth_covered(head_only = 1))
+ to_chat(user, "Remove your headgear first.")
+ return
+
+ if(user.is_mouth_covered(mask_only = 1))
+ to_chat(user, "Remove your mask first.")
+ return
+
+ if (!reagents.total_volume)
+ to_chat(user, "There's nothing in the bowl.")
+ return
+
+ if (!firecharges)
+ to_chat(user, "You have to light it up first.")
+ return
+
+ if (last_used_time + 30 < world.time)
+ var/hit_strength
+ var/noise
+ var/hittext = ""
+ //if the intent is help then you take a small hit, else a big one
+ if (user.a_intent == INTENT_HARM)
+ hit_strength = 2
+ noise = 100
+ hittext = "big hit"
+ else
+ hit_strength = 1
+ noise = 70
+ hittext = "hit"
+ //bubbling sound
+ playsound(user.loc,'sound/effects/bonghit.ogg', noise, 1)
+
+ last_used_time = world.time
+
+ //message
+ user.visible_message("[user] begins to take a "+ hittext +" from the [src]!", \
+ "You begin to take a "+ hittext +" from [src].")
+
+ //we take a hit here, after an uninterrupted delay
+ if(do_after(user, 25, target = user))
+ if (reagents && reagents.total_volume)
+ var/fraction = 12 * hit_strength
+
+ var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
+ s.set_up(reagents, hit_strength, 18, user.loc)
+ s.start()
+
+ reagents.reaction(user, INGEST, fraction)
+ if(!reagents.trans_to(user, fraction))
+ reagents.remove_any(fraction)
+
+ if (hit_strength == 2 && prob(15))
+ user.emote("cough")
+ user.adjustOxyLoss(15)
+
+ //playsound(user.loc, 'sound/effects/smoke.ogg', 10, 1, -3)
+
+ user.visible_message("[user] takes a "+ hittext +" from the [src]!", \
+ "You take a "+ hittext +" from [src].")
+
+ firecharges = firecharges - 1
+ if (firecharges == 0)
+ bongturnoff()
+ if (!reagents.total_volume)
+ firecharges = 0
+ bongturnoff()
+
+
+
+/obj/item/bong/proc/bongturnon()
+ icon_state = icon_on
+ set_light(3, 0.8)
+
+/obj/item/bong/proc/bongturnoff()
+ icon_state = icon_off
+ set_light(0, 0.0)
+
+
+
+/obj/item/bong/coconut
+ name = "coconut bong"
+ icon_off = "coconut_bong"
+ icon_on = "coconut_bong_lit"
+ desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo"
diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm
index f21b26014..55de19dba 100644
--- a/code/game/objects/items/trash.dm
+++ b/code/game/objects/items/trash.dm
@@ -1,89 +1,90 @@
-//Added by Jack Rost
-/obj/item/trash
- icon = 'icons/obj/janitor.dmi'
- lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
- desc = "This is rubbish."
- w_class = WEIGHT_CLASS_TINY
- resistance_flags = FLAMMABLE
-
-/obj/item/trash/raisins
- name = "\improper 4no raisins"
- icon_state= "4no_raisins"
-
-/obj/item/trash/candy
- name = "candy"
- icon_state= "candy"
-
-/obj/item/trash/cheesie
- name = "cheesie honkers"
- icon_state = "cheesie_honkers"
-
-/obj/item/trash/chips
- name = "chips"
- icon_state = "chips"
-
-/obj/item/trash/popcorn
- name = "popcorn"
- icon_state = "popcorn"
-
-/obj/item/trash/sosjerky
- name = "\improper Scaredy's Private Reserve Beef Jerky"
- icon_state = "sosjerky"
-
-/obj/item/trash/syndi_cakes
- name = "syndi-cakes"
- icon_state = "syndi_cakes"
-
-/obj/item/trash/waffles
- name = "waffles tray"
- icon_state = "waffles"
-
-/obj/item/trash/plate
- name = "plate"
- icon_state = "plate"
- resistance_flags = NONE
-
-/obj/item/trash/pistachios
- name = "pistachios pack"
- icon_state = "pistachios_pack"
-
-/obj/item/trash/semki
- name = "semki pack"
- icon_state = "semki_pack"
-
-/obj/item/trash/tray
- name = "tray"
- icon_state = "tray"
- resistance_flags = NONE
-
-/obj/item/trash/candle
- name = "candle"
- icon = 'icons/obj/candle.dmi'
- icon_state = "candle4"
-
-/obj/item/trash/can
- name = "crushed can"
- icon_state = "cola"
- resistance_flags = NONE
- grind_results = list(/datum/reagent/aluminium = 10)
-
-/obj/item/trash/boritos
- name = "boritos bag"
- icon_state = "boritos"
- grind_results = list(/datum/reagent/aluminium = 1) //from the mylar bag
-
-/obj/item/trash/soy_food
- name = "soyfood"
- icon_state = "soy_food"
-
-/obj/item/trash/carbonnanotube_noodles
- name = "carbon nanotube noodles"
- icon_state = "carbonnanotube_noodles"
-
-/obj/item/trash/bird_seed
- name = "Sunflower Seeds"
- icon_state = "seedtrash"
-
-/obj/item/trash/attack(mob/M, mob/living/user)
- return
+//Added by Jack Rost
+/obj/item/trash
+ icon = 'icons/obj/janitor.dmi'
+ lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
+ desc = "This is rubbish."
+ w_class = WEIGHT_CLASS_TINY
+ resistance_flags = FLAMMABLE
+
+/obj/item/trash/Initialize()
+ . = ..()
+ AddElement(/datum/element/trash)
+
+/obj/item/trash/raisins
+ name = "\improper 4no raisins"
+ icon_state= "4no_raisins"
+
+/obj/item/trash/candy
+ name = "candy"
+ icon_state= "candy"
+
+/obj/item/trash/cheesie
+ name = "cheesie honkers"
+ icon_state = "cheesie_honkers"
+
+/obj/item/trash/chips
+ name = "chips"
+ icon_state = "chips"
+
+/obj/item/trash/popcorn
+ name = "popcorn"
+ icon_state = "popcorn"
+
+/obj/item/trash/sosjerky
+ name = "\improper Scaredy's Private Reserve Beef Jerky"
+ icon_state = "sosjerky"
+
+/obj/item/trash/syndi_cakes
+ name = "syndi-cakes"
+ icon_state = "syndi_cakes"
+
+/obj/item/trash/waffles
+ name = "waffles tray"
+ icon_state = "waffles"
+
+/obj/item/trash/plate
+ name = "plate"
+ icon_state = "plate"
+ resistance_flags = NONE
+
+/obj/item/trash/pistachios
+ name = "pistachios pack"
+ icon_state = "pistachios_pack"
+
+/obj/item/trash/semki
+ name = "semki pack"
+ icon_state = "semki_pack"
+
+/obj/item/trash/tray
+ name = "tray"
+ icon_state = "tray"
+ resistance_flags = NONE
+
+/obj/item/trash/candle
+ name = "candle"
+ icon = 'icons/obj/candle.dmi'
+ icon_state = "candle4"
+
+/obj/item/trash/can
+ name = "crushed can"
+ icon_state = "cola"
+ resistance_flags = NONE
+ grind_results = list(/datum/reagent/aluminium = 10)
+
+/obj/item/trash/boritos
+ name = "boritos bag"
+ icon_state = "boritos"
+ grind_results = list(/datum/reagent/aluminium = 1) //from the mylar bag
+
+/obj/item/trash/soy_food
+ name = "soyfood"
+ icon_state = "soy_food"
+
+/obj/item/trash/carbonnanotube_noodles
+ name = "carbon nanotube noodles"
+ icon_state = "carbonnanotube_noodles"
+
+/obj/item/trash/bird_seed
+ name = "Sunflower Seeds"
+ icon_state = "seedtrash"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 848c8a3bc..822d72abe 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1196,6 +1196,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
"
dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
"
dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
"
+ dat += "Allow trash forcefeeding (requires Trashcan quirk) [(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]
"
dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]
"
dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]
"
dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]
"
@@ -2742,7 +2743,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("toggledigestionnoise")
cit_toggles ^= DIGESTION_NOISES
-
+
+ if("toggleforcefeedtrash")
+ cit_toggles ^= TRASH_FORCEFEED
+
if("breast_enlargement")
cit_toggles ^= BREAST_ENLARGEMENT
diff --git a/tgstation.dme b/tgstation.dme
index eacff3297..50cd554fb 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -492,6 +492,7 @@
#include "code\datums\elements\mob_holder.dm"
#include "code\datums\elements\squish.dm"
#include "code\datums\elements\swimming.dm"
+#include "code\datums\elements\trash.dm"
#include "code\datums\elements\wuv.dm"
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"