Burning paper (and similar) is now two way (you can hold a paper to your cigarette to burn it) (#90307)

## About The Pull Request

1. Burning paper (and similar) is now two way - rather than
necessitating you touch the paper with the burning thing, you can now
touch the burning thing with the paper

2. You can now light a cigarette on a lit candle

3. Candles no longer craft into flashlight eyes

## Why It's Good For The Game

1. Burning money with a cigarette larp 

2. Cool Frenchman larp

3. ??? I noticed you can't light a candle with a candle because it tried
to craft flashlight eyes.

## Changelog

🆑 Melbert
qol: Burning paper (and similar) is now two way. Rather than needing to
click on the paper with a burning item, you can now click on a burning
item with the paper. This means you can burn paper on your lit cigarette
like a badass.
qol: You can now light cigarettes on candles. 
del: Flares and candles can no longer craft into flashlight eyes, I
guess.
/🆑
This commit is contained in:
MrMelbert
2025-04-29 17:08:46 -06:00
committed by Shadow-Quill
parent f357561812
commit 86eee7d521
14 changed files with 176 additions and 102 deletions
@@ -95,3 +95,6 @@
/// signal sent when a mouse is hovering over us, sent by atom/proc/on_mouse_entered
#define COMSIG_ATOM_MOUSE_ENTERED "mouse_entered"
/// Sent from [/datum/element/burn_on_item_ignition] to an atom being ignited by something: (mob/living/user, obj/item/burning_thing)
#define COMSIG_ATOM_IGNITED_BY_ITEM "atom_ignited_by_item"
@@ -164,6 +164,10 @@
)
category = CAT_EQUIPMENT
/datum/crafting_recipe/flashlight_eyes/New()
. = ..()
blacklist += typesof(/obj/item/flashlight/flare)
/datum/crafting_recipe/extendohand_r
name = "Extendo-Hand (Right Arm)"
reqs = list(
@@ -0,0 +1,68 @@
/**
* This item will be set on fire if a mob clicks on it with something that can ignite objects,
* OR if a mob clicks it on something else that can ignite objects.
*/
/datum/element/burn_on_item_ignition
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
/// If TRUE clumsy people can't burn themselves
var/bypass_clumsy = FALSE
/datum/element/burn_on_item_ignition/Attach(datum/target, bypass_clumsy = FALSE)
. = ..()
src.bypass_clumsy = bypass_clumsy
RegisterSignal(target, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(try_burn))
RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(try_hold_burn))
/datum/element/burn_on_item_ignition/Detach(datum/target)
. = ..()
UnregisterSignal(target, COMSIG_ATOM_ITEM_INTERACTION)
UnregisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM)
/datum/element/burn_on_item_ignition/proc/try_burn(atom/source, mob/living/user, obj/item/tool, list/modifiers)
SIGNAL_HANDLER
//can't be put on fire!
if((source.resistance_flags & FIRE_PROOF) || !(source.resistance_flags & FLAMMABLE))
return NONE
//already on fire!
if(source.resistance_flags & ON_FIRE)
return NONE
var/ignition_message = tool.ignition_effect(source, user)
if(!ignition_message)
return NONE
if(!bypass_clumsy && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && source.Adjacent(user))
if(user.is_holding(tool)) //checking if they're holding it in case TK is involved
user.dropItemToGround(tool)
var/firestacks = tool.get_temperature() / 200
user.adjust_fire_stacks(clamp(firestacks, 1, 10))
user.apply_damage(clamp(firestacks, 4, 12), BURN, user.get_active_hand(), attacking_item = tool)
user.ignite_mob()
if(user.on_fire)
user.visible_message(
span_warning("[user] accidentally ignites [user.p_them()]self!"),
span_userdanger("You miss [src] and accidentally light yourself on fire!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
user.visible_message(
span_warning("[user] accidentally burns [user.p_them()]self!"),
span_userdanger("You miss [src] and accidentally burn yourself!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
return ITEM_INTERACT_SUCCESS
if(user.is_holding(source)) //no TK shit here.
user.dropItemToGround(source)
source.add_fingerprint(user)
user.visible_message(ignition_message)
source.fire_act(tool.get_temperature())
SEND_SIGNAL(source, COMSIG_ATOM_IGNITED_BY_ITEM, user, tool)
return ITEM_INTERACT_SUCCESS
// Represents holding a paper over a cigarette like a badass
/datum/element/burn_on_item_ignition/proc/try_hold_burn(atom/source, mob/living/user, atom/interacting_with, list/modifiers)
SIGNAL_HANDLER
return try_burn(source, user, interacting_with, modifiers)
+8 -4
View File
@@ -54,6 +54,8 @@
saved_wanted_body = GLOB.news_network.wanted_issue.body
if(GLOB.news_network.wanted_issue.img)
saved_wanted_icon = GLOB.news_network.wanted_issue.img
AddElement(/datum/element/burn_on_item_ignition)
RegisterSignal(src, COMSIG_ATOM_IGNITED_BY_ITEM, PROC_REF(close_paper_ui))
/obj/item/newspaper/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(held_item)
@@ -64,6 +66,10 @@
context[SCREENTIP_CONTEXT_LMB] = "Burn"
return CONTEXTUAL_SCREENTIP_SET
/obj/item/newspaper/proc/close_paper_ui()
SIGNAL_HANDLER
SStgui.close_uis(src)
/obj/item/newspaper/suicide_act(mob/living/user)
user.visible_message(span_suicide(\
"[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... \
@@ -77,10 +83,6 @@
return TOXLOSS
/obj/item/newspaper/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if (burn_paper_product_attackby_check(tool, user))
SStgui.close_uis(src)
return ITEM_INTERACT_SKIP_TO_ATTACK
if (tool.tool_behaviour == TOOL_SCREWDRIVER || tool.tool_behaviour == TOOL_WIRECUTTER || tool.sharpness)
if (punctured)
balloon_alert(user, "already has holes!")
@@ -190,6 +192,8 @@
identity[VISIBLE_NAME_ID] = ""
/obj/item/newspaper/ui_interact(mob/user, datum/tgui/ui)
if(resistance_flags & ON_FIRE)
return
ui = SStgui.try_update_ui(user, src, ui)
if(ui)
return
+50 -30
View File
@@ -44,7 +44,9 @@
set_light_on(TRUE)
update_brightness()
register_context()
init_slapcrafting()
/obj/item/flashlight/proc/init_slapcrafting()
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/flashlight_eyes)
AddElement(
@@ -446,20 +448,21 @@
damtype = BURN
update_brightness()
/obj/item/flashlight/flare/init_slapcrafting()
return
/obj/item/flashlight/flare/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/flashlight/flare/attack(mob/living/carbon/victim, mob/living/carbon/user)
if(!isliving(victim))
return ..()
if(light_on && victim.ignite_mob())
/obj/item/flashlight/flare/afterattack(atom/target, mob/user, click_parameters)
if(!isliving(target))
return
var/mob/living/victim = target
if(get_temperature() && victim.ignite_mob())
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(victim)] on fire with [src] at [AREACOORD(user)]")
user.log_message("set [key_name(victim)] on fire with [src]", LOG_ATTACK)
return ..()
/obj/item/flashlight/flare/toggle_light()
if(light_on || !fuel)
return FALSE
@@ -593,10 +596,8 @@
* Arguments:
* * obj/item/fire_starter - the item being used to ignite the candle.
* * mob/user - the user to display a message to.
* * quiet - suppresses the to_chat message.
* * silent - suppresses the balloon alerts as well as the to_chat message.
*/
/obj/item/flashlight/flare/candle/proc/try_light_candle(obj/item/fire_starter, mob/user, quiet, silent)
/obj/item/flashlight/flare/candle/proc/try_light_candle(obj/item/fire_starter, mob/user)
if(!istype(fire_starter))
return
if(!istype(user))
@@ -611,34 +612,53 @@
switch(ignition_result)
if(SUCCESS)
update_appearance(UPDATE_ICON | UPDATE_NAME)
if(!quiet && !silent)
user.visible_message(success_msg)
user.visible_message(success_msg)
return SUCCESS
if(ALREADY_LIT)
if(!silent)
balloon_alert(user, "already lit!")
balloon_alert(user, "already lit!")
return ALREADY_LIT
if(NO_FUEL)
if(!silent)
balloon_alert(user, "out of fuel!")
balloon_alert(user, "out of fuel!")
return NO_FUEL
/// allows lighting an unlit candle from some fire source by left clicking the candle with the source
/obj/item/flashlight/flare/candle/attackby(obj/item/attacking_item, mob/user, params)
if(try_light_candle(attacking_item, user, silent = istype(attacking_item, src.type))) // so we don't double balloon alerts when a candle is used to light another candle
return COMPONENT_CANCEL_ATTACK_CHAIN
else
return ..()
/obj/item/flashlight/flare/candle/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(get_temperature())
if(istype(tool, /obj/item/cigarette))
var/obj/item/cigarette/cig = tool
if(cig.lit)
return NONE
cig.light()
if(cig.loc == user)
user.visible_message(
span_rose("[user] holds [user.p_their()] [cig.name] to [src] and lights it, like a true romantic."),
span_rose("You hold your [cig.name] to [src] and light it, like a true romantic."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
user.visible_message(
span_rose("[user] lights [cig] with [src], like a true romantic."),
span_rose("You light [cig] with [src], like a true romantic."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
return ITEM_INTERACT_SUCCESS
return NONE
if(try_light_candle(tool, user))
return ITEM_INTERACT_SUCCESS
return NONE
// allows lighting an unlit candle from some fire source by left clicking the source with the candle
/obj/item/flashlight/flare/candle/pre_attack(atom/target, mob/living/user, params)
if(ismob(target))
return ..()
/obj/item/flashlight/flare/candle/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(get_temperature())
return NONE
if(try_light_candle(interacting_with, user))
return ITEM_INTERACT_SUCCESS
return NONE
if(try_light_candle(target, user, quiet = TRUE))
return COMPONENT_CANCEL_ATTACK_CHAIN
return ..()
/obj/item/flashlight/flare/candle/ignition_effect(atom/A, mob/user)
if(!get_temperature())
return ""
if(isitem(A) && A.loc == user)
return span_rose("[user] holds [A] in the flame of [src], letting it catch fire.")
return span_rose("[user] lights [A] ablaze with [src], like a true romantic.")
/obj/item/flashlight/flare/candle/attack_self(mob/user)
if(light_on && (fuel != INFINITY || !can_be_extinguished)) // can't extinguish eternal candles
+13 -9
View File
@@ -7,20 +7,24 @@
///Has this item been used already.
var/used_up = FALSE
#define NICKNAME_CAP (MAX_NAME_LEN/2)
/obj/item/virgin_mary/attackby(obj/item/potential_lighter, mob/living/user, params)
/obj/item/virgin_mary/Initialize(mapload)
. = ..()
if(resistance_flags & ON_FIRE)
return
if(!istype(user) || !user.mind) //A sentient mob needs to be burning it, ya cheezit.
return
AddElement(/datum/element/burn_on_item_ignition, bypass_clumsy = TRUE)
RegisterSignal(src, COMSIG_ATOM_IGNITED_BY_ITEM, PROC_REF(induct_new_initiate))
#define NICKNAME_CAP (MAX_NAME_LEN/2)
/obj/item/virgin_mary/proc/induct_new_initiate(datum/source, mob/living/user, obj/item/burning_tool)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(induct_new_initiate_async), user, burning_tool)
/obj/item/virgin_mary/proc/induct_new_initiate_async(mob/living/user, obj/item/burning_tool)
if(isnull(user.mind))
return
if(HAS_TRAIT(user, TRAIT_MAFIAINITIATE)) //Only one nickname fuckhead
to_chat(user, span_warning("You have already been initiated into the mafioso life."))
return
if(!burn_paper_product_attackby_check(potential_lighter, user, TRUE))
return
if(used_up)
return
+14 -13
View File
@@ -87,6 +87,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
on_intercepted = CALLBACK(src, PROC_REF(on_intercepted_bullet)),\
block_charges = 1,\
)
RegisterSignal(src, COMSIG_ATOM_IGNITED_BY_ITEM, PROC_REF(curse_heathen))
/// Destroy the bible when it's shot by a bullet
/obj/item/book/bible/proc/on_intercepted_bullet(mob/living/victim, obj/projectile/bullet)
@@ -113,22 +114,22 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
else
. += span_notice("[src] can be unpacked by hitting the floor of a holy area with it.")
/obj/item/book/bible/burn_paper_product_attackby_check(obj/item/attacking_item, mob/living/user, bypass_clumsy)
. = ..()
/obj/item/book/bible/proc/curse_heathen(datum/source, mob/living/user, obj/item/burning_tool)
SIGNAL_HANDLER
// no deity to cast a curse upon thee
if(!deity_name)
return
if(. && (resistance_flags & ON_FIRE))
var/datum/component/omen/existing_omen = user.GetComponent(/datum/component/omen)
//DOUBLE CURSED?! Just straight up gib the guy.
if(existing_omen)
to_chat(user, span_userdanger("[deity_name] <b>SMITE</b> thee!"))
add_memory_in_range(user, 7, /datum/memory/witnessed_gods_wrath, protagonist = user, deuteragonist = src, antagonist = deity_name)
user.client?.give_award(/datum/award/achievement/misc/gods_wrath, user)
user.gib(DROP_ALL_REMAINS)
else
to_chat(user, span_userdanger("[deity_name] cast a curse upon thee!"))
user.AddComponent(/datum/component/omen/bible)
var/datum/component/omen/existing_omen = user.GetComponent(/datum/component/omen)
//DOUBLE CURSED?! Just straight up gib the guy.
if(existing_omen)
to_chat(user, span_userdanger("[deity_name] <b>SMITE</b> thee!"))
add_memory_in_range(user, 7, /datum/memory/witnessed_gods_wrath, protagonist = user, deuteragonist = src, antagonist = deity_name)
user.client?.give_award(/datum/award/achievement/misc/gods_wrath, user)
user.gib(DROP_ALL_REMAINS)
else
to_chat(user, span_userdanger("[deity_name] cast a curse upon thee!"))
user.AddComponent(/datum/component/omen/bible)
/obj/item/book/bible/carve_out(obj/item/carving_item, mob/living/user)
. = ..()
+1 -3
View File
@@ -35,6 +35,7 @@
book_data = new(starting_title, starting_author, starting_content)
AddElement(/datum/element/falling_hazard, damage = 5, wound_bonus = 0, hardhat_safety = TRUE, crushes = FALSE, impact_sound = drop_sound)
AddElement(/datum/element/burn_on_item_ignition)
/obj/item/book/examine(mob/user)
. = ..()
@@ -98,9 +99,6 @@
display_content(user)
/obj/item/book/attackby(obj/item/attacking_item, mob/living/user, params)
if(burn_paper_product_attackby_check(attacking_item, user))
return
if(IS_WRITING_UTENSIL(attacking_item))
if(!user.can_perform_action(src) || !user.can_write(attacking_item))
return
+1 -2
View File
@@ -27,6 +27,7 @@
/obj/item/folder/Initialize(mapload)
update_icon()
. = ..()
AddElement(/datum/element/burn_on_item_ignition)
/obj/item/folder/Destroy()
for(var/obj/important_thing in contents)
@@ -79,8 +80,6 @@
return paper_overlay
/obj/item/folder/attackby(obj/item/weapon, mob/user, params)
if(burn_paper_product_attackby_check(weapon, user))
return
if(is_type_in_typecache(weapon, folder_insertables))
//Add paper, photo or documents into the folder
if(!user.transferItemToLoc(weapon, src))
+9 -30
View File
@@ -79,6 +79,9 @@
if(can_become_message_in_bottle && !mapload && prob(MESSAGE_BOTTLE_CHANCE))
LAZYADD(SSpersistence.queued_message_bottles, src)
AddElement(/datum/element/burn_on_item_ignition)
RegisterSignal(src, COMSIG_ATOM_IGNITED_BY_ITEM, PROC_REF(close_paper_ui))
/obj/item/paper/Destroy()
camera_holder = null
clear_paper()
@@ -90,6 +93,10 @@
custom_fire_overlay = mutable_appearance('icons/obj/service/bureaucracy.dmi', "paper_onfire_overlay", appearance_flags = RESET_COLOR|KEEP_APART)
return custom_fire_overlay
/obj/item/paper/proc/close_paper_ui()
SIGNAL_HANDLER
SStgui.close_uis(src)
/// Determines whether this paper has been written or stamped to.
/obj/item/paper/proc/is_empty()
return !(LAZYLEN(raw_text_inputs) || LAZYLEN(raw_stamp_data))
@@ -407,37 +414,7 @@
user.put_in_hands(new_plane)
return new_plane
/obj/item/proc/burn_paper_product_attackby_check(obj/item/attacking_item, mob/living/user, bypass_clumsy = FALSE)
//can't be put on fire!
if((resistance_flags & FIRE_PROOF) || !(resistance_flags & FLAMMABLE))
return FALSE
//already on fire!
if(resistance_flags & ON_FIRE)
return FALSE
var/ignition_message = attacking_item.ignition_effect(src, user)
if(!ignition_message)
return FALSE
if(!bypass_clumsy && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && Adjacent(user))
user.visible_message(span_warning("[user] accidentally ignites [user.p_them()]self!"), \
span_userdanger("You miss [src] and accidentally light yourself on fire!"))
if(user.is_holding(attacking_item)) //checking if they're holding it in case TK is involved
user.dropItemToGround(attacking_item)
user.adjust_fire_stacks(attacking_item)
user.ignite_mob()
return TRUE
if(user.is_holding(src)) //no TK shit here.
user.dropItemToGround(src)
user.visible_message(ignition_message)
add_fingerprint(user)
fire_act(attacking_item.get_temperature())
return TRUE
/obj/item/paper/attackby(obj/item/attacking_item, mob/living/user, params)
if(burn_paper_product_attackby_check(attacking_item, user))
SStgui.close_uis(src)
return
// Enable picking paper up by clicking on it with the clipboard or folder
if(istype(attacking_item, /obj/item/clipboard) || istype(attacking_item, /obj/item/folder) || istype(attacking_item, /obj/item/paper_bin))
attacking_item.attackby(src, user)
@@ -530,6 +507,8 @@
)
/obj/item/paper/ui_interact(mob/user, datum/tgui/ui)
if(resistance_flags & ON_FIRE)
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PaperSheet", name)
+1 -2
View File
@@ -46,6 +46,7 @@
if(istype(internal_paper, /obj/item/paper/carbon_copy))
icon_state = "[base_icon_state]_carbon"
update_appearance(UPDATE_ICON)
AddElement(/datum/element/burn_on_item_ignition)
/obj/item/paperplane/Exited(atom/movable/gone, direction)
. = ..()
@@ -91,8 +92,6 @@
user.put_in_hands(released_paper)
/obj/item/paperplane/attackby(obj/item/attacking_item, mob/user, params)
if(burn_paper_product_attackby_check(attacking_item, user))
return
if(IS_WRITING_UTENSIL(attacking_item))
to_chat(user, span_warning("You should unfold [src] before changing it!"))
return
+1 -6
View File
@@ -253,6 +253,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
name += " #[num]"
saved_maptext = MAPTEXT(num)
maptext = saved_maptext
AddElement(/datum/element/burn_on_item_ignition)
/obj/item/ticket_machine_ticket/examine(mob/user)
. = ..()
@@ -265,12 +266,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
. = ..()
maptext = saved_maptext //For some reason, storage code removes all maptext off objs, this stops its number from being wiped off when taken out of storage.
/obj/item/ticket_machine_ticket/attackby(obj/item/P, mob/living/carbon/human/user, params) //Stolen from papercode
if(burn_paper_product_attackby_check(P, user))
return
return ..()
/obj/item/ticket_machine_ticket/Destroy()
if(source)
source.ticket_holders -= owner_ref
+2 -3
View File
@@ -20,7 +20,8 @@
//Photos are quite rarer than papers, so they're more likely to be added to the queue to make things even.
if(!mapload && prob(MESSAGE_BOTTLE_CHANCE * 5) && picture?.id)
LAZYADD(SSpersistence.queued_message_bottles, src)
return ..()
. = ..()
AddElement(/datum/element/burn_on_item_ignition)
/obj/item/photo/Destroy()
LAZYREMOVE(SSpersistence.queued_message_bottles, src)
@@ -75,8 +76,6 @@
user.examinate(src)
/obj/item/photo/attackby(obj/item/P, mob/user, params)
if(burn_paper_product_attackby_check(P, user))
return
if(IS_WRITING_UTENSIL(P))
if(!user.can_write(P))
return
+1
View File
@@ -1618,6 +1618,7 @@
#include "code\datums\elements\bsa_blocker.dm"
#include "code\datums\elements\bugkiller_reagent.dm"
#include "code\datums\elements\bump_click.dm"
#include "code\datums\elements\burn_when_item_ignition.dm"
#include "code\datums\elements\can_barricade.dm"
#include "code\datums\elements\can_shatter.dm"
#include "code\datums\elements\caseless.dm"