Files
vgstation13/code/modules/projectiles/guns/projectile.dm
2015-08-24 00:27:57 +02:00

229 lines
8.2 KiB
Plaintext

#define SPEEDLOADER 0 //the gun takes bullets directly
#define FROM_BOX 1
#define MAGAZINE 2 //the gun takes a magazine into gun storage
/obj/item/weapon/gun/projectile
desc = "A classic revolver. Uses 357 ammo"
name = "revolver"
icon_state = "revolver"
caliber = list("357" = 1)
origin_tech = "combat=2;materials=2"
w_class = 3.0
starting_materials = list(MAT_IRON = 1000)
w_type = RECYK_METAL
recoil = 1
var/ammo_type = "/obj/item/ammo_casing/a357"
var/list/loaded = list()
var/max_shells = 7 //only used by guns with no magazine
var/load_method = SPEEDLOADER //0 = Single shells or quick loader, 1 = box, 2 = magazine
var/obj/item/ammo_storage/magazine/stored_magazine = null
var/obj/item/ammo_casing/chambered = null
var/mag_type = ""
var/gun_flags = EMPTYCASINGS //Yay, flags
/obj/item/weapon/gun/projectile/New()
..()
if(mag_type && load_method == 2)
stored_magazine = new mag_type(src)
chamber_round()
else
for(var/i = 1, i <= max_shells, i++)
loaded += new ammo_type(src)
update_icon()
return
//loads the argument magazine into the gun
/obj/item/weapon/gun/projectile/proc/LoadMag(var/obj/item/ammo_storage/magazine/AM, var/mob/user)
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/item/weapon/gun/projectile/proc/LoadMag() called tick#: [world.time]")
if(istype(AM, text2path(mag_type)) && !stored_magazine)
if(user)
user.drop_item(AM, src)
usr << "<span class='notice'>You load the magazine into \the [src].</span>"
stored_magazine = AM
chamber_round()
AM.update_icon()
update_icon()
return 1
return 0
/obj/item/weapon/gun/projectile/proc/RemoveMag(var/mob/user)
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/item/weapon/gun/projectile/proc/RemoveMag() called tick#: [world.time]")
if(stored_magazine)
stored_magazine.loc = get_turf(src.loc)
if(user)
user.put_in_hands(stored_magazine)
usr << "<span class='notice'>You pull the magazine out of \the [src]!</span>"
stored_magazine.update_icon()
stored_magazine = null
update_icon()
return 1
return 0
/obj/item/weapon/gun/projectile/verb/force_removeMag()
set name = "Remove Magazine"
set category = "Object"
set src in range(0)
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/item/weapon/gun/projectile/verb/force_removeMag() called tick#: [world.time]")
if(stored_magazine)
RemoveMag()
else
usr << "<span class='rose'>There is no magazine to remove!</span>"
/obj/item/weapon/gun/projectile/proc/chamber_round() //Only used by guns with magazine
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/item/weapon/gun/projectile/proc/chamber_round() called tick#: [world.time]")
if(chambered || !stored_magazine)
return 0
else
var/obj/item/ammo_casing/round = stored_magazine.get_round()
if(istype(round))
chambered = round
chambered.loc = src
return 1
return 0
/obj/item/weapon/gun/projectile/proc/getAC()
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/item/weapon/gun/projectile/proc/getAC() called tick#: [world.time]")
var/obj/item/ammo_casing/AC = null
if(mag_type && load_method == 2)
AC = chambered
else if(getAmmo())
AC = loaded[1] //load next casing.
return AC
/obj/item/weapon/gun/projectile/process_chambered()
var/obj/item/ammo_casing/AC = getAC()
if(in_chamber)
return 1 //{R}
if(isnull(AC) || !istype(AC))
return
if(mag_type && load_method == 2)
chambered = null //Remove casing from chamber.
chamber_round()
else
loaded -= AC //Remove casing from loaded list.
if(gun_flags &EMPTYCASINGS)
AC.loc = get_turf(src) //Eject casing onto ground.
if(AC.BB)
in_chamber = AC.BB //Load projectile into chamber.
AC.BB.loc = src //Set projectile loc to gun.
AC.BB = null //Empty casings
AC.update_icon()
return 1
return 0
/obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/gun_part/silencer) && src.gun_flags &SILENCECOMP)
if(user.l_hand != src && user.r_hand != src) //if we're not in his hands
user << "<span class='notice'>You'll need [src] in your hands to do that.</span>"
return
user.drop_item(A, src) //put the silencer into the gun
user << "<span class='notice'>You screw [A] onto [src].</span>"
silenced = A //dodgy?
w_class = 3
update_icon()
return 1
var/num_loaded = 0
if(istype(A, /obj/item/ammo_storage/magazine))
var/obj/item/ammo_storage/magazine/AM = A
if(load_method == MAGAZINE)
if(!stored_magazine)
LoadMag(AM, user)
else
user << "<span class='rose'>There is already a magazine loaded in \the [src]!</span>"
else
user << "<span class='rose'>You can't load \the [src] with a magazine, dummy!</span>"
if(istype(A, /obj/item/ammo_storage) && load_method != MAGAZINE)
var/obj/item/ammo_storage/AS = A
var/success_load = AS.LoadInto(AS, src)
if(success_load)
user << "<span class='notice'>You successfully fill the [src] with [success_load] shell\s from the [AS]</span>"
if(istype(A, /obj/item/ammo_casing))
var/obj/item/ammo_casing/AC = A
//message_admins("Loading the [src], with [AC], [AC.caliber] and [caliber.len]") //Enable this for testing
if(AC.BB && caliber[AC.caliber]) // a used bullet can't be fired twice
if(load_method == MAGAZINE && !chambered)
user.drop_item(AC, src)
chambered = AC
num_loaded++
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1)
else if(getAmmo() < max_shells)
user.drop_item(AC, src)
loaded += AC
num_loaded++
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1)
if(num_loaded)
user << "<span class='notice'>You load [num_loaded] shell\s into \the [src]!</span>"
A.update_icon()
update_icon()
return
/obj/item/weapon/gun/projectile/attack_self(mob/user as mob)
if (target)
return ..()
if (loaded.len || stored_magazine)
if (load_method == SPEEDLOADER)
var/obj/item/ammo_casing/AC = loaded[1]
loaded -= AC
AC.loc = get_turf(src) //Eject casing onto ground.
user << "<span class='notice'>You unload \the [AC] from \the [src]!</span>"
update_icon()
return
if (load_method == MAGAZINE && stored_magazine)
RemoveMag(user)
else if(loc == user)
if(chambered) // So it processing unloading of a bullet first
var/obj/item/ammo_casing/AC = chambered
AC.loc = get_turf(src) //Eject casing onto ground.
chambered = null
user << "<span class='notice'>You unload \the [AC] from \the [src]!</span>"
update_icon()
return
if(silenced)
if(user.l_hand != src && user.r_hand != src)
..()
return
user << "<span class='notice'>You unscrew [silenced] from [src].</span>"
user.put_in_hands(silenced)
silenced = 0
w_class = 2
update_icon()
return
else
user << "<span class='warning'>Nothing loaded in \the [src]!</span>"
/obj/item/weapon/gun/projectile/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, struggle = 0)
..()
if(!chambered && stored_magazine && !stored_magazine.ammo_count() && gun_flags &AUTOMAGDROP) //auto_mag_drop decides whether or not the mag is dropped once it empties
RemoveMag()
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
return
/obj/item/weapon/gun/projectile/examine(mob/user)
..()
user << "<span class='info'>Has [getAmmo()] round\s remaining.</span>"
// if(in_chamber && !loaded.len)
// usr << "However, it has a chambered round."
// if(in_chamber && loaded.len)
// usr << "It also has a chambered round." {R}
if(istype(silenced, /obj/item/gun_part/silencer))
user << "<span class='warning'>It has a supressor attached to the barrel.</span>"
/obj/item/weapon/gun/projectile/proc/getAmmo()
//writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/item/weapon/gun/projectile/proc/getAmmo() called tick#: [world.time]")
var/bullets = 0
if(mag_type && load_method == 2)
if(stored_magazine)
bullets += stored_magazine.ammo_count()
if(chambered)
bullets++
else
for(var/obj/item/ammo_casing/AC in loaded)
if(istype(AC))
bullets += 1
return bullets