var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.dmi', "icon_state" = "fire") /obj/item name = "item" icon = 'icons/obj/items.dmi' var/discrete = 0 // used in item_attack.dm to make an item not show an attack message to viewers var/no_embed = 0 // For use in item_attack.dm var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite var/blood_overlay_color = null 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 lefthand_file and righthand_file vars //eg: 32x32 sprite, 64x64 sprite, etc. var/inhand_x_dimension = 32 var/inhand_y_dimension = 32 var/r_speed = 1.0 var/health = null var/hitsound = null var/w_class = 3 var/slot_flags = 0 //This is used to determine on which slots an item can fit. pass_flags = PASSTABLE pressure_resistance = 3 // causeerrorheresoifixthis var/obj/item/master = null var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, UPPER_TORSO, LOWER_TORSO, 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() //list of /datum/action's that this item has. var/list/actions_types = list() //list of paths of action datums to give to the item on New(). var/list/materials = list() //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 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/armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) var/armour_penetration = 0 //percentage of armour effectiveness to remove var/list/allowed = null //suit storage stuff. var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers. var/needs_permit = 0 //Used by security bots to determine if this item is safe for public use. var/strip_delay = DEFAULT_ITEM_STRIP_DELAY var/put_on_delay = DEFAULT_ITEM_PUTON_DELAY var/breakouttime = 0 var/flags_size = 0 //flag, primarily used for clothing to determine if a fatty can wear something or not. 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 /* Species-specific sprites, concept stolen from Paradise//vg/. ex: sprite_sheets = list( "Tajaran" = 'icons/cat/are/bad' ) If index term exists and icon_override is not set, this sprite sheet will be used. */ var/list/sprite_sheets = null var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. var/sprite_sheets_obj = null //Used to override hardcoded clothing inventory object dmis in human clothing proc. var/list/species_fit = null //This object has a different appearance when worn by these species /obj/item/New() ..() for(var/path in actions_types) new path(src) /obj/item/Destroy() if(ismob(loc)) var/mob/m = loc m.unEquip(src, 1) for(var/X in actions) qdel(X) return ..() /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside))) return 0 else return 1 /obj/item/device icon = 'icons/obj/device.dmi' /obj/item/ex_act(severity) switch(severity) if(1.0) qdel(src) return if(2.0) if(prob(50)) qdel(src) return if(3.0) if(prob(5)) qdel(src) return else return /obj/item/blob_act() 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 = null set src in oview(1) if(!istype(src.loc, /turf) || usr.stat || usr.restrained() ) return var/turf/T = src.loc src.loc = null src.loc = T /obj/item/examine(mob/user, var/distance = -1) var/size switch(src.w_class) if(1.0) size = "tiny" if(2.0) size = "small" if(3.0) size = "normal-sized" if(4.0) size = "bulky" if(5.0) size = "huge" . = ..(user, distance, "", "It is 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]]
" msg += "Research reliability: [reliability]%
" if(crit_fail) msg += "Critical failure detected in subject!
" 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_hand(mob/user as mob) if(!user) return 0 if(hasorgans(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] if(user.hand) temp = H.organs_by_name["l_hand"] if(!temp) to_chat(user, "You try to use your hand, but it's missing!") return 0 if(temp && !temp.is_usable()) to_chat(user, "You try to move your [temp.name], but cannot!") return 0 if(istype(src.loc, /obj/item/weapon/storage)) //If the item is in a storage item, take it out var/obj/item/weapon/storage/S = src.loc S.remove_from_storage(src) src.throwing = 0 if(loc == user) if(!user.unEquip(src)) return 0 else if(isliving(loc)) return 0 pickup(user) add_fingerprint(user) user.put_in_active_hand(src) return 1 /obj/item/attack_alien(mob/user as mob) if(isalien(user)) // -- TLE 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.unEquip(src) to_chat(user, "Your claws aren't capable of such fine manipulation.") return if(istype(src.loc, /obj/item/weapon/storage)) for(var/mob/M in range(1, src.loc)) if(M.s_active == src.loc) if(M.client) M.client.screen -= src src.throwing = 0 if(src.loc == user) if(!user.unEquip(src)) return else if(istype(src.loc, /mob/living)) return src.pickup(user) user.put_in_active_hand(src) return /obj/item/attack_alien(mob/user as mob) 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.unEquip(src) to_chat(user, "Your claws aren't capable of such fine manipulation.") return attack_hand(A) /obj/item/attack_ai(mob/user as mob) if(istype(src.loc, /obj/item/weapon/robot_module)) //If the item is part of a cyborg module, equip it if(!isrobot(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 /obj/item/attackby(obj/item/weapon/W as obj, mob/user as mob, 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 all items on a tile and we clicked on a valid one. if(isturf(src.loc)) var/list/rejections = list() var/success = 0 var/failure = 0 for(var/obj/item/I in src.loc) if(I.type in rejections) // To limit bag spamming: any given type only complains once continue if(!S.can_be_inserted(I)) // Note can_be_inserted still makes noise when the answer is no rejections += I.type // therefore full bags are still a little spammy failure = 1 continue success = 1 S.handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. if(success && !failure) to_chat(user, "You put everything in [S].") else if(success) to_chat(user, "You put some things in [S].") else to_chat(user, "You fail to pick anything up with [S].") else if(S.can_be_inserted(src)) S.handle_item_insertion(src) return /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, var/text, var/channel=null) return /obj/item/proc/moved(mob/user, old_loc) return /obj/item/proc/dropped(mob/user) for(var/X in actions) var/datum/action/A = X A.Remove(user) // 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 as obj) 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 as obj) return // called when "found" in pockets and storage items. Returns 1 if the search should end. /obj/item/proc/on_found(mob/finder as mob) return // called after an item is placed in an equipment slot // 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(var/mob/user, var/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) /obj/item/proc/item_action_slot_check(slot, mob/user) return 1 //returns 1 if the item is equipped by a mob, 0 otherwise. //This might need some error trapping, not sure if get_equipped_items() is safe for non-human mobs. /obj/item/proc/is_equipped() if(!ismob(loc)) return 0 var/mob/M = loc if(src in M.get_equipped_items()) return 1 else return 0 //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 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, 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 = null set name = "Pick up" if(!(usr)) //BS12 EDIT return if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) return if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain to_chat(usr, "\red You can't pick things up!") return if( usr.stat || usr.restrained() )//Is not asleep/dead and is not restrained to_chat(usr, "\red You can't pick things up!") return if(src.anchored) //Object isn't anchored to_chat(usr, "\red You can't pick that up!") return if(!usr.hand && usr.r_hand) //Right hand is not full to_chat(usr, "\red Your right hand is full.") return if(usr.hand && usr.l_hand) //Left hand is not full to_chat(usr, "\red Your left hand is full.") return if(!istype(src.loc, /turf)) //Object is on a turf to_chat(usr, "\red You can't pick that up!") return //All checks are done, time to pick it up! usr.UnarmedAttack(src) return //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/get_loc_turf() var/atom/L = loc while(L && !istype(L, /turf/)) L = L.loc return loc /obj/item/proc/eyestab(mob/living/carbon/M as mob, mob/living/carbon/user as mob) var/mob/living/carbon/human/H = M if(istype(H) && ( \ (H.head && H.head.flags & HEADCOVERSEYES) || \ (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ (H.glasses && H.glasses.flags & 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(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//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(!iscarbon(user)) M.LAssailant = null else M.LAssailant = user src.add_fingerprint(user) playsound(loc, src.hitsound, 30, 1, -1) if(M != user) M.visible_message("[user] has stabbed [M] in the eye with [src]!", \ "[user] stabs you in the eye with [src]!") user.do_attack_animation(M) else user.visible_message( \ "[user] has stabbed themself in the eyes with [src]!", \ "You stab yourself in the eyes with [src]!" \ ) add_logs(M, user, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])") if(istype(H)) var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) if(!eyes) // should still get stabbed in the head var/obj/item/organ/external/head/head = H.organs_by_name["head"] head.take_damage(rand(10,14), 1) return eyes.take_damage(rand(3,4), 1) if(eyes.damage >= eyes.min_bruised_damage) if(M.stat != 2) if(!(eyes.status & ORGAN_ROBOT) || !(eyes.status & ORGAN_ASSISTED)) //robot eyes bleeding might be a bit silly to_chat(M, "Your eyes start to bleed profusely!") if(prob(50)) if(M.stat != 2) to_chat(M, "You drop what you're holding and clutch at your eyes!") M.drop_item() M.eye_blurry += 10 M.Paralyse(1) M.Weaken(2) if(eyes.damage >= eyes.min_broken_damage) if(M.stat != 2) to_chat(M, "You go blind!") var/obj/item/organ/external/affecting = H.get_organ("head") if(affecting.take_damage(7)) H.UpdateDamageIcon() else M.take_organ_damage(7) M.eye_blurry += rand(3,4) return /obj/item/clean_blood() . = ..() if(blood_overlay) overlays.Remove(blood_overlay) if(istype(src, /obj/item/clothing/gloves)) var/obj/item/clothing/gloves/G = src G.transfer_blood = 0 /obj/item/add_blood(mob/living/carbon/human/M as mob) if(!..()) return 0 if(istype(src, /obj/item/weapon/melee/energy)) return //if we haven't made our blood_overlay already if( !blood_overlay ) generate_blood_overlay() //apply the blood-splatter overlay if it isn't already in there if(!blood_DNA.len) blood_overlay.color = blood_color overlays += blood_overlay //if this blood isn't already in the list, add it if(istype(M)) if(blood_DNA[M.dna.unique_enzymes]) return 0 //already bloodied with this blood. Cannot add more. blood_DNA[M.dna.unique_enzymes] = M.dna.b_type return 1 //we applied blood to the item /obj/item/proc/generate_blood_overlay() if(blood_overlay) return var/icon/I = new /icon(icon, icon_state) I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent) I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant //not sure if this is worth it. It attaches the blood_overlay to every item of the same type if they don't have one already made. for(var/obj/item/A in world) if(A.type == type && !A.blood_overlay) A.blood_overlay = image(I) /obj/item/singularity_pull(S, current_size) spawn(0) //this is needed or multiple items will be thrown sequentially and not simultaneously if(current_size >= STAGE_FOUR) throw_at(S,14,3) else ..() /obj/item/proc/pwr_drain() return 0 // Process Kill /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/wash(mob/user, atom/source) if(flags & ABSTRACT) //Abstract items like grabs won't wash. No-drop items will though because it's still technically an item in your hand. return to_chat(user, "You start washing [src]...") if(!do_after(user, 40, target = source)) return clean_blood() user.visible_message("[user] washes [src] using [source].", \ "You wash [src] using [source].") return 1