/obj/item/gun/ballistic desc = "Now comes in flavors like GUN. Uses 10mm ammo, for some reason." name = "projectile gun" icon_state = "pistol" w_class = WEIGHT_CLASS_NORMAL var/spawnwithmagazine = TRUE var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info var/obj/item/ammo_box/magazine/magazine var/casing_ejector = TRUE //whether the gun ejects the chambered casing /obj/item/gun/ballistic/Initialize() . = ..() if(!spawnwithmagazine) update_icon() return if (!magazine) magazine = new mag_type(src) chamber_round() update_icon() /obj/item/gun/ballistic/update_icon() ..() if(current_skin) icon_state = "[unique_reskin[current_skin]][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]" else icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]" /obj/item/gun/ballistic/process_chamber(empty_chamber = 1) var/obj/item/ammo_casing/AC = chambered //Find chambered round if(istype(AC)) //there's a chambered round if(casing_ejector) AC.forceMove(drop_location()) //Eject casing onto ground. AC.bounce_away(TRUE) chambered = null else if(empty_chamber) chambered = null chamber_round() /obj/item/gun/ballistic/proc/chamber_round() if (chambered || !magazine) return else if (magazine.ammo_count()) chambered = magazine.get_round() chambered.forceMove(src) /obj/item/gun/ballistic/can_shoot() if(!magazine || !magazine.ammo_count(0)) return 0 return 1 /obj/item/gun/ballistic/attackby(obj/item/A, mob/user, params) ..() if (istype(A, /obj/item/ammo_box/magazine)) var/obj/item/ammo_box/magazine/AM = A if (!magazine && istype(AM, mag_type)) if(user.transferItemToLoc(AM, src)) magazine = AM to_chat(user, "You load a new magazine into \the [src].") if(magazine.ammo_count()) playsound(src, "gun_insert_full_magazine", 70, 1) if(!chambered) chamber_round() addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/weapons/gun_chamber_round.ogg', 100, 1), 3) else playsound(src, "gun_insert_empty_magazine", 70, 1) A.update_icon() update_icon() return 1 else to_chat(user, "You cannot seem to get \the [src] out of your hands!") return else if (magazine) to_chat(user, "There's already a magazine in \the [src].") if(istype(A, /obj/item/suppressor)) var/obj/item/suppressor/S = A if(!can_suppress) to_chat(user, "You can't seem to figure out how to fit [S] on [src]!") return if(!user.is_holding(src)) to_chat(user, "You need be holding [src] to fit [S] to it!") return if(suppressed) to_chat(user, "[src] already has a suppressor!") return if(user.transferItemToLoc(A, src)) to_chat(user, "You screw [S] onto [src].") suppressed = A S.oldsound = fire_sound fire_sound = 'sound/weapons/gunshot_silenced.ogg' w_class += A.w_class //so pistols do not fit in pockets when suppressed update_icon() return return 0 /obj/item/gun/ballistic/attack_hand(mob/user) if(loc == user) if(suppressed && can_unsuppress) var/obj/item/suppressor/S = suppressed if(!user.is_holding(src)) ..() return to_chat(user, "You unscrew [suppressed] from [src].") user.put_in_hands(suppressed) fire_sound = S.oldsound w_class -= S.w_class suppressed = null update_icon() return ..() /obj/item/gun/ballistic/attack_self(mob/living/user) var/obj/item/ammo_casing/AC = chambered //Find chambered round if(magazine) magazine.forceMove(drop_location()) user.put_in_hands(magazine) magazine.update_icon() if(magazine.ammo_count()) playsound(src, "sound/weapons/gun_magazine_remove_full.ogg", 70, 1) else playsound(src, "gun_remove_empty_magazine", 70, 1) magazine = null to_chat(user, "You pull the magazine out of \the [src].") else if(chambered) AC.forceMove(drop_location()) AC.bounce_away() chambered = null to_chat(user, "You unload the round from \the [src]'s chamber.") playsound(src, "gun_slide_lock", 70, 1) else to_chat(user, "There's no magazine in \the [src].") update_icon() return /obj/item/gun/ballistic/examine(mob/user) ..() to_chat(user, "It has [get_ammo()] round\s remaining.") /obj/item/gun/ballistic/proc/get_ammo(countchambered = 1) var/boolets = 0 //mature var names for mature people if (chambered && countchambered) boolets++ if (magazine) boolets += magazine.ammo_count() return boolets #define BRAINS_BLOWN_THROW_RANGE 3 #define BRAINS_BLOWN_THROW_SPEED 1 /obj/item/gun/ballistic/suicide_act(mob/user) var/obj/item/organ/brain/B = user.getorganslot(ORGAN_SLOT_BRAIN) if (B && chambered && chambered.BB && can_trigger_gun(user) && !chambered.BB.nodamage) user.visible_message("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!") sleep(25) if(user.is_holding(src)) var/turf/T = get_turf(user) process_fire(user, user, 0, zone_override = "head") user.visible_message("[user] blows [user.p_their()] brain[user.p_s()] out with [src]!") var/turf/target = get_ranged_target_turf(user, turn(user.dir, 180), BRAINS_BLOWN_THROW_RANGE) B.Remove(user) B.forceMove(T) var/datum/dna/user_dna if(iscarbon(user)) var/mob/living/carbon/C = user user_dna = C.dna B.add_blood_DNA(user_dna) var/datum/callback/gibspawner = CALLBACK(GLOBAL_PROC, /proc/spawn_atom_to_turf, /obj/effect/gibspawner/generic, B, 1, FALSE, list(user_dna)) B.throw_at(target, BRAINS_BLOWN_THROW_RANGE, BRAINS_BLOWN_THROW_SPEED, callback=gibspawner) return(BRUTELOSS) else user.visible_message("[user] panics and starts choking to death!") return(OXYLOSS) else user.visible_message("[user] is pretending to blow [user.p_their()] brain[user.p_s()] out with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(src, "gun_dry_fire", 30, 1) return (OXYLOSS) #undef BRAINS_BLOWN_THROW_SPEED #undef BRAINS_BLOWN_THROW_RANGE /obj/item/gun/ballistic/proc/sawoff(mob/user) if(sawn_state == SAWN_OFF) to_chat(user, "\The [src] is already shortened!") return user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src]...") //if there's any live ammo inside the gun, makes it go off if(blow_up(user)) user.visible_message("\The [src] goes off!", "\The [src] goes off in your face!") return if(do_after(user, 30, target = src)) if(sawn_state == SAWN_OFF) return user.visible_message("[user] shortens \the [src]!", "You shorten \the [src].") name = "sawn-off [src.name]" desc = sawn_desc w_class = WEIGHT_CLASS_NORMAL item_state = "gun" slot_flags &= ~SLOT_BACK //you can't sling it on your back slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) sawn_state = SAWN_OFF update_icon() return 1 // Sawing guns related proc /obj/item/gun/ballistic/proc/blow_up(mob/user) . = 0 for(var/obj/item/ammo_casing/AC in magazine.stored_ammo) if(AC.BB) process_fire(user, user,0) . = 1 /obj/item/suppressor name = "suppressor" desc = "A universal syndicate small-arms suppressor for maximum espionage." icon = 'icons/obj/guns/projectile.dmi' icon_state = "suppressor" w_class = WEIGHT_CLASS_TINY var/oldsound = null /obj/item/suppressor/specialoffer name = "cheap suppressor" desc = "A foreign knock-off suppressor, it feels flimsy, cheap, and brittle. Still fits all weapons." icon = 'icons/obj/guns/projectile.dmi' icon_state = "suppressor"