Files
Aurora.3/code/modules/projectiles/ammunition/ammo_pile.dm
T
Casper3667andGitHub f09bcd6cdd Replaces security disruptors with ballistics and removes all disruptors (#21987)
Security officers and the warden each get a .45 pistol loaded with
rubbers, and a spare rubber mag in their lockers.
The investigator get a new .45 revolver loaded with rubbers, based on
the konyang revolver, and a speedloader, also with rubbers.

The armory has had .45 speedloaders added to it, but is otherwise
untouched.

Also the autolathe gets to print .45 speedloaders now for the
investigator gun.

Practice ammo has been added to the autolathe.

The Elyran ERT had their disruptors replaced with plasma pistols.
Other non-Horizon disruptors were replaced with lethal .45.
Horizon disruptors were replaced with rubber .45.
2026-03-25 21:19:47 +00:00

211 lines
6.3 KiB
Plaintext

/obj/item/ammo_pile
name = "ammo pile"
desc = "A handful of some kind of ammunition."
w_class = WEIGHT_CLASS_SMALL
var/list/ammo = list()
var/list/image/ammo_overlays = list()
var/ammo_type // the type of ammo this ammo pile accepts
var/max_ammo = 5
/obj/item/ammo_pile/Destroy()
QDEL_LIST(ammo)
ammo_overlays.Cut()
. = ..()
/obj/item/ammo_pile/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
if(is_adjacent)
. += SPAN_NOTICE("It contains [length(ammo)] rounds.")
/obj/item/ammo_pile/Initialize(mapload, var/list/provided_ammo)
. = ..()
if(islist(provided_ammo))
var/obj/first_round = provided_ammo[1]
add_ammo(first_round)
check_name_and_ammo()
provided_ammo -= first_round
for(var/obj/rounds in provided_ammo)
add_ammo(rounds)
else if(ammo_type)
var/obj/first_round = new ammo_type()
add_ammo(first_round)
check_name_and_ammo()
for(var/i = 1, i <= max_ammo - 1, i++)
var/obj/C = new ammo_type()
add_ammo(C)
addtimer(CALLBACK(src, PROC_REF(check_ammo)), 5) // if we don't have any ammo in 5 deciseconds, we're an empty pile, which is worthless, so self-delete
/obj/item/ammo_pile/attack(mob/living/target_mob, mob/living/user, target_zone)
return
/obj/item/ammo_pile/afterattack(atom/A, mob/living/user, proximity_flag)
if(!proximity_flag)
return
if(!length(ammo))
check_ammo()
if(A.type == ammo_type)
if(length(ammo) >= max_ammo)
to_chat(user, SPAN_WARNING("\The [src] is already fully stacked."))
return
var/obj/item/ammo_casing/B = A
if(!B.BB)
to_chat(user, SPAN_WARNING("\The [B] is spent!"))
return
to_chat(user, SPAN_NOTICE("You add \the [A] to \the [src]."))
add_ammo(A)
else if(istype(A, /obj/item/ammo_pile))
if(length(ammo) >= max_ammo)
to_chat(user, SPAN_WARNING("\The [src] is already fully stacked."))
return
var/obj/item/ammo_pile/target_pile = A
if(target_pile.ammo_type != src.ammo_type)
to_chat(user, SPAN_WARNING("\The [target_pile] has a different type of ammunition!"))
return
var/amount_taken = 0
for(var/obj/bullet in target_pile.ammo)
if(length(src.ammo) >= src.max_ammo)
break
src.add_ammo(bullet)
target_pile.remove_ammo()
amount_taken++
to_chat(user, SPAN_NOTICE("You take [amount_taken] rounds from the other pile and add it to yours."))
else if(istype(A, /obj/item/gun) || istype(A, /obj/item/ammo_magazine))
var/obj/bullet = get_next_ammo()
A.attackby(bullet, user)
if(!(bullet in src)) // if the gun / mag accepted the bullet, it will no longer be in our pile
remove_ammo()
/obj/item/ammo_pile/attackby(obj/item/attacking_item, mob/user)
if(istype(attacking_item, /obj/item/ammo_casing))
if(attacking_item.type != ammo_type)
to_chat(user, SPAN_WARNING("\The [attacking_item] has a different type of ammunition!"))
return TRUE
if(length(ammo) >= max_ammo)
to_chat(user, SPAN_WARNING("\The [src] is already fully stacked."))
return TRUE
var/obj/item/ammo_casing/B = attacking_item
if(!B.BB)
to_chat(user, SPAN_WARNING("\The [B] is spent!"))
return TRUE
to_chat(user, SPAN_NOTICE("You add \the [attacking_item] to \the [src]."))
add_ammo(attacking_item)
return TRUE
return ..()
/obj/item/ammo_pile/attack_hand(mob/user)
if(user.get_inactive_hand() == src)
var/obj/item/ammo_casing/C = get_next_ammo()
user.put_in_hands(C)
remove_ammo()
else
..()
/obj/item/ammo_pile/proc/check_name_and_ammo()
if(length(ammo))
var/obj/item/ammo_casing/first_round = ammo[1]
name = "[first_round.caliber] pile"
desc = "A pile of [first_round.caliber] rounds."
ammo_type = first_round.type
max_ammo = first_round.max_stack
/obj/item/ammo_pile/proc/get_next_ammo() //Returns the next shell to be used.
if(!length(ammo))
qdel(src)
return null
var/obj/item/ammo_casing/to_load = ammo[1]
return to_load
/obj/item/ammo_pile/proc/check_ammo()
var/ammo_amount = length(ammo)
if(ammo_amount > 1)
var/obj/first_round = ammo[1]
if(ammo_amount > 7)
w_class = first_round.w_class + 2 // too many to fit in your pockets, generally
else
w_class = first_round.w_class + 1
return
switch(ammo_amount)
if(0)
qdel(src)
if(1)
var/obj/bullet = ammo[1]
ammo -= bullet
bullet.forceMove(get_turf(src))
var/mob/gunman = ismob(loc) ? loc : null
qdel(src)
if(gunman)
// Do this after qdeleting the pile so that they have a free hand.
gunman.put_in_hands(bullet)
/obj/item/ammo_pile/proc/add_ammo(var/obj/item/ammo_casing/bullet)
if(!bullet.BB)
return
RegisterSignal(bullet, COMSIG_QDELETING, PROC_REF(clear_ammo))
if(ismob(bullet.loc))
var/mob/gunman = bullet.loc
gunman.drop_from_inventory(bullet, src)
if(istype(bullet.loc, /obj/item/storage))
var/obj/item/storage/S = bullet.loc
S.remove_from_storage(bullet, src)
bullet.forceMove(src)
ammo += bullet
var/image/ammo_picture = image(bullet.icon, bullet.icon_state, dir = pick(GLOB.alldirs))
ammo_picture.pixel_x = rand(-6, 6)
ammo_picture.pixel_y = rand(-6, 6)
ammo_overlays[bullet] = ammo_picture
AddOverlays(ammo_overlays[bullet])
/// Called when one of our contained bullets is qdel'd -- why does this happen? it is a mystery
/obj/item/ammo_pile/proc/clear_ammo(datum/source)
SIGNAL_HANDLER
CutOverlays(ammo_overlays[source])
ammo -= source
UnregisterSignal(source, COMSIG_QDELETING)
/obj/item/ammo_pile/proc/remove_ammo(var/atom/target)
var/obj/bullet = ammo[1]
if(target)
bullet.forceMove(target)
CutOverlays(ammo_overlays[bullet])
ammo -= bullet
UnregisterSignal(bullet, COMSIG_QDELETING)
check_ammo()
/obj/item/ammo_pile/proc/scatter()
for(var/thing in ammo)
var/obj/bullet = thing
bullet.forceMove(get_turf(src))
bullet.throw_at_random(FALSE, 2, 7)
remove_ammo(bullet)
/obj/item/ammo_pile/throw_at()
..()
scatter()
/obj/item/ammo_pile/slug
ammo_type = /obj/item/ammo_casing/shotgun
/obj/item/ammo_pile/shotgun_blanks
ammo_type = /obj/item/ammo_casing/shotgun/blank
/obj/item/ammo_pile/shotgun_beanbag
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
/obj/item/ammo_pile/shotgun_flash
ammo_type = /obj/item/ammo_casing/shotgun/flash
/obj/item/ammo_pile/shotgun_pellet
ammo_type = /obj/item/ammo_casing/shotgun/pellet
/obj/item/ammo_pile/shotgun_stunshell
ammo_type = /obj/item/ammo_casing/shotgun/stunshell
/obj/item/ammo_pile/shotgun_practice
ammo_type = /obj/item/ammo_casing/shotgun/practice
/obj/item/ammo_pile/fourty_five
ammo_type = /obj/item/ammo_casing/c45