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"