diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 28388d656d..4a69fdff87 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1,629 +1,632 @@
GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/effects/fire.dmi', "fire"))
-
-GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
-// if true, everyone item when created will have its name changed to be
-// more... RPG-like.
-
-/obj/item
- name = "item"
- icon = 'icons/obj/items.dmi'
- var/item_state = null
- var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
- var/righthand_file = 'icons/mob/inhands/items_righthand.dmi'
-
- //Dimensions of the icon file used when this item is worn, eg: hats.dmi
- //eg: 32x32 sprite, 64x64 sprite, etc.
- //allows inhands/worn sprites to be of any size, but still centered on a mob properly
- var/worn_x_dimension = 32
- var/worn_y_dimension = 32
- //Same as above but for inhands, uses the lefthand_ and righthand_ file vars
- var/inhand_x_dimension = 32
- var/inhand_y_dimension = 32
-
- //Not on /clothing because for some reason any /obj/item can technically be "worn" with enough fuckery.
- var/icon/alternate_worn_icon = null//If this is set, update_icons() will find on mob (WORN, NOT INHANDS) states in this file instead, primary use: badminnery/events
- var/alternate_worn_layer = null//If this is set, update_icons() will force the on mob state (WORN, NOT INHANDS) onto this layer, instead of it's default
-
- obj_integrity = 200
- max_integrity = 200
-
-
- var/hitsound = null
- var/usesound = null
- var/throwhitsound = null
- var/w_class = WEIGHT_CLASS_NORMAL
- var/slot_flags = 0 //This is used to determine on which slots an item can fit.
- pass_flags = PASSTABLE
- pressure_resistance = 4
- var/obj/item/master = null
-
- var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, CHEST, GROIN, etc. flags. See setup.dm
- var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, CHEST, GROIN, etc. flags. See setup.dm
- var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags
- var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags
-
- var/list/actions //list of /datum/action's that this item has.
- var/list/actions_types //list of paths of action datums to give to the item on New().
-
- //Since any item can now be a piece of clothing, this has to be put here so all items share it.
- var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc.
-
- var/item_color = null //this needs deprecating, soonish
-
- var/body_parts_covered = 0 //see setup.dm for appropriate bit flags
- //var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible
- var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets)
- var/permeability_coefficient = 1 // for chemicals/diseases
- var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit)
- var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up
- var/armour_penetration = 0 //percentage of armour effectiveness to remove
- var/list/allowed = null //suit storage stuff.
- var/obj/item/device/uplink/hidden_uplink = null
- var/strip_delay = 40
- var/put_on_delay = 20
- var/breakouttime = 0
- var/list/materials
- var/origin_tech = null //Used by R&D to determine what research bonuses it grants.
- var/needs_permit = 0 //Used by security bots to determine if this item is safe for public use.
-
- var/list/attack_verb //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
- var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
-
- var/suittoggled = 0
- var/hooded = 0
-
- var/mob/thrownby = null
-
- /obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
-
- //So items can have custom embedd values
- //Because customisation is king
- var/embed_chance = EMBED_CHANCE
- var/embedded_fall_chance = EMBEDDED_ITEM_FALLOUT
- var/embedded_pain_chance = EMBEDDED_PAIN_CHANCE
- var/embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
- var/embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
- var/embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
- var/embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
- var/embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME //A time in ticks, multiplied by the w_class.
-
- var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
- var/heat = 0
- var/sharpness = IS_BLUNT
- var/toolspeed = 1
-
- var/block_chance = 0
- var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom
- var/reach = 1 //In tiles, how far this weapon can reach; 1 for adjacent, which is default
-
- //The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
- var/list/slot_equipment_priority = null // for default list, see /mob/proc/equip_to_appropriate_slot()
-
- // Needs to be in /obj/item because corgis can wear a lot of
- // non-clothing items
- var/datum/dog_fashion/dog_fashion = null
-
- var/datum/rpg_loot/rpg_loot = null
-
-/obj/item/Initialize()
- if (!materials)
- materials = list()
- . = ..()
- for(var/path in actions_types)
- new path(src)
- actions_types = null
-
- if(GLOB.rpg_loot_items)
- rpg_loot = new(src)
-
-/obj/item/Destroy()
- flags &= ~DROPDEL //prevent reqdels
- if(ismob(loc))
- var/mob/m = loc
- m.temporarilyRemoveItemFromInventory(src, TRUE)
- for(var/X in actions)
- qdel(X)
- QDEL_NULL(rpg_loot)
- return ..()
-
-/obj/item/device
- icon = 'icons/obj/device.dmi'
-
-/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
- if(((src in target) && !target_self) || (!isturf(target.loc) && !isturf(target) && not_inside))
- return 0
- else
- return 1
-
-/obj/item/blob_act(obj/structure/blob/B)
- if(B && B.loc == loc)
- qdel(src)
-
-//user: The mob that is suiciding
-//damagetype: The type of damage the item will inflict on the user
-//BRUTELOSS = 1
-//FIRELOSS = 2
-//TOXLOSS = 4
-//OXYLOSS = 8
-//Output a creative message and then return the damagetype done
-/obj/item/proc/suicide_act(mob/user)
- return
-
-/obj/item/verb/move_to_top()
- set name = "Move To Top"
- set category = "Object"
- set src in oview(1)
-
- if(!isturf(loc) || usr.stat || usr.restrained() || !usr.canmove)
- return
-
- var/turf/T = src.loc
-
- src.loc = null
-
- src.loc = T
-
-/obj/item/examine(mob/user) //This might be spammy. Remove?
- ..()
- var/pronoun
- if(src.gender == PLURAL)
- pronoun = "They are"
- else
- pronoun = "It is"
- var/size = weightclass2text(src.w_class)
- to_chat(user, "[pronoun] a [size] item." )
-
- if(user.research_scanner) //Mob has a research scanner active.
- var/msg = "*--------*
"
-
- if(origin_tech)
- msg += "Testing potentials:
"
- var/list/techlvls = params2list(origin_tech)
- for(var/T in techlvls) //This needs to use the better names.
- msg += "Tech: [CallTechName(T)] | magnitude: [techlvls[T]]
"
- else
- msg += "No tech origins detected.
"
-
-
- if(materials.len)
- msg += "Extractable materials:
"
- for(var/mat in materials)
- msg += "[CallMaterialName(mat)]
" //Capitize first word, remove the "$"
- else
- msg += "No extractable materials detected.
"
- msg += "*--------*"
- to_chat(user, msg)
-
-
-/obj/item/attack_self(mob/user)
- interact(user)
-
-/obj/item/interact(mob/user)
- add_fingerprint(user)
- if(hidden_uplink && hidden_uplink.active)
- hidden_uplink.interact(user)
- return 1
- ui_interact(user)
-
-/obj/item/ui_act(action, params)
- add_fingerprint(usr)
- return ..()
-
-/obj/item/attack_hand(mob/user)
- if(!user)
- return
- if(anchored)
- return
-
- if(resistance_flags & ON_FIRE)
- var/mob/living/carbon/C = user
- if(istype(C))
- if(C.gloves && (C.gloves.max_heat_protection_temperature > 360))
- extinguish()
- to_chat(user, "You put out the fire on [src].")
- else
- to_chat(user, "You burn your hand on [src]!")
- var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
- if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
- C.update_damage_overlays()
- return
- else
- extinguish()
-
- if(acid_level > 20 && !ismob(loc))// so we can still remove the clothes on us that have acid.
- var/mob/living/carbon/C = user
- if(istype(C))
- if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
- to_chat(user, "The acid on [src] burns your hand!")
- var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
- if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
- C.update_damage_overlays()
-
-
- if(istype(loc, /obj/item/weapon/storage))
- //If the item is in a storage item, take it out
- var/obj/item/weapon/storage/S = loc
- S.remove_from_storage(src, user.loc)
-
- if(throwing)
- throwing.finalize(FALSE)
- if(loc == user)
- if(!user.dropItemToGround(src))
- return
-
- pickup(user)
- add_fingerprint(user)
- if(!user.put_in_active_hand(src))
- dropped(user)
-
-
-/obj/item/attack_paw(mob/user)
- if(!user)
- return
- if(anchored)
- return
-
- if(istype(loc, /obj/item/weapon/storage))
- var/obj/item/weapon/storage/S = loc
- S.remove_from_storage(src, user.loc)
-
- if(throwing)
- throwing.finalize(FALSE)
- if(loc == user)
- if(!user.dropItemToGround(src))
- return
-
- pickup(user)
- add_fingerprint(user)
- if(!user.put_in_active_hand(src))
- dropped(user)
-
-/obj/item/attack_alien(mob/user)
- var/mob/living/carbon/alien/A = user
-
- if(!A.has_fine_manipulation)
- if(src in A.contents) // To stop Aliens having items stuck in their pockets
- A.dropItemToGround(src)
- to_chat(user, "Your claws aren't capable of such fine manipulation!")
- return
- attack_paw(A)
-
-/obj/item/attack_ai(mob/user)
- if(istype(src.loc, /obj/item/weapon/robot_module))
- //If the item is part of a cyborg module, equip it
- if(!iscyborg(user))
- return
- var/mob/living/silicon/robot/R = user
- if(!R.low_power_mode) //can't equip modules with an empty cell.
- R.activate_module(src)
- R.hud_used.update_robot_modules_display()
-
-// Due to storage type consolidation this should get used more now.
-// I have cleaned it up a little, but it could probably use more. -Sayu
-// The lack of ..() is intentional, do not add one
-/obj/item/attackby(obj/item/weapon/W, mob/user, params)
- if(istype(W,/obj/item/weapon/storage))
- var/obj/item/weapon/storage/S = W
- if(S.use_to_pickup)
- if(S.collection_mode) //Mode is set to collect multiple items on a tile and we clicked on a valid one.
- if(isturf(loc))
- var/list/rejections = list()
-
- var/list/things = loc.contents.Copy()
- if (S.collection_mode == 2)
- things = typecache_filter_list(things, typecacheof(type))
-
- var/len = things.len
- if(!len)
- to_chat(user, "You failed to pick up anything with [S].")
- return
- var/datum/progressbar/progress = new(user, len, loc)
-
- while (do_after(user, 10, TRUE, S, FALSE, CALLBACK(src, .proc/handle_mass_pickup, S, things, loc, rejections, progress)))
- sleep(1)
-
- qdel(progress)
-
- to_chat(user, "You put everything you could [S.preposition] [S].")
-
- else if(S.can_be_inserted(src))
- S.handle_item_insertion(src)
-
-/obj/item/proc/handle_mass_pickup(obj/item/weapon/storage/S, list/things, atom/thing_loc, list/rejections, datum/progressbar/progress)
- for(var/obj/item/I in things)
- things -= I
- if(I.loc != thing_loc)
- continue
- if(I.type in rejections) // To limit bag spamming: any given type only complains once
- continue
- if(!S.can_be_inserted(I, stop_messages = TRUE)) // Note can_be_inserted still makes noise when the answer is no
- if(S.contents.len >= S.storage_slots)
- break
- rejections += I.type // therefore full bags are still a little spammy
- continue
-
- S.handle_item_insertion(I, TRUE) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed.
-
- if (TICK_CHECK)
- progress.update(progress.goal - things.len)
- return TRUE
-
- progress.update(progress.goal - things.len)
- return FALSE
-
-// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
-
-/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- if(prob(final_block_chance))
- owner.visible_message("[owner] blocks [attack_text] with [src]!")
- return 1
- return 0
-
-/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language)
- return ITALICS | REDUCE_RANGE
-
-/obj/item/proc/dropped(mob/user)
- for(var/X in actions)
- var/datum/action/A = X
- A.Remove(user)
- if(DROPDEL & flags)
- qdel(src)
-
-// called just as an item is picked up (loc is not yet changed)
-/obj/item/proc/pickup(mob/user)
- return
-
-
-// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
-/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S)
- return
-
-// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
-/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S)
- return
-
-// called when "found" in pockets and storage items. Returns 1 if the search should end.
-/obj/item/proc/on_found(mob/finder)
- return
-
-// called after an item is placed in an equipment slot //NOPE, for example, if you put a helmet in slot_head, it is NOT in user's head variable yet, how stupid.
-// user is mob that equipped it
-// slot uses the slot_X defines found in setup.dm
-// for items that can be placed in multiple slots
-// note this isn't called during the initial dressing of a player
-/obj/item/proc/equipped(mob/user, slot)
- for(var/X in actions)
- var/datum/action/A = X
- if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
- A.Grant(user)
-
-//sometimes we only want to grant the item's action if it's equipped in a specific slot.
-/obj/item/proc/item_action_slot_check(slot, mob/user)
- if(slot == slot_in_backpack || slot == slot_legcuffed) //these aren't true slots, so avoid granting actions there
- return FALSE
- return TRUE
-
-//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't.
-//if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise.
-//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
-//Set disable_warning to 1 if you wish it to not give you outputs.
-/obj/item/proc/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
- if(!M)
- return 0
-
- return M.can_equip(src, slot, disable_warning)
-
-/obj/item/verb/verb_pickup()
- set src in oview(1)
- set category = "Object"
- set name = "Pick up"
-
- if(usr.incapacitated() || !Adjacent(usr) || usr.lying)
- return
-
- if(usr.get_active_held_item() == null) // Let me know if this has any problems -Yota
- usr.UnarmedAttack(src)
-
-//This proc is executed when someone clicks the on-screen UI button.
-//The default action is attack_self().
-//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob.
-/obj/item/proc/ui_action_click(mob/user, actiontype)
- attack_self(user)
-
-/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
- return 0
-
-/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user)
-
- var/is_human_victim = 0
- var/obj/item/bodypart/affecting = M.get_bodypart("head")
- if(ishuman(M))
- if(!affecting) //no head!
- return
- is_human_victim = 1
- var/mob/living/carbon/human/H = M
- if((H.head && H.head.flags_cover & HEADCOVERSEYES) || \
- (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || \
- (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES))
- // you can't stab someone in the eyes wearing a mask!
- to_chat(user, "You're going to need to remove that mask/helmet/glasses first!")
- return
-
- if(ismonkey(M))
- var/mob/living/carbon/monkey/Mo = M
- if(Mo.wear_mask && Mo.wear_mask.flags_cover & MASKCOVERSEYES)
- // you can't stab someone in the eyes wearing a mask!
- to_chat(user, "You're going to need to remove that mask/helmet/glasses first!")
- return
-
- if(isalien(M))//Aliens don't have eyes./N slimes also don't have eyes!
- to_chat(user, "You cannot locate any eyes on this creature!")
- return
-
- if(isbrain(M))
- to_chat(user, "You cannot locate any organic eyes on this brain!")
- return
-
- src.add_fingerprint(user)
-
- playsound(loc, src.hitsound, 30, 1, -1)
-
- user.do_attack_animation(M)
-
- if(M != user)
- M.visible_message("[user] has stabbed [M] in the eye with [src]!", \
- "[user] stabs you in the eye with [src]!")
- else
- user.visible_message( \
- "[user] has stabbed themself in the eyes with [src]!", \
- "You stab yourself in the eyes with [src]!" \
- )
- if(is_human_victim)
- var/mob/living/carbon/human/U = M
- U.apply_damage(7, BRUTE, affecting)
-
- else
- M.take_bodypart_damage(7)
-
- add_logs(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])")
-
- M.adjust_blurriness(3)
- M.adjust_eye_damage(rand(2,4))
- if(M.eye_damage >= 10)
- M.adjust_blurriness(15)
- if(M.stat != DEAD)
- to_chat(M, "Your eyes start to bleed profusely!")
- if(!(M.disabilities & (NEARSIGHT | BLIND)))
- if(M.become_nearsighted())
- to_chat(M, "You become nearsighted!")
- if(prob(50))
- if(M.stat != DEAD)
- if(M.drop_item())
- to_chat(M, "You drop what you're holding and clutch at your eyes!")
- M.adjust_blurriness(10)
- M.Paralyse(1)
- M.Weaken(2)
- if (prob(M.eye_damage - 10 + 1))
- if(M.become_blind())
- to_chat(M, "You go blind!")
-
-/obj/item/clean_blood()
- . = ..()
- if(.)
- if(initial(icon) && initial(icon_state))
- var/index = blood_splatter_index()
- var/icon/blood_splatter_icon = GLOB.blood_splatter_icons[index]
- if(blood_splatter_icon)
- cut_overlay(blood_splatter_icon)
-
-/obj/item/clothing/gloves/clean_blood()
- . = ..()
- if(.)
- transfer_blood = 0
-
-/obj/item/singularity_pull(S, current_size)
- if(current_size >= STAGE_FOUR)
- throw_at(S,14,3, spin=0)
- else ..()
-
-/obj/item/throw_impact(atom/A)
- if(A && !QDELETED(A))
- var/itempush = 1
- if(w_class < 4)
- itempush = 0 //too light to push anything
- return A.hitby(src, 0, itempush)
-
-/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
- thrownby = thrower
- callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own
- . = ..(target, range, speed, thrower, spin, diagonals_first, callback)
-
-
-/obj/item/proc/after_throw(datum/callback/callback)
- if (callback) //call the original callback
- . = callback.Invoke()
- throw_speed = initial(throw_speed) //explosions change this.
-
-/obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/weapon/storage
- if(!newLoc)
- return 0
- if(istype(loc,/obj/item/weapon/storage))
- var/obj/item/weapon/storage/S = loc
- S.remove_from_storage(src,newLoc)
- return 1
- return 0
-
-/obj/item/proc/is_hot()
- return heat
-
-/obj/item/proc/is_sharp()
- return sharpness
-
-/obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting)
- if(affecting.can_dismember(src))
- if((sharpness || damtype == BURN) && w_class >= 3)
- . = force*(w_class-1)
-
-/obj/item/proc/get_dismember_sound()
- if(damtype == BURN)
- . = 'sound/weapons/sear.ogg'
- else
- . = pick('sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg')
-
-/obj/item/proc/open_flame(flame_heat=700)
- var/turf/location = loc
- if(ismob(location))
- var/mob/M = location
- var/success = FALSE
- if(src == M.get_item_by_slot(slot_wear_mask))
- success = TRUE
- if(success)
- location = get_turf(M)
- if(isturf(location))
- location.hotspot_expose(flame_heat, 5)
-
-/obj/item/proc/ignition_effect(atom/A, mob/user)
- if(is_hot())
- . = "[user] lights [A] with [src]."
- else
- . = ""
-
-
-//when an item modify our speech spans when in our active hand. Override this to modify speech spans.
-/obj/item/proc/get_held_item_speechspans(mob/living/carbon/user)
- return
-
-/obj/item/hitby(atom/movable/AM)
- return
-
-/obj/item/attack_hulk(mob/living/carbon/human/user)
- return 0
-
-/obj/item/attack_animal(mob/living/simple_animal/M)
- return 0
-
-/obj/item/mech_melee_attack(obj/mecha/M)
- return 0
-
-/obj/item/burn()
- if(!QDELETED(src))
- var/turf/T = get_turf(src)
- var/ash_type = /obj/effect/decal/cleanable/ash
- if(w_class == WEIGHT_CLASS_HUGE || w_class == WEIGHT_CLASS_GIGANTIC)
- ash_type = /obj/effect/decal/cleanable/ash/large
- var/obj/effect/decal/cleanable/ash/A = new ash_type(T)
- A.desc += "\nLooks like this used to be \an [name] some time ago."
- ..()
-
-/obj/item/acid_melt()
- if(!QDELETED(src))
- var/turf/T = get_turf(src)
- var/obj/effect/decal/cleanable/molten_object/MO = new(T)
- MO.pixel_x = rand(-16,16)
- MO.pixel_y = rand(-16,16)
- MO.desc = "Looks like this was \an [src] some time ago."
- ..()
-
-/obj/item/proc/microwave_act(obj/machinery/microwave/M)
- if(M && M.dirty < 100)
- M.dirty++
+
+GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
+// if true, everyone item when created will have its name changed to be
+// more... RPG-like.
+
+/obj/item
+ name = "item"
+ icon = 'icons/obj/items.dmi'
+ var/item_state = null
+ var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ var/righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+
+ //Dimensions of the icon file used when this item is worn, eg: hats.dmi
+ //eg: 32x32 sprite, 64x64 sprite, etc.
+ //allows inhands/worn sprites to be of any size, but still centered on a mob properly
+ var/worn_x_dimension = 32
+ var/worn_y_dimension = 32
+ //Same as above but for inhands, uses the lefthand_ and righthand_ file vars
+ var/inhand_x_dimension = 32
+ var/inhand_y_dimension = 32
+
+ //Not on /clothing because for some reason any /obj/item can technically be "worn" with enough fuckery.
+ var/icon/alternate_worn_icon = null//If this is set, update_icons() will find on mob (WORN, NOT INHANDS) states in this file instead, primary use: badminnery/events
+ var/alternate_worn_layer = null//If this is set, update_icons() will force the on mob state (WORN, NOT INHANDS) onto this layer, instead of it's default
+
+ obj_integrity = 200
+ max_integrity = 200
+
+
+ var/hitsound = null
+ var/usesound = null
+ var/throwhitsound = null
+ var/w_class = WEIGHT_CLASS_NORMAL
+ var/slot_flags = 0 //This is used to determine on which slots an item can fit.
+ pass_flags = PASSTABLE
+ pressure_resistance = 4
+ var/obj/item/master = null
+
+ var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, CHEST, GROIN, etc. flags. See setup.dm
+ var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, CHEST, GROIN, etc. flags. See setup.dm
+ var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags
+ var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags
+
+ var/list/actions //list of /datum/action's that this item has.
+ var/list/actions_types //list of paths of action datums to give to the item on New().
+
+ //Since any item can now be a piece of clothing, this has to be put here so all items share it.
+ var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc.
+
+ var/item_color = null //this needs deprecating, soonish
+
+ var/body_parts_covered = 0 //see setup.dm for appropriate bit flags
+ //var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible
+ var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets)
+ var/permeability_coefficient = 1 // for chemicals/diseases
+ var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit)
+ var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up
+ var/armour_penetration = 0 //percentage of armour effectiveness to remove
+ var/list/allowed = null //suit storage stuff.
+ var/obj/item/device/uplink/hidden_uplink = null
+ var/strip_delay = 40
+ var/put_on_delay = 20
+ var/breakouttime = 0
+ var/list/materials
+ var/origin_tech = null //Used by R&D to determine what research bonuses it grants.
+ var/needs_permit = 0 //Used by security bots to determine if this item is safe for public use.
+
+ var/list/attack_verb //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
+ var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
+
+ var/suittoggled = 0
+ var/hooded = 0
+
+ var/mob/thrownby = null
+
+ /obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
+
+ //So items can have custom embedd values
+ //Because customisation is king
+ var/embed_chance = EMBED_CHANCE
+ var/embedded_fall_chance = EMBEDDED_ITEM_FALLOUT
+ var/embedded_pain_chance = EMBEDDED_PAIN_CHANCE
+ var/embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
+ var/embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
+ var/embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
+ var/embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
+ var/embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME //A time in ticks, multiplied by the w_class.
+
+ var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
+ var/heat = 0
+ var/sharpness = IS_BLUNT
+ var/toolspeed = 1
+
+ var/block_chance = 0
+ var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom
+ var/reach = 1 //In tiles, how far this weapon can reach; 1 for adjacent, which is default
+
+ //The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
+ var/list/slot_equipment_priority = null // for default list, see /mob/proc/equip_to_appropriate_slot()
+
+ // Needs to be in /obj/item because corgis can wear a lot of
+ // non-clothing items
+ var/datum/dog_fashion/dog_fashion = null
+
+ var/datum/rpg_loot/rpg_loot = null
+
+/obj/item/Initialize()
+ if (!materials)
+ materials = list()
+ . = ..()
+ for(var/path in actions_types)
+ new path(src)
+ actions_types = null
+
+ if(GLOB.rpg_loot_items)
+ rpg_loot = new(src)
+
+/obj/item/Destroy()
+ flags &= ~DROPDEL //prevent reqdels
+ if(ismob(loc))
+ var/mob/m = loc
+ m.temporarilyRemoveItemFromInventory(src, TRUE)
+ for(var/X in actions)
+ qdel(X)
+ QDEL_NULL(rpg_loot)
+ return ..()
+
+/obj/item/device
+ icon = 'icons/obj/device.dmi'
+
+/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
+ if(((src in target) && !target_self) || (!isturf(target.loc) && !isturf(target) && not_inside))
+ return 0
+ else
+ return 1
+
+/obj/item/blob_act(obj/structure/blob/B)
+ if(B && B.loc == loc)
+ qdel(src)
+
+//user: The mob that is suiciding
+//damagetype: The type of damage the item will inflict on the user
+//BRUTELOSS = 1
+//FIRELOSS = 2
+//TOXLOSS = 4
+//OXYLOSS = 8
+//Output a creative message and then return the damagetype done
+/obj/item/proc/suicide_act(mob/user)
+ return
+
+/obj/item/verb/move_to_top()
+ set name = "Move To Top"
+ set category = "Object"
+ set src in oview(1)
+
+ if(!isturf(loc) || usr.stat || usr.restrained() || !usr.canmove)
+ return
+
+ var/turf/T = src.loc
+
+ src.loc = null
+
+ src.loc = T
+
+/obj/item/examine(mob/user) //This might be spammy. Remove?
+ ..()
+ var/pronoun
+ if(src.gender == PLURAL)
+ pronoun = "They are"
+ else
+ pronoun = "It is"
+ var/size = weightclass2text(src.w_class)
+ to_chat(user, "[pronoun] a [size] item." )
+
+ if(user.research_scanner) //Mob has a research scanner active.
+ var/msg = "*--------*
"
+
+ if(origin_tech)
+ msg += "Testing potentials:
"
+ var/list/techlvls = params2list(origin_tech)
+ for(var/T in techlvls) //This needs to use the better names.
+ msg += "Tech: [CallTechName(T)] | magnitude: [techlvls[T]]
"
+ else
+ msg += "No tech origins detected.
"
+
+
+ if(materials.len)
+ msg += "Extractable materials:
"
+ for(var/mat in materials)
+ msg += "[CallMaterialName(mat)]
" //Capitize first word, remove the "$"
+ else
+ msg += "No extractable materials detected.
"
+ msg += "*--------*"
+ to_chat(user, msg)
+
+
+/obj/item/attack_self(mob/user)
+ interact(user)
+
+/obj/item/interact(mob/user)
+ add_fingerprint(user)
+ if(hidden_uplink && hidden_uplink.active)
+ hidden_uplink.interact(user)
+ return 1
+ ui_interact(user)
+
+/obj/item/ui_act(action, params)
+ add_fingerprint(usr)
+ return ..()
+
+/obj/item/attack_hand(mob/user)
+ if(!user)
+ return
+ if(anchored)
+ return
+
+ if(resistance_flags & ON_FIRE)
+ var/mob/living/carbon/C = user
+ if(istype(C))
+ if(C.gloves && (C.gloves.max_heat_protection_temperature > 360))
+ extinguish()
+ to_chat(user, "You put out the fire on [src].")
+ else
+ to_chat(user, "You burn your hand on [src]!")
+ var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
+ if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
+ C.update_damage_overlays()
+ return
+ else
+ extinguish()
+
+ if(acid_level > 20 && !ismob(loc))// so we can still remove the clothes on us that have acid.
+ var/mob/living/carbon/C = user
+ if(istype(C))
+ if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
+ to_chat(user, "The acid on [src] burns your hand!")
+ var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
+ if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
+ C.update_damage_overlays()
+
+
+ if(istype(loc, /obj/item/weapon/storage))
+ //If the item is in a storage item, take it out
+ var/obj/item/weapon/storage/S = loc
+ S.remove_from_storage(src, user.loc)
+
+ if(throwing)
+ throwing.finalize(FALSE)
+ if(loc == user)
+ if(!user.dropItemToGround(src))
+ return
+
+ pickup(user)
+ add_fingerprint(user)
+ if(!user.put_in_active_hand(src))
+ dropped(user)
+
+
+/obj/item/attack_paw(mob/user)
+ if(!user)
+ return
+ if(anchored)
+ return
+
+ if(istype(loc, /obj/item/weapon/storage))
+ var/obj/item/weapon/storage/S = loc
+ S.remove_from_storage(src, user.loc)
+
+ if(throwing)
+ throwing.finalize(FALSE)
+ if(loc == user)
+ if(!user.dropItemToGround(src))
+ return
+
+ pickup(user)
+ add_fingerprint(user)
+ if(!user.put_in_active_hand(src))
+ dropped(user)
+
+/obj/item/attack_alien(mob/user)
+ var/mob/living/carbon/alien/A = user
+
+ if(!A.has_fine_manipulation)
+ if(src in A.contents) // To stop Aliens having items stuck in their pockets
+ A.dropItemToGround(src)
+ to_chat(user, "Your claws aren't capable of such fine manipulation!")
+ return
+ attack_paw(A)
+
+/obj/item/attack_ai(mob/user)
+ if(istype(src.loc, /obj/item/weapon/robot_module))
+ //If the item is part of a cyborg module, equip it
+ if(!iscyborg(user))
+ return
+ var/mob/living/silicon/robot/R = user
+ if(!R.low_power_mode) //can't equip modules with an empty cell.
+ R.activate_module(src)
+ R.hud_used.update_robot_modules_display()
+
+// Due to storage type consolidation this should get used more now.
+// I have cleaned it up a little, but it could probably use more. -Sayu
+// The lack of ..() is intentional, do not add one
+/obj/item/attackby(obj/item/weapon/W, mob/user, params)
+ if(istype(W,/obj/item/weapon/storage))
+ var/obj/item/weapon/storage/S = W
+ if(S.use_to_pickup)
+ if(S.collection_mode) //Mode is set to collect multiple items on a tile and we clicked on a valid one.
+ if(isturf(loc))
+ var/list/rejections = list()
+
+ var/list/things = loc.contents.Copy()
+ if (S.collection_mode == 2)
+ things = typecache_filter_list(things, typecacheof(type))
+
+ var/len = things.len
+ if(!len)
+ to_chat(user, "You failed to pick up anything with [S].")
+ return
+ var/datum/progressbar/progress = new(user, len, loc)
+
+ while (do_after(user, 10, TRUE, S, FALSE, CALLBACK(src, .proc/handle_mass_pickup, S, things, loc, rejections, progress)))
+ sleep(1)
+
+ qdel(progress)
+
+ to_chat(user, "You put everything you could [S.preposition] [S].")
+
+ else if(S.can_be_inserted(src))
+ S.handle_item_insertion(src)
+
+/obj/item/proc/handle_mass_pickup(obj/item/weapon/storage/S, list/things, atom/thing_loc, list/rejections, datum/progressbar/progress)
+ for(var/obj/item/I in things)
+ things -= I
+ if(I.loc != thing_loc)
+ continue
+ if(I.type in rejections) // To limit bag spamming: any given type only complains once
+ continue
+ if(!S.can_be_inserted(I, stop_messages = TRUE)) // Note can_be_inserted still makes noise when the answer is no
+ if(S.contents.len >= S.storage_slots)
+ break
+ rejections += I.type // therefore full bags are still a little spammy
+ continue
+
+ S.handle_item_insertion(I, TRUE) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed.
+
+ if (TICK_CHECK)
+ progress.update(progress.goal - things.len)
+ return TRUE
+
+ progress.update(progress.goal - things.len)
+ return FALSE
+
+// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
+
+/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ if(prob(final_block_chance))
+ owner.visible_message("[owner] blocks [attack_text] with [src]!")
+ return 1
+ return 0
+
+/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language)
+ return ITALICS | REDUCE_RANGE
+
+/obj/item/proc/dropped(mob/user)
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.Remove(user)
+ if(DROPDEL & flags)
+ qdel(src)
+
+// called just as an item is picked up (loc is not yet changed)
+/obj/item/proc/pickup(mob/user)
+ return
+
+
+// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
+/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S)
+ return
+
+// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
+/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S)
+ return
+
+// called when "found" in pockets and storage items. Returns 1 if the search should end.
+/obj/item/proc/on_found(mob/finder)
+ return
+
+// called after an item is placed in an equipment slot //NOPE, for example, if you put a helmet in slot_head, it is NOT in user's head variable yet, how stupid.
+// user is mob that equipped it
+// slot uses the slot_X defines found in setup.dm
+// for items that can be placed in multiple slots
+// note this isn't called during the initial dressing of a player
+/obj/item/proc/equipped(mob/user, slot)
+ for(var/X in actions)
+ var/datum/action/A = X
+ if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
+ A.Grant(user)
+
+//sometimes we only want to grant the item's action if it's equipped in a specific slot.
+/obj/item/proc/item_action_slot_check(slot, mob/user)
+ if(slot == slot_in_backpack || slot == slot_legcuffed) //these aren't true slots, so avoid granting actions there
+ return FALSE
+ return TRUE
+
+//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't.
+//if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise.
+//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
+//Set disable_warning to 1 if you wish it to not give you outputs.
+/obj/item/proc/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
+ if(!M)
+ return 0
+
+ return M.can_equip(src, slot, disable_warning)
+
+/obj/item/verb/verb_pickup()
+ set src in oview(1)
+ set category = "Object"
+ set name = "Pick up"
+
+ if(usr.incapacitated() || !Adjacent(usr) || usr.lying)
+ return
+
+ if(usr.get_active_held_item() == null) // Let me know if this has any problems -Yota
+ usr.UnarmedAttack(src)
+
+//This proc is executed when someone clicks the on-screen UI button.
+//The default action is attack_self().
+//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob.
+/obj/item/proc/ui_action_click(mob/user, actiontype)
+ attack_self(user)
+
+/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
+ return 0
+
+/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user)
+
+ var/is_human_victim = 0
+ var/obj/item/bodypart/affecting = M.get_bodypart("head")
+ if(ishuman(M))
+ if(!affecting) //no head!
+ return
+ is_human_victim = 1
+ var/mob/living/carbon/human/H = M
+ if((H.head && H.head.flags_cover & HEADCOVERSEYES) || \
+ (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || \
+ (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES))
+ // you can't stab someone in the eyes wearing a mask!
+ to_chat(user, "You're going to need to remove that mask/helmet/glasses first!")
+ return
+
+ if(ismonkey(M))
+ var/mob/living/carbon/monkey/Mo = M
+ if(Mo.wear_mask && Mo.wear_mask.flags_cover & MASKCOVERSEYES)
+ // you can't stab someone in the eyes wearing a mask!
+ to_chat(user, "You're going to need to remove that mask/helmet/glasses first!")
+ return
+
+ if(isalien(M))//Aliens don't have eyes./N slimes also don't have eyes!
+ to_chat(user, "You cannot locate any eyes on this creature!")
+ return
+
+ if(isbrain(M))
+ to_chat(user, "You cannot locate any organic eyes on this brain!")
+ return
+
+ src.add_fingerprint(user)
+
+ playsound(loc, src.hitsound, 30, 1, -1)
+
+ user.do_attack_animation(M)
+
+ if(M != user)
+ M.visible_message("[user] has stabbed [M] in the eye with [src]!", \
+ "[user] stabs you in the eye with [src]!")
+ else
+ user.visible_message( \
+ "[user] has stabbed themself in the eyes with [src]!", \
+ "You stab yourself in the eyes with [src]!" \
+ )
+ if(is_human_victim)
+ var/mob/living/carbon/human/U = M
+ U.apply_damage(7, BRUTE, affecting)
+
+ else
+ M.take_bodypart_damage(7)
+
+ add_logs(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])")
+
+ M.adjust_blurriness(3)
+ M.adjust_eye_damage(rand(2,4))
+ if(M.eye_damage >= 10)
+ M.adjust_blurriness(15)
+ if(M.stat != DEAD)
+ to_chat(M, "Your eyes start to bleed profusely!")
+ if(!(M.disabilities & (NEARSIGHT | BLIND)))
+ if(M.become_nearsighted())
+ to_chat(M, "You become nearsighted!")
+ if(prob(50))
+ if(M.stat != DEAD)
+ if(M.drop_item())
+ to_chat(M, "You drop what you're holding and clutch at your eyes!")
+ M.adjust_blurriness(10)
+ M.Paralyse(1)
+ M.Weaken(2)
+ if (prob(M.eye_damage - 10 + 1))
+ if(M.become_blind())
+ to_chat(M, "You go blind!")
+
+/obj/item/clean_blood()
+ . = ..()
+ if(.)
+ if(initial(icon) && initial(icon_state))
+ var/index = blood_splatter_index()
+ var/icon/blood_splatter_icon = GLOB.blood_splatter_icons[index]
+ if(blood_splatter_icon)
+ cut_overlay(blood_splatter_icon)
+
+/obj/item/clothing/gloves/clean_blood()
+ . = ..()
+ if(.)
+ transfer_blood = 0
+
+/obj/item/singularity_pull(S, current_size)
+ if(current_size >= STAGE_FOUR)
+ throw_at(S,14,3, spin=0)
+ else ..()
+
+/obj/item/throw_impact(atom/A)
+ if(A && !QDELETED(A))
+ if(is_hot() && isliving(A))
+ var/mob/living/L = A
+ L.IgniteMob()
+ var/itempush = 1
+ if(w_class < 4)
+ itempush = 0 //too light to push anything
+ return A.hitby(src, 0, itempush)
+
+/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
+ thrownby = thrower
+ callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own
+ . = ..(target, range, speed, thrower, spin, diagonals_first, callback)
+
+
+/obj/item/proc/after_throw(datum/callback/callback)
+ if (callback) //call the original callback
+ . = callback.Invoke()
+ throw_speed = initial(throw_speed) //explosions change this.
+
+/obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/weapon/storage
+ if(!newLoc)
+ return 0
+ if(istype(loc,/obj/item/weapon/storage))
+ var/obj/item/weapon/storage/S = loc
+ S.remove_from_storage(src,newLoc)
+ return 1
+ return 0
+
+/obj/item/proc/is_hot()
+ return heat
+
+/obj/item/proc/is_sharp()
+ return sharpness
+
+/obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting)
+ if(affecting.can_dismember(src))
+ if((sharpness || damtype == BURN) && w_class >= 3)
+ . = force*(w_class-1)
+
+/obj/item/proc/get_dismember_sound()
+ if(damtype == BURN)
+ . = 'sound/weapons/sear.ogg'
+ else
+ . = pick('sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg')
+
+/obj/item/proc/open_flame(flame_heat=700)
+ var/turf/location = loc
+ if(ismob(location))
+ var/mob/M = location
+ var/success = FALSE
+ if(src == M.get_item_by_slot(slot_wear_mask))
+ success = TRUE
+ if(success)
+ location = get_turf(M)
+ if(isturf(location))
+ location.hotspot_expose(flame_heat, 5)
+
+/obj/item/proc/ignition_effect(atom/A, mob/user)
+ if(is_hot())
+ . = "[user] lights [A] with [src]."
+ else
+ . = ""
+
+
+//when an item modify our speech spans when in our active hand. Override this to modify speech spans.
+/obj/item/proc/get_held_item_speechspans(mob/living/carbon/user)
+ return
+
+/obj/item/hitby(atom/movable/AM)
+ return
+
+/obj/item/attack_hulk(mob/living/carbon/human/user)
+ return 0
+
+/obj/item/attack_animal(mob/living/simple_animal/M)
+ return 0
+
+/obj/item/mech_melee_attack(obj/mecha/M)
+ return 0
+
+/obj/item/burn()
+ if(!QDELETED(src))
+ var/turf/T = get_turf(src)
+ var/ash_type = /obj/effect/decal/cleanable/ash
+ if(w_class == WEIGHT_CLASS_HUGE || w_class == WEIGHT_CLASS_GIGANTIC)
+ ash_type = /obj/effect/decal/cleanable/ash/large
+ var/obj/effect/decal/cleanable/ash/A = new ash_type(T)
+ A.desc += "\nLooks like this used to be \an [name] some time ago."
+ ..()
+
+/obj/item/acid_melt()
+ if(!QDELETED(src))
+ var/turf/T = get_turf(src)
+ var/obj/effect/decal/cleanable/molten_object/MO = new(T)
+ MO.pixel_x = rand(-16,16)
+ MO.pixel_y = rand(-16,16)
+ MO.desc = "Looks like this was \an [src] some time ago."
+ ..()
+
+/obj/item/proc/microwave_act(obj/machinery/microwave/M)
+ if(M && M.dirty < 100)
+ M.dirty++