Ammo magazine and casing update

Rewrites ammo magazines and casings to be a bit more logical.
Updates gun/projectile and all subtypes to work with the new ammo code.
This commit is contained in:
mwerezak
2015-02-09 21:32:49 -05:00
parent a679d22db8
commit fc6dfb5f1b
19 changed files with 527 additions and 511 deletions
+2 -2
View File
@@ -710,7 +710,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
for(var/i=3, i>0, i--)
sec_briefcase.contents += new /obj/item/weapon/spacecash/c1000
sec_briefcase.contents += new /obj/item/weapon/gun/energy/crossbow
sec_briefcase.contents += new /obj/item/weapon/gun/projectile/mateba
sec_briefcase.contents += new /obj/item/weapon/gun/projectile/revolver/mateba
sec_briefcase.contents += new /obj/item/ammo_magazine/a357
sec_briefcase.contents += new /obj/item/weapon/plastique
M.equip_to_slot_or_del(sec_briefcase, slot_l_hand)
@@ -892,7 +892,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/hgpirate(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back)
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(M), slot_belt)
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_belt)
M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform)
var/obj/item/weapon/card/id/W = new(M)
W.name = "[M.real_name]'s ID Card"
+1 -1
View File
@@ -153,7 +153,7 @@ var/global/sent_strike_team = 0
equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/grenade/flashbang(src), slot_r_store)
equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(src), slot_belt)
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(src), slot_belt)
equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand)
@@ -38,7 +38,7 @@
icon_state = "russianranged"
icon_living = "russianranged"
corpse = /obj/effect/landmark/mobcorpse/russian/ranged
weapon1 = /obj/item/weapon/gun/projectile/mateba
weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba
ranged = 1
projectiletype = /obj/item/projectile/bullet
projectilesound = 'sound/weapons/Gunshot.ogg'
+92 -40
View File
@@ -6,73 +6,125 @@
flags = CONDUCT
slot_flags = SLOT_BELT
throwforce = 1
w_class = 1.0
w_class = 1
var/caliber = "" //Which kind of guns it can be loaded into
var/projectile_type //The bullet type to create when New() is called
var/obj/item/projectile/BB = null //The loaded bullet
New()
..()
if(ispath(projectile_type))
BB = new projectile_type(src)
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)
set_dir(pick(cardinal))
var/obj/item/projectile/BB = null //The loaded bullet - make it so that the projectiles are created only when needed?
/obj/item/ammo_casing/New()
..()
if(ispath(projectile_type))
BB = new projectile_type(src)
pixel_x = rand(-10, 10)
pixel_y = rand(-10, 10)
set_dir(pick(cardinal))
/obj/item/ammo_casing/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/screwdriver))
if(BB)
if(initial(BB.name) == "bullet")
var/tmp_label = ""
var/label_text = sanitize(copytext(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label), 1, MAX_NAME_LEN))
if(length(label_text) > 20)
user << "\red The inscription can be at most 20 characters long."
else
if(label_text == "")
user << "\blue You scratch the inscription off of [initial(BB)]."
BB.name = initial(BB.name)
else
user << "\blue You inscribe \"[label_text]\" into \the [initial(BB.name)]."
BB.name = "[initial(BB.name)] \"[label_text]\""
else
user << "\blue You can only inscribe a metal bullet." //because inscribing beanbags is silly
else
if(!BB)
user << "\blue There is no bullet in the casing to inscribe anything into."
return
var/tmp_label = ""
var/label_text = sanitize(copytext(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label), 1, MAX_NAME_LEN))
if(length(label_text) > 20)
user << "\red The inscription can be at most 20 characters long."
else if(!label_text)
user << "\blue You scratch the inscription off of [initial(BB)]."
BB.name = initial(BB.name)
else
user << "\blue You inscribe \"[label_text]\" into \the [initial(BB.name)]."
BB.name = "[initial(BB.name)] (\"[label_text]\")"
/obj/item/ammo_casing/examine(mob/user)
..()
if (!BB)
user << "This one is spent."
//Boxes of ammo
//Gun loading types
#define SINGLE_CASING 1 //The gun only accepts ammo_casings. ammo_magazines should never have this as their mag_type.
#define SPEEDLOADER 2 //Transfers casings from the mag to the gun when used.
#define MAGAZINE 4 //The magazine item itself goes inside the gun
//An item that holds casings and can be used to put them inside guns
/obj/item/ammo_magazine
name = "ammo box (.357)"
desc = "A box of ammo"
name = "magazine"
desc = "A magazine for some kind of gun."
icon_state = "357"
icon = 'icons/obj/ammo.dmi'
flags = CONDUCT
slot_flags = SLOT_BELT
item_state = "syringe_kit"
matter = list("metal" = 50000)
throwforce = 2
w_class = 2.0
matter = list("metal" = 500)
throwforce = 5
w_class = 2
throw_speed = 4
throw_range = 10
var/list/stored_ammo = list()
var/ammo_type = "/obj/item/ammo_casing"
var/mag_type = SPEEDLOADER //ammo_magazines can only be used with compatible guns
var/caliber = "357"
var/max_ammo = 7
var/ammo_type = /obj/item/ammo_casing //ammo type that is initially loaded
var/initial_ammo = null
var/multiple_sprites = 0
var/list/icon_map = list()
/obj/item/ammo_magazine/New()
if(multiple_sprites)
//should probably be cached or something.
icon_map = list(max_ammo = icon_state)
var/list/states = icon_states(icon)
for(var/i = 0, i <= max_ammo, i++)
var/ammo_state = "[icon_state]-[i]"
if(ammo_state in states)
//icon_map += i //so stupid BYOND understands that it's an association
icon_map[i] = ammo_state
New()
for(var/i = 1, i <= max_ammo, i++)
if(isnull(initial_ammo))
initial_ammo = max_ammo
if(initial_ammo)
for(var/i in 1 to initial_ammo)
stored_ammo += new ammo_type(src)
update_icon()
/obj/item/ammo_magazine/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/ammo_casing))
var/obj/item/ammo_casing/C = W
if(C.caliber != caliber)
user << "<span class='warning'>[C] does not fit into [src].</span>"
return
if(stored_ammo.len >= max_ammo)
user << "<span class='warning'>[src] is full!</span>"
return
user.remove_from_mob(C)
C.loc = src
stored_ammo.Insert(1, C) //add to the head of the list
update_icon()
/obj/item/ammo_magazine/attack_self(mob/user)
if(!stored_ammo.len)
user << "<span class='notice'>[src] is already empty!</span>"
return
user << "<span class='notice'>You empty [src].</span>"
for(var/obj/item/ammo_casing/C in stored_ammo)
C.loc = user.loc
stored_ammo.Cut()
update_icon()
if(multiple_sprites)
icon_state = "[initial(icon_state)]-[stored_ammo.len]"
desc = "There are [stored_ammo.len] shell\s left!"
/obj/item/ammo_magazine/update_icon()
if(multiple_sprites)
//find the lowest key greater than or equal to stored_ammo.len
var/new_state = null
for(var/i in icon_map)
if (i >= stored_ammo.len)
new_state = icon_map[i]
break
icon_state = (new_state)? new_state : initial(icon_state)
/obj/item/ammo_magazine/examine(mob/user)
..()
user << "There [(stored_ammo.len > 1)? "are" : "is"] [stored_ammo.len] round\s left!"
+118 -119
View File
@@ -2,44 +2,147 @@
name = "ammo box (.357)"
desc = "A box of .357 ammo"
icon_state = "357"
ammo_type = "/obj/item/ammo_casing/a357"
caliber = "357"
ammo_type = /obj/item/ammo_casing/a357
max_ammo = 7
multiple_sprites = 1
/obj/item/ammo_magazine/c38
name = "speed loader (.38)"
icon_state = "38"
ammo_type = "/obj/item/ammo_casing/c38"
caliber = "38"
ammo_type = /obj/item/ammo_casing/c38
max_ammo = 6
multiple_sprites = 1
/obj/item/ammo_magazine/c38/rubber
name = "speed loader (.38 rubber)"
ammo_type = /obj/item/ammo_casing/c38r
/obj/item/ammo_magazine/c45m
name = "magazine (.45)"
icon_state = "45"
ammo_type = "/obj/item/ammo_casing/c45"
mag_type = MAGAZINE
ammo_type = /obj/item/ammo_casing/c45
caliber = ".45"
max_ammo = 7
multiple_sprites = 1
/obj/item/ammo_magazine/c45/empty
max_ammo = 0
/obj/item/ammo_magazine/c45m/empty
initial_ammo = 0
/obj/item/ammo_magazine/c45r
/obj/item/ammo_magazine/c45m/rubber
name = "magazine (.45 rubber)"
icon_state = "45"
ammo_type = "/obj/item/ammo_casing/c45r"
max_ammo = 7
multiple_sprites = 1
ammo_type = /obj/item/ammo_casing/c45r
/obj/item/ammo_magazine/c45f
/obj/item/ammo_magazine/c45m/flash
name = "magazine (.45 flash)"
icon_state = "45"
ammo_type = "/obj/item/ammo_casing/c45f"
/obj/item/ammo_magazine/mc9mm
name = "magazine (9mm)"
icon_state = "9x19p"
origin_tech = "combat=2"
mag_type = MAGAZINE
caliber = "9mm"
ammo_type = /obj/item/ammo_casing/c9mm
max_ammo = 10
multiple_sprites = 1
/obj/item/ammo_magazine/mc9mm/empty
initial_ammo = 0
/obj/item/ammo_magazine/mc9mm/flash
ammo_type = /obj/item/ammo_casing/c9mmf
/obj/item/ammo_magazine/c9mm
name = "ammunition Box (9mm)"
icon_state = "9mm"
origin_tech = "combat=2"
caliber = "9mm"
ammo_type = /obj/item/ammo_casing/c9mm
max_ammo = 30
/obj/item/ammo_magazine/c9mm/empty
initial_ammo = 0
/obj/item/ammo_magazine/c45
name = "ammunition Box (.45)"
icon_state = "9mm"
origin_tech = "combat=2"
caliber = ".45"
ammo_type = /obj/item/ammo_casing/c45
max_ammo = 30
/obj/item/ammo_magazine/c9mm/empty
initial_ammo = 0
/obj/item/ammo_magazine/a12mm
name = "magazine (12mm)"
icon_state = "12mm"
origin_tech = "combat=2"
mag_type = MAGAZINE
caliber = "12mm"
ammo_type = "/obj/item/ammo_casing/a12mm"
max_ammo = 20
multiple_sprites = 1
/obj/item/ammo_magazine/a12mm/empty
initial_ammo = 0
/obj/item/ammo_magazine/a50
name = "magazine (.50)"
icon_state = "50ae"
origin_tech = "combat=2"
mag_type = MAGAZINE
caliber = ".50"
ammo_type = /obj/item/ammo_casing/a50
max_ammo = 7
multiple_sprites = 1
/obj/item/ammo_magazine/c45r/empty
max_ammo = 0
/obj/item/ammo_magazine/a50/empty
initial_ammo = 0
/obj/item/ammo_magazine/a75
name = "ammo magazine (20mm)"
icon_state = "75"
mag_type = MAGAZINE
caliber = "75"
ammo_type = /obj/item/ammo_casing/a75
multiple_sprites = 1
max_ammo = 4
/obj/item/ammo_magazine/a75/empty
initial_ammo = 0
/obj/item/ammo_magazine/a762
name = "magazine box (7.62mm)"
icon_state = "a762"
origin_tech = "combat=2"
mag_type = MAGAZINE
caliber = "a762"
ammo_type = /obj/item/ammo_casing/a762
max_ammo = 50
multiple_sprites = 1
/obj/item/ammo_magazine/a762/empty
initial_ammo = 0
/obj/item/ammo_magazine/chameleon
name = "magazine (.45)"
icon_state = "45"
mag_type = MAGAZINE
caliber = ".45"
ammo_type = /obj/item/ammo_casing/chameleon
max_ammo = 7
multiple_sprites = 1
matter = list()
/obj/item/ammo_magazine/chameleon/empty
initial_ammo = 0
/*
//unused garbage
/obj/item/ammo_magazine/a418
name = "ammo box (.418)"
@@ -48,114 +151,10 @@
max_ammo = 7
multiple_sprites = 1
/obj/item/ammo_magazine/a666
name = "ammo box (.666)"
icon_state = "666"
ammo_type = "/obj/item/ammo_casing/a666"
max_ammo = 4
multiple_sprites = 1
/obj/item/ammo_magazine/mc9mm
name = "magazine (9mm)"
icon_state = "9x19p"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
max_ammo = 10
multiple_sprites = 1
/obj/item/ammo_magazine/mc9mm/empty
max_ammo = 0
/obj/item/ammo_magazine/c9mm
name = "Ammunition Box (9mm)"
icon_state = "9mm"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
max_ammo = 30
/obj/item/ammo_magazine/c45
name = "Ammunition Box (.45)"
icon_state = "9mm"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/c45"
max_ammo = 30
/obj/item/ammo_magazine/a12mm
name = "magazine (12mm)"
icon_state = "12mm"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/a12mm"
max_ammo = 20
multiple_sprites = 1
/obj/item/ammo_magazine/a12mm/empty
name = "magazine (12mm)"
icon_state = "12mm"
ammo_type = "/obj/item/ammo_casing/12mm"
max_ammo = 0
/obj/item/ammo_magazine/a50
name = "magazine (.50)"
icon_state = "50ae"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/a50"
max_ammo = 7
multiple_sprites = 1
/obj/item/ammo_magazine/a50/empty
name = "magazine (.50)"
icon_state = "50ae"
ammo_type = "/obj/item/ammo_casing/a50"
max_ammo = 0
/obj/item/ammo_magazine/a75
name = "ammo magazine (.75)"
icon_state = "75"
ammo_type = "/obj/item/ammo_casing/a75"
multiple_sprites = 1
max_ammo = 8
/obj/item/ammo_magazine/a75/empty
name = "ammo magazine (.75)"
icon_state = "75"
ammo_type = "/obj/item/ammo_casing/a75"
max_ammo = 0
/obj/item/ammo_magazine/a762
name = "magazine (a762)"
icon_state = "a762"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/a762"
max_ammo = 50
multiple_sprites = 1
/obj/item/ammo_magazine/a762/empty
name = "magazine (a762)"
icon_state = "a762"
ammo_type = "/obj/item/ammo_casing/a762"
max_ammo = 0
multiple_sprites = 1
/obj/item/ammo_magazine/chameleon
name = "magazine (.45)"
icon_state = "45"
ammo_type = "/obj/item/ammo_casing/chameleon"
max_ammo = 7
multiple_sprites = 1
matter = list()
/obj/item/ammo_magazine/chameleon/empty
name = "magazine (.45)"
icon_state = "45"
ammo_type = "/obj/item/ammo_casing/chameleon"
max_ammo = 0
multiple_sprites = 1
matter = list()
*/
@@ -16,6 +16,11 @@
/obj/item/ammo_casing/c38
desc = "A .38 bullet casing."
caliber = "38"
projectile_type = /obj/item/projectile/bullet/pistol
/obj/item/ammo_casing/c38r
desc = "A .38 rubber bullet casing."
caliber = "38"
projectile_type = /obj/item/projectile/bullet/pistol/rubber
/obj/item/ammo_casing/c9mm
@@ -23,6 +28,12 @@
caliber = "9mm"
projectile_type = /obj/item/projectile/bullet/pistol
/obj/item/ammo_casing/c9mmf
desc = "A 9mm flash shell casing."
caliber = "9mm"
projectile_type = /obj/item/projectile/energy/flash
/obj/item/ammo_casing/c45
desc = "A .45 bullet casing."
caliber = ".45"
+13 -14
View File
@@ -78,7 +78,7 @@
/obj/item/weapon/gun/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)//TODO: go over this
//Exclude lasertag guns from the CLUMSY check.
if(!user) return
if(clumsy_check)
if(istype(user, /mob/living))
var/mob/living/M = user
@@ -122,7 +122,7 @@
"You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!")
user.next_move = world.time + 4
var/x_offset = 0
var/y_offset = 0
if(istype(user, /mob/living/carbon))
@@ -135,21 +135,20 @@
x_offset = rand(-1,1)
if(in_chamber)
if(params) in_chamber.set_clickpoint(params)
if(params)
in_chamber.set_clickpoint(params)
var/fail = in_chamber.launch(
target = target,
user = user,
launcher = src,
target_zone = user.zone_sel.selecting,
x_offset = x_offset,
y_offset = y_offset,
px = p_x,
py = p_y
target = target,
user = user,
launcher = src,
target_zone = user.zone_sel.selecting,
x_offset = x_offset,
y_offset = y_offset
)
if(fail) return
if(recoil)
spawn()
shake_camera(user, recoil + 1, recoil)
+133 -83
View File
@@ -1,111 +1,160 @@
#define SPEEDLOADER 0
#define FROM_BOX 1
#define MAGAZINE 2
/obj/item/weapon/gun/projectile
name = "revolver"
desc = "A classic revolver. Uses .357 ammo"
name = "gun"
desc = "A gun that fires bullets."
icon_state = "revolver"
caliber = "357"
origin_tech = "combat=2;materials=2"
w_class = 3.0
w_class = 3
matter = list("metal" = 1000)
recoil = 1
var/ammo_type = "/obj/item/ammo_casing/a357"
var/load_method = SINGLE_CASING|SPEEDLOADER //1 = Single shells, 2 = box or quick loader, 3 = magazine
//For SINGLE_CASING or SPEEDLOADER guns
var/max_shells = 0
var/ammo_type = null
var/list/loaded = list()
var/max_shells = 7
var/load_method = SPEEDLOADER //0 = Single shells or quick loader, 1 = box, 2 = magazine
var/obj/item/ammo_magazine/empty_mag = null
var/mag_type = null
//For MAGAZINE guns
var/magazine_type = null
var/obj/item/ammo_magazine/ammo_magazine = null
var/auto_eject = 0 //if the magazine should automatically eject itself when empty.
/obj/item/weapon/gun/projectile/New()
..()
for(var/i = 1, i <= max_shells, i++)
loaded += new ammo_type(src)
if(load_method == MAGAZINE)
empty_mag = new mag_type(src)
if(load_method & (SINGLE_CASING|SPEEDLOADER))
for(var/i in 1 to max_shells)
loaded += new ammo_type(src)
if(load_method & MAGAZINE)
ammo_magazine = new magazine_type(src)
update_icon()
return
//This proc is badly named. There is no "chamber." Would be better to call this get_next_projectile() or something.
/obj/item/weapon/gun/projectile/load_into_chamber()
if(in_chamber)
return 1 //{R}
if(!loaded.len)
return 0
var/obj/item/ammo_casing/AC = loaded[1] //load next casing.
loaded -= AC //Remove casing from loaded list.
if(isnull(AC) || !istype(AC))
return 0
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.
return 1
var/obj/item/ammo_casing/C = null
if(loaded.len)
C = loaded[1] //load next casing.
loaded -= C
else if(ammo_magazine && ammo_magazine.stored_ammo.len)
C = ammo_magazine.stored_ammo[1]
ammo_magazine.stored_ammo -= C
if(istype(C))
C.loc = get_turf(src) //Eject casing onto ground.
if(C.BB)
in_chamber = C.BB
C.BB.loc = src //Set projectile loc to gun.
return 1
return 0
//Attempts to load A into src, depending on the type of thing being loaded and the load_method
/obj/item/weapon/gun/projectile/proc/load_ammo(var/obj/item/A, mob/user)
if(istype(A, /obj/item/ammo_magazine))
var/obj/item/ammo_magazine/AM = A
if(!(load_method & AM.mag_type) || caliber != AM.caliber)
return //incompatible
switch(AM.mag_type)
if(MAGAZINE)
if(ammo_magazine)
return //already a magazine here
user.remove_from_mob(AM)
AM.loc = src
ammo_magazine = AM
user.visible_message("[user] inserts [AM] into [src].", "<span class='notice'>You insert [AM] into [src]!</span>")
if(SPEEDLOADER)
var/count = 0
for(var/obj/item/ammo_casing/C in AM.stored_ammo)
if(loaded.len >= max_shells)
break
if(C.caliber == caliber)
C.loc = src
loaded += C
AM.stored_ammo -= C //should probably go inside an ammo_magazine proc, but I guess less proc calls this way...
count++
if(count)
user.visible_message("[user] reloads [src].", "<span class='notice'>You load [count] round\s into [src]!</span>")
AM.update_icon()
update_icon()
return
else if(istype(A, /obj/item/ammo_casing))
var/obj/item/ammo_casing/C = A
if(!(load_method & SINGLE_CASING) || caliber != C.caliber || loaded.len >= max_shells)
return //incompatible or full
user.remove_from_mob(C)
C.loc = src
loaded += C
user.visible_message("[user] inserts \a [C] into [src].", "<span class='notice'>You insert \a [C] into [src]!</span>")
update_icon()
return
//attempts to unload src
/obj/item/weapon/gun/projectile/proc/unload_ammo(mob/user)
if(ammo_magazine)
user.put_in_hands(ammo_magazine)
user.visible_message("[user] removes [ammo_magazine] from [src].", "<span class='notice'>You remove [ammo_magazine] from [src]!</span>")
ammo_magazine.update_icon()
ammo_magazine = null
update_icon()
else if(loaded.len)
//presumably, if it can be speed-loaded, it can be speed-unloaded.
if(load_method & SPEEDLOADER)
var/count = 0
var/turf/T = get_turf(user)
if(T)
for(var/obj/item/ammo_casing/C in loaded)
C.loc = T
count++
loaded.Cut()
if(count)
user.visible_message("[user] unloads [src].", "<span class='notice'>You unload [count] round\s from [src]!</span>")
else
var/obj/item/ammo_casing/C = loaded[loaded.len]
loaded.len--
user.put_in_hands(C)
user.visible_message("[user] removes \a [C] from [src].", "<span class='notice'>You remove \a [C] from [src]!</span>")
update_icon()
else
user << "<span class='warning'>There's nothing loaded in [src]!</span>"
/obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob)
var/num_loaded = 0
if(istype(A, /obj/item/ammo_magazine))
if((load_method == MAGAZINE) && loaded.len) return
var/obj/item/ammo_magazine/AM = A
if(AM.stored_ammo.len <= 0)
user << "<span class='warning'>The magazine is empty!</span>"
return
for(var/obj/item/ammo_casing/AC in AM.stored_ammo)
if(loaded.len >= max_shells)
break
if(AC.caliber == caliber && loaded.len < max_shells)
AC.loc = src
AM.stored_ammo -= AC
loaded += AC
num_loaded++
if(load_method == MAGAZINE)
user.remove_from_mob(AM)
empty_mag = AM
empty_mag.loc = src
if(istype(A, /obj/item/ammo_casing) && load_method == SPEEDLOADER)
var/obj/item/ammo_casing/AC = A
if(AC.caliber == caliber && loaded.len < max_shells)
user.drop_item()
AC.loc = src
loaded += AC
num_loaded++
if(num_loaded)
user << "\blue You load [num_loaded] shell\s into the gun!"
A.update_icon()
update_icon()
return
load_ammo(A, user)
/obj/item/weapon/gun/projectile/attack_self(mob/user as mob)
if (target)
if (target) //TODO replace untargeting with a hotkey
return ..()
if (loaded.len)
if (load_method == SPEEDLOADER)
var/obj/item/ammo_casing/AC = loaded[1]
loaded -= AC
AC.loc = get_turf(src) //Eject casing onto ground.
user << "\blue You unload shell from \the [src]!"
if (load_method == MAGAZINE)
var/obj/item/ammo_magazine/AM = empty_mag
for (var/obj/item/ammo_casing/AC in loaded)
AM.stored_ammo += AC
loaded -= AC
AM.loc = get_turf(src)
empty_mag = null
update_icon()
AM.update_icon()
user << "\blue You unload magazine from \the [src]!"
else
user << "\red Nothing loaded in \the [src]!"
unload_ammo(user)
/obj/item/weapon/gun/projectile/afterattack(atom/A, mob/living/user)
..()
if(auto_eject && !ammo_magazine.stored_ammo.len)
eject_magazine(user)
//called when the magazine auto-ejects
/obj/item/weapon/gun/projectile/proc/eject_magazine(mob/user)
if(ammo_magazine)
ammo_magazine.loc = get_turf(src.loc)
user.visible_message(
"[ammo_magazine] falls out and clatters on the floor!",
"<span class='notice'>[ammo_magazine] falls out and clatters on the floor!</span>"
)
ammo_magazine = null
update_icon()
/obj/item/weapon/gun/projectile/examine(mob/user)
..(user)
if(ammo_magazine)
user << "It has \a [ammo_magazine] loaded."
user << "Has [getAmmo()] round\s remaining."
// if(in_chamber && !loaded.len)
// user << "However, it has a chambered round."
@@ -115,7 +164,8 @@
/obj/item/weapon/gun/projectile/proc/getAmmo()
var/bullets = 0
for(var/obj/item/ammo_casing/AC in loaded)
if(istype(AC))
bullets += 1
if(loaded)
bullets += loaded.len
if(ammo_magazine.stored_ammo)
bullets += ammo_magazine.stored_ammo.len
return bullets
@@ -2,11 +2,12 @@
name = "submachine gun"
desc = "A lightweight, fast firing gun. Uses 9mm rounds."
icon_state = "saber" //ugly
w_class = 3.0
w_class = 3
load_method = SPEEDLOADER //yup. until someone sprites a magazine for it.
max_shells = 22
caliber = "9mm"
origin_tech = "combat=4;materials=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
ammo_type = /obj/item/ammo_casing/c9mm
automatic = 1
fire_delay = 0
@@ -14,19 +15,16 @@
isHandgun()
return 0
/obj/item/weapon/gun/projectile/automatic/test
name = "test gun"
ammo_type = "/obj/item/ammo_casing/a145"
/obj/item/weapon/gun/projectile/automatic/mini_uzi
name = "\improper Uzi"
desc = "A lightweight, fast firing gun, for when you want someone dead. Uses .45 rounds."
icon_state = "mini-uzi"
w_class = 3.0
max_shells = 16
w_class = 3
load_method = SPEEDLOADER //yup. until someone sprites a magazine for it.
max_shells = 15
caliber = ".45"
origin_tech = "combat=5;materials=2;syndicate=8"
ammo_type = "/obj/item/ammo_casing/c45"
ammo_type = /obj/item/ammo_casing/c45
isHandgun()
return 1
@@ -37,32 +35,26 @@
desc = "A lightweight, fast firing gun, for when you REALLY need someone dead. Uses 12mm rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp"
icon_state = "c20r"
item_state = "c20r"
w_class = 3.0
max_shells = 20
w_class = 3
caliber = "12mm"
origin_tech = "combat=5;materials=2;syndicate=8"
ammo_type = "/obj/item/ammo_casing/a12mm"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/a12mm/empty
magazine_type = /obj/item/ammo_magazine/a12mm
auto_eject = 1
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
if(!loaded.len && empty_mag)
empty_mag.loc = get_turf(src.loc)
empty_mag = null
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
update_icon()
return
/obj/item/weapon/gun/projectile/automatic/c20r/eject_magazine(mob/user)
..()
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
/obj/item/weapon/gun/projectile/automatic/c20r/update_icon()
..()
if(ammo_magazine)
icon_state = "c20r-[round(loaded.len,4)]"
else
icon_state = "c20r"
return
update_icon()
..()
if(empty_mag)
icon_state = "c20r-[round(loaded.len,4)]"
else
icon_state = "c20r"
return
/obj/item/weapon/gun/projectile/automatic/l6_saw
name = "\improper L6 SAW"
@@ -77,19 +69,16 @@
ammo_type = "/obj/item/ammo_casing/a762"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/a762
var/cover_open = 0
var/mag_inserted = 1
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob)
cover_open = !cover_open
user << "<span class='notice'>You [cover_open ? "open" : "close"] [src]'s cover.</span>"
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][mag_inserted ? round(loaded.len, 25) : "-empty"]"
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(loaded.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) //what I tried to do here is just add a check to see if the cover is open or not and add an icon_state change because I can't figure out how c-20rs do it with overlays
if(cover_open)
@@ -98,46 +87,14 @@
..()
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user as mob)
if(loc != user)
..()
return //let them pick it up
if(!cover_open || (cover_open && !mag_inserted))
..()
else if(cover_open && mag_inserted)
//drop the mag
empty_mag = new /obj/item/ammo_magazine/a762(src)
empty_mag.stored_ammo = loaded
empty_mag.icon_state = "a762-[round(loaded.len, 10)]"
empty_mag.desc = "There are [loaded.len] shells left!"
empty_mag.loc = get_turf(src.loc)
user.put_in_hands(empty_mag)
empty_mag = null
mag_inserted = 0
loaded = list()
update_icon()
user << "<span class='notice'>You remove the magazine from [src].</span>"
..() //let them pick it up
else if(cover_open)
unload_ammo(user)
/obj/item/weapon/gun/projectile/automatic/l6_saw/attackby(var/obj/item/A as obj, mob/user as mob)
if(!cover_open)
if(istype(A,/obj/item/ammo_magazine) && !cover_open)
user << "<span class='notice'>[src]'s cover is closed! You can't insert a new mag!</span>"
return
else if(cover_open && mag_inserted)
user << "<span class='notice'>[src] already has a magazine inserted!</span>"
return
else if(cover_open && !mag_inserted)
mag_inserted = 1
user << "<span class='notice'>You insert the magazine!</span>"
update_icon()
..()
/* The thing I found with guns in ss13 is that they don't seem to simulate the rounds in the magazine in the gun.
Afaik, since projectile.dm features a revolver, this would make sense since the magazine is part of the gun.
However, it looks like subsequent guns that use removable magazines don't take that into account and just get
around simulating a removable magazine by adding the casings into the loaded list and spawning an empty magazine
when the gun is out of rounds. Which means you can't eject magazines with rounds in them. The below is a very
rough and poor attempt at making that happen. -Ausops */
..()
@@ -2,42 +2,32 @@
name = "silenced pistol"
desc = "A small, quiet, easily concealable gun. Uses .45 rounds."
icon_state = "silenced_pistol"
w_class = 3.0
max_shells = 12
w_class = 3
caliber = ".45"
silenced = 1
origin_tech = "combat=2;materials=2;syndicate=8"
ammo_type = "/obj/item/ammo_casing/c45"
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/c45m
/obj/item/weapon/gun/projectile/deagle
name = "desert eagle"
desc = "A robust handgun that uses .50 AE ammo"
icon_state = "deagle"
force = 14.0
max_shells = 7
caliber = ".50"
ammo_type ="/obj/item/ammo_casing/a50"
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/a50/empty
magazine_type = /obj/item/ammo_magazine/a50
auto_eject = 1
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
if(!loaded.len && empty_mag)
empty_mag.loc = get_turf(src.loc)
empty_mag = null
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
update_icon()
return
/obj/item/weapon/gun/projectile/deagle/eject_magazine(mob/user)
..()
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
/obj/item/weapon/gun/projectile/deagle/gold
desc = "A gold plated gun folded over a million times by superior martian gunsmiths. Uses .50 AE ammo."
icon_state = "deagleg"
item_state = "deagleg"
/obj/item/weapon/gun/projectile/deagle/camo
desc = "A Deagle brand Deagle for operators operating operationally. Uses .50 AE ammo."
icon_state = "deaglecamo"
@@ -55,44 +45,34 @@
origin_tech = "combat=3"
ammo_type = "/obj/item/ammo_casing/a75"
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/a75/empty
magazine_type = /obj/item/ammo_magazine/a75
auto_eject = 1
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
if(!loaded.len && empty_mag)
empty_mag.loc = get_turf(src.loc)
empty_mag = null
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
update_icon()
return
/obj/item/weapon/gun/projectile/gyropistol/eject_magazine(mob/user)
..()
playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1)
update_icon()
..()
if(empty_mag)
icon_state = "gyropistolloaded"
else
icon_state = "gyropistol"
return
/obj/item/weapon/gun/projectile/gyropistol/update_icon()
..()
if(ammo_magazine)
icon_state = "gyropistolloaded"
else
icon_state = "gyropistol"
/obj/item/weapon/gun/projectile/pistol
name = "\improper Stechtkin pistol"
desc = "A small, easily concealable gun. Uses 9mm rounds."
icon_state = "pistol"
w_class = 2
max_shells = 10
caliber = "9mm"
silenced = 0
origin_tech = "combat=2;materials=2;syndicate=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/mc9mm/empty
magazine_type = /obj/item/ammo_magazine/mc9mm
/obj/item/weapon/gun/projectile/pistol/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
if(!loaded.len && empty_mag)
empty_mag.loc = get_turf(src.loc)
empty_mag = null
return
/obj/item/weapon/gun/projectile/pistol/flash
desc = "A small, easily concealable gun. Uses 9mm illumination rounds."
magazine_type = /obj/item/ammo_magazine/mc9mm/flash
/obj/item/weapon/gun/projectile/pistol/attack_hand(mob/user as mob)
if(loc == user)
@@ -108,7 +88,6 @@
return
..()
/obj/item/weapon/gun/projectile/pistol/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I, /obj/item/weapon/silencer))
if(user.l_hand != src && user.r_hand != src) //if we're not in his hands
@@ -1,3 +1,13 @@
/obj/item/weapon/gun/projectile/revolver
name = "revolver"
desc = "A classic revolver. Uses .357 ammo"
icon_state = "revolver"
caliber = "357"
origin_tech = "combat=2;materials=2"
max_shells = 7
ammo_type = /obj/item/ammo_casing/a357
/obj/item/weapon/gun/projectile/detective
name = "revolver"
desc = "A cheap Martian knock-off of a Smith & Wesson Model 10. Uses .38-Special rounds."
@@ -5,7 +15,7 @@
max_shells = 6
caliber = "38"
origin_tech = "combat=2;materials=2"
ammo_type = "/obj/item/ammo_casing/c38"
ammo_type = /obj/item/ammo_casing/c38
special_check(var/mob/living/carbon/human/M)
if(caliber == initial(caliber))
@@ -73,37 +83,27 @@
name = "\improper Colt M1911"
desc = "A cheap Martian knock-off of a Colt M1911. Uses less-than-lethal .45 rounds."
icon_state = "colt"
max_shells = 7
caliber = ".45"
ammo_type = "/obj/item/ammo_casing/c45r"
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/c45r/empty
magazine_type = /obj/item/ammo_magazine/c45m/rubber
/obj/item/weapon/gun/projectile/detective/semiauto/flash
ammo_type = "/obj/item/ammo_casing/c45f"
magazine_type = /obj/item/ammo_magazine/c45m/flash
/obj/item/weapon/gun/projectile/detective/semiauto/colt
desc = "A cheap Martian knock-off of a Colt M1911."
ammo_type = "/obj/item/ammo_casing/c45"
magazine_type = /obj/item/ammo_magazine/c45m
/obj/item/weapon/gun/projectile/detective/semiauto/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
if(!loaded.len && empty_mag)
empty_mag.loc = get_turf(src.loc)
empty_mag = null
user << "<span class='notice'>The Magazine falls out and clatters on the floor!</span>"
return
/obj/item/weapon/gun/projectile/mateba
/obj/item/weapon/gun/projectile/revolver/mateba
name = "mateba"
desc = "When you absolutely, positively need a 10mm hole in the other guy. Uses .357 ammo." //>10mm hole >.357
icon_state = "mateba"
origin_tech = "combat=2;materials=2"
// A gun to play Russian Roulette!
// You can spin the chamber to randomize the position of the bullet.
/*
/obj/item/weapon/gun/projectile/russian
name = "\improper Russian revolver"
desc = "A Russian made revolver. Uses .357 ammo. It has a single slot in it's chamber for a bullet."
@@ -184,3 +184,4 @@
user.apply_damage(300, BRUTE, affecting, sharp=1) // You are dead, dead, dead.
return
..()
*/
@@ -10,127 +10,89 @@
slot_flags = SLOT_BACK
caliber = "shotgun"
origin_tech = "combat=4;materials=2"
ammo_type = "/obj/item/ammo_casing/shotgun/pellet"
load_method = SINGLE_CASING
ammo_type = /obj/item/ammo_casing/shotgun/pellet
var/recentpump = 0 // to prevent spammage
var/pumped = 0
var/obj/item/ammo_casing/current_shell = null
isHandgun()
return 0
/obj/item/weapon/gun/projectile/shotgun/pump/isHandgun()
return 0
load_into_chamber()
if(in_chamber)
return 1
return 0
attack_self(mob/living/user as mob)
if(recentpump) return
pump(user)
recentpump = 1
spawn(10)
recentpump = 0
return
proc/pump(mob/M as mob)
playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1)
pumped = 0
if(current_shell)//We have a shell in the chamber
current_shell.loc = get_turf(src)//Eject casing
current_shell = null
if(in_chamber)
in_chamber = null
if(!loaded.len) return 0
var/obj/item/ammo_casing/AC = loaded[1] //load next casing.
loaded -= AC //Remove casing from loaded list.
current_shell = AC
if(AC.BB)
in_chamber = AC.BB //Load projectile into chamber.
update_icon() //I.E. fix the desc
/obj/item/weapon/gun/projectile/shotgun/pump/load_into_chamber()
if(in_chamber)
return 1
return 0
/obj/item/weapon/gun/projectile/shotgun/pump/attack_self(mob/living/user as mob)
if(world.time >= recentpump + 10)
pump(user)
recentpump = world.time
/obj/item/weapon/gun/projectile/shotgun/pump/getAmmo()
. = ..()
if(current_shell) .++
/obj/item/weapon/gun/projectile/shotgun/pump/proc/pump(mob/M as mob)
playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1)
pumped = 0
if(current_shell)//We have a shell in the chamber
current_shell.loc = get_turf(src)//Eject casing
current_shell = null
if(in_chamber)
in_chamber = null
if(!loaded.len) return 0
var/obj/item/ammo_casing/AC = loaded[1] //load next casing.
loaded -= AC //Remove casing from loaded list.
current_shell = AC
if(AC.BB)
in_chamber = AC.BB //Load projectile into chamber.
update_icon() //I.E. fix the desc
return 1
/obj/item/weapon/gun/projectile/shotgun/pump/combat
name = "combat shotgun"
icon_state = "cshotgun"
max_shells = 8
origin_tech = "combat=5;materials=2"
ammo_type = "/obj/item/ammo_casing/shotgun"
max_shells = 8
ammo_type = /obj/item/ammo_casing/shotgun
//this is largely hacky and bad :( -Pete
/obj/item/weapon/gun/projectile/shotgun/doublebarrel
name = "double-barreled shotgun"
desc = "A true classic."
icon_state = "dshotgun"
item_state = "shotgun"
//SPEEDLOADER because rapid unloading.
//In principle someone could make a speedloader for it, so it makes sense.
load_method = SINGLE_CASING|SPEEDLOADER
max_shells = 2
w_class = 4.0
w_class = 4
force = 10
flags = CONDUCT
slot_flags = SLOT_BACK
caliber = "shotgun"
origin_tech = "combat=3;materials=1"
ammo_type = "/obj/item/ammo_casing/shotgun/beanbag"
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
New()
for(var/i = 1, i <= max_shells, i++)
loaded += new ammo_type(src)
update_icon()
return
load_into_chamber()
// if(in_chamber)
// return 1 {R}
if(!loaded.len)
return 0
var/obj/item/ammo_casing/AC = loaded[1] //load next casing.
loaded -= AC //Remove casing from loaded list.
AC.desc += " This one is spent."
if(AC.BB)
in_chamber = AC.BB //Load projectile into chamber.
return 1
return 0
attack_self(mob/living/user as mob)
if(!(locate(/obj/item/ammo_casing/shotgun) in src) && !loaded.len)
user << "<span class='notice'>\The [src] is empty.</span>"
return
for(var/obj/item/ammo_casing/shotgun/shell in src) //This feels like a hack. //don't code at 3:30am kids!!
if(shell in loaded)
loaded -= shell
shell.loc = get_turf(src.loc)
user << "<span class='notice'>You break \the [src].</span>"
update_icon()
attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/ammo_casing) && !load_method)
var/obj/item/ammo_casing/AC = A
if(AC.caliber == caliber && (loaded.len < max_shells) && (contents.len < max_shells)) //forgive me father, for i have sinned
user.drop_item()
AC.loc = src
loaded += AC
user << "<span class='notice'>You load a shell into \the [src]!</span>"
A.update_icon()
update_icon()
if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter))
user << "<span class='notice'>You begin to shorten the barrel of \the [src].</span>"
if(loaded.len)
afterattack(user, user) //will this work?
afterattack(user, user) //it will. we call it twice, for twice the FUN
//this is largely hacky and bad :( -Pete
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter))
user << "<span class='notice'>You begin to shorten the barrel of \the [src].</span>"
if(loaded.len)
for(var/i in 1 to max_shells)
afterattack(user, user) //will this work? //it will. we call it twice, for twice the FUN
playsound(user, fire_sound, 50, 1)
user.visible_message("<span class='danger'>The shotgun goes off!</span>", "<span class='danger'>The shotgun goes off in your face!</span>")
return
if(do_after(user, 30)) //SHIT IS STEALTHY EYYYYY
icon_state = "sawnshotgun"
w_class = 3.0
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)
name = "sawn-off shotgun"
desc = "Omar's coming!"
user << "<span class='warning'>You shorten the barrel of \the [src]!</span>"
user.visible_message("<span class='danger'>The shotgun goes off!</span>", "<span class='danger'>The shotgun goes off in your face!</span>")
return
if(do_after(user, 30)) //SHIT IS STEALTHY EYYYYY
icon_state = "sawnshotgun"
w_class = 3
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)
name = "sawn-off shotgun"
desc = "Omar's coming!"
user << "<span class='warning'>You shorten the barrel of \the [src]!</span>"
else
..()
+16 -10
View File
@@ -103,8 +103,8 @@
user.bullet_act(src, target_zone)
del(src)
return 0
if(targloc == curloc) //Shooting the ground
targloc.bullet_act(src, target_zone)
if(targloc == curloc) //Shooting something in the same turf
target.bullet_act(src, target_zone)
del(src)
return 0
@@ -236,14 +236,20 @@
/obj/item/projectile/process()
if(kill_count < 1)
del(src)
return
step_towards(src, current)
sleep(1)
if(!bumped && !isturf(original))
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
sleep(1)
kill_count--
spawn while(src)
if((!( current ) || loc == current))
current = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z)
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
del(src)
return
step_towards(src, current)
sleep(1)
if(!bumped && !isturf(original))
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
sleep(1)
//"Tracing" projectile
/obj/item/projectile/test //Used to see if you can hit them.
@@ -367,7 +367,7 @@
item_type = "gun"
if(27)
//revolver
var/obj/item/weapon/gun/projectile/new_gun = new /obj/item/weapon/gun/projectile(src.loc)
var/obj/item/weapon/gun/projectile/new_gun = new /obj/item/weapon/gun/projectile/revolver(src.loc)
new_item = new_gun
new_item.icon_state = "gun[rand(1,4)]"
new_item.icon = 'icons/obj/xenoarchaeology.dmi'
@@ -383,7 +383,7 @@
if(num_bullets < new_gun.loaded.len)
new_gun.loaded.Cut()
for(var/i = 1, i <= num_bullets, i++)
var/A = text2path(new_gun.ammo_type)
var/A = new_gun.ammo_type
new_gun.loaded += new A(new_gun)
else
for(var/obj/item/I in new_gun)