mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
497 lines
19 KiB
Plaintext
497 lines
19 KiB
Plaintext
#define BOLT_NOEVENT 0
|
|
#define BOLT_CLOSED 1
|
|
#define BOLT_OPENED 2
|
|
#define BOLT_LOCKED 4
|
|
#define BOLT_UNLOCKED 8
|
|
#define BOLT_CASING_EJECTED 16
|
|
#define BOLT_CASING_CHAMBERED 32
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////// CADYN'S BALLISTICS ////////////////////////////////////////////////////////////////////////// ORIGINAL FROM CHOMPSTATION ////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/obj/item/gun/projectile
|
|
var/manual_chamber = TRUE
|
|
var/only_open_load = FALSE
|
|
var/auto_loading_type = CLOSED_BOLT | LOCK_MANUAL_LOCK | LOCK_SLAPPABLE
|
|
var/misc_loading_flags = 0
|
|
var/bolt_name = "bolt"
|
|
var/bolt_open = FALSE
|
|
var/bolt_locked = FALSE
|
|
var/bolt_release = "bolt release"
|
|
var/muzzle_velocity = 500 // meters per second
|
|
var/sound_ejectchamber = 'sound/weapons/ballistics/pistol_ejectchamber.ogg'
|
|
var/sound_eject = 'sound/weapons/ballistics/pistol_eject.ogg'
|
|
var/sound_chamber = 'sound/weapons/ballistics/pistol_chamber.ogg'
|
|
|
|
/obj/item/gun/projectile/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0)
|
|
if(fire_anim)
|
|
flick(fire_anim, src)
|
|
|
|
if(muzzle_flash)
|
|
set_light(muzzle_flash)
|
|
|
|
if(one_handed_penalty)
|
|
if(!src.is_held_twohanded(user))
|
|
switch(one_handed_penalty)
|
|
if(1 to 15)
|
|
if(prob(50)) //don't need to tell them every single time
|
|
to_chat(user, span_warning("Your aim wavers slightly."))
|
|
if(16 to 30)
|
|
to_chat(user, span_warning("Your aim wavers as you fire \the [src] with just one hand."))
|
|
if(31 to 45)
|
|
to_chat(user, span_warning("You have trouble keeping \the [src] on target with just one hand."))
|
|
if(46 to INFINITY)
|
|
to_chat(user, span_warning("You struggle to keep \the [src] on target with just one hand!"))
|
|
else if(!user.can_wield_item(src))
|
|
switch(one_handed_penalty)
|
|
if(1 to 15)
|
|
if(prob(50)) //don't need to tell them every single time
|
|
to_chat(user, span_warning("Your aim wavers slightly."))
|
|
if(16 to 30)
|
|
to_chat(user, span_warning("Your aim wavers as you try to hold \the [src] steady."))
|
|
if(31 to 45)
|
|
to_chat(user, span_warning("You have trouble holding \the [src] steady."))
|
|
if(46 to INFINITY)
|
|
to_chat(user, span_warning("You struggle to hold \the [src] steady!"))
|
|
|
|
if(recoil)
|
|
spawn()
|
|
shake_camera(user, recoil+1, recoil)
|
|
update_icon()
|
|
|
|
if(chambered)
|
|
chambered.expend()
|
|
if(!manual_chamber) process_chambered()
|
|
if(manual_chamber && auto_loading_type)
|
|
bolt_toggle()
|
|
|
|
/obj/item/gun/projectile/attack_self(mob/user as mob)
|
|
if(manual_chamber)
|
|
if(do_after(user, 0.4 SECONDS, src))
|
|
bolt_handle(user)
|
|
else if(firemodes.len > 1)
|
|
switch_firemodes(user)
|
|
else
|
|
unload_ammo(user)
|
|
|
|
/obj/item/gun/projectile/proc/bolt_handle(mob/user)
|
|
var/previous_chambered = chambered
|
|
var/result = bolt_toggle(TRUE)
|
|
update_icon()
|
|
if(!result)
|
|
to_chat(user,span_notice("Nothing happens."))
|
|
else
|
|
var/closed = CHECK_BITFIELD(result,BOLT_CLOSED)
|
|
var/opened = CHECK_BITFIELD(result,BOLT_OPENED)
|
|
var/locked = CHECK_BITFIELD(result,BOLT_LOCKED)
|
|
var/unlocked = CHECK_BITFIELD(result,BOLT_UNLOCKED)
|
|
var/casing_ejected = CHECK_BITFIELD(result,BOLT_CASING_EJECTED)
|
|
var/close_open_ejected = casing_ejected ? ", which causes \the [previous_chambered] to be ejected, as well as" : ","
|
|
var/other_ejected = CHECK_BITFIELD(result,BOLT_CASING_CHAMBERED) ? " and causing \the [previous_chambered] to be ejected" : ", causing \the [previous_chambered] to be ejected"
|
|
other_ejected = casing_ejected ? other_ejected : ""
|
|
var/casing_chambered = CHECK_BITFIELD(result,BOLT_CASING_CHAMBERED) ? ", chambering a new round" : ""
|
|
if(closed && opened)
|
|
playsound(src, sound_ejectchamber, 50, 0)
|
|
user.visible_message(span_notice("[user] pulls back \the [bolt_name] before releasing it[close_open_ejected] causing it to slide forward again[casing_chambered]."), \
|
|
span_notice("You pull back \the [bolt_name] before releasing it[close_open_ejected] causing it to slide forward again[casing_chambered]."))
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
else if(opened)
|
|
playsound(src, sound_eject, 50, 0)
|
|
if(locked)
|
|
if(CHECK_BITFIELD(auto_loading_type,LOCK_MANUAL_LOCK))
|
|
playsound(src, sound_ejectchamber, 50, 0)
|
|
user.visible_message(span_notice("[user] pulls back \the [bolt_name] and locks it in the open position[casing_chambered][other_ejected]."), \
|
|
span_notice("You pull back \the [bolt_name] and lock it in the open position[other_ejected][casing_chambered]."))
|
|
else
|
|
user.visible_message(span_notice("[user] pulls back \the [bolt_name] before releasing it, causing it to lock in the open position[casing_chambered][other_ejected]."), \
|
|
span_notice("You pull back \the [bolt_name] before releasing it, causing it to lock in the open position[casing_chambered][other_ejected]."))
|
|
else
|
|
user.visible_message(span_notice("[user] opens \the [bolt_name][casing_chambered][other_ejected]."), \
|
|
span_notice("You pull back \the [bolt_name][casing_chambered][other_ejected]."))
|
|
else if(closed)
|
|
playsound(src, sound_chamber, 50, 0)
|
|
if(unlocked)
|
|
if(bolt_release)
|
|
if(user.a_intent == I_HURT && CHECK_BITFIELD(auto_loading_type,LOCK_SLAPPABLE))
|
|
user.visible_message(span_notice("[user] slaps the [bolt_release], causing \the [bolt_name] to slide forward[casing_chambered]!"), \
|
|
span_notice("You slap the [bolt_release], causing \the [bolt_name] to slide forward[casing_chambered]!"))
|
|
else
|
|
user.visible_message(span_notice("[user] presses the [bolt_release], causing \the [bolt_name] to slide forward[casing_chambered]."), \
|
|
span_notice("You press the [bolt_release], causing \the [bolt_name] to slide forward[casing_chambered]."))
|
|
else
|
|
user.visible_message(span_notice("[user] pulls \the [bolt_name] back the rest of the way, causing it to slide forward[casing_chambered]."), \
|
|
span_notice("You pull \the [bolt_name] back the rest of the way, causing it to slide forward[casing_chambered]."))
|
|
else
|
|
user.visible_message(span_notice("[user] closes \the [bolt_name][casing_chambered]."), \
|
|
span_notice("You close \the [bolt_name][casing_chambered]."))
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
|
|
/obj/item/gun/projectile/proc/bolt_toggle(var/manual)
|
|
if(!bolt_open)
|
|
if(auto_loading_type)
|
|
var/able_to_lock = (CHECK_BITFIELD(auto_loading_type,LOCK_OPEN_EMPTY) || (CHECK_BITFIELD(auto_loading_type,LOCK_MANUAL_LOCK) && manual))
|
|
if(CHECK_BITFIELD(auto_loading_type,OPEN_BOLT))
|
|
bolt_open = TRUE
|
|
var/ejected = process_chambered()
|
|
var/output = BOLT_OPENED
|
|
if(ejected) output |= BOLT_CASING_EJECTED
|
|
return output
|
|
else if(loaded.len || (ammo_magazine && ammo_magazine.stored_ammo.len) || !able_to_lock)
|
|
var/ejected = process_chambered()
|
|
var/chambering = chamber_bullet()
|
|
var/output = BOLT_OPENED | BOLT_CLOSED
|
|
if(ejected) output |= BOLT_CASING_EJECTED
|
|
if(chambering) output |= BOLT_CASING_CHAMBERED
|
|
return output
|
|
else
|
|
if(!manual)
|
|
visible_message(src,span_notice("The [src] fires its last round, causing the [bolt_name] to lock."))
|
|
bolt_open = TRUE
|
|
bolt_locked = TRUE
|
|
var/ejected = process_chambered()
|
|
var/output = BOLT_OPENED | BOLT_LOCKED
|
|
if(ejected) output |= BOLT_CASING_EJECTED
|
|
return output
|
|
else
|
|
bolt_open = TRUE
|
|
var/ejected = process_chambered()
|
|
|
|
var/output = BOLT_OPENED
|
|
if(ejected) output |= BOLT_CASING_EJECTED
|
|
//if(chambering) output |= BOLT_CASING_CHAMBERED
|
|
return output
|
|
else
|
|
if(auto_loading_type)
|
|
if(CHECK_BITFIELD(auto_loading_type,OPEN_BOLT))
|
|
if(loaded.len || (ammo_magazine && ammo_magazine.stored_ammo.len))
|
|
if(!manual)
|
|
var/ejected = process_chambered()
|
|
var/output = BOLT_CLOSED | BOLT_OPENED
|
|
if(ejected) output |= BOLT_CASING_EJECTED
|
|
return output
|
|
else
|
|
return BOLT_NOEVENT
|
|
else
|
|
bolt_open = FALSE
|
|
return BOLT_CLOSED
|
|
else if(bolt_locked)
|
|
var/chambering = FALSE
|
|
if(!chambered)
|
|
chambering = chamber_bullet()
|
|
bolt_locked = FALSE
|
|
bolt_open = FALSE
|
|
var/output = BOLT_CLOSED | BOLT_UNLOCKED
|
|
if(chambering) output |= BOLT_CASING_CHAMBERED
|
|
return output
|
|
else
|
|
bolt_open = FALSE
|
|
return BOLT_CLOSED
|
|
else
|
|
bolt_open = FALSE
|
|
var/output = BOLT_CLOSED
|
|
var/chambering = chamber_bullet()
|
|
if(chambering) output |= BOLT_CASING_CHAMBERED
|
|
return output
|
|
|
|
|
|
/obj/item/gun/projectile/process_chambered()
|
|
if (!chambered) return 0
|
|
|
|
// Aurora forensics port, gunpowder residue.
|
|
if(chambered.leaves_residue)
|
|
var/mob/living/carbon/human/H = loc
|
|
if(istype(H))
|
|
if(!istype(H.gloves, /obj/item/clothing))
|
|
H.add_gunshotresidue(chambered)
|
|
else
|
|
var/obj/item/clothing/G = H.gloves
|
|
G.add_gunshotresidue(chambered)
|
|
|
|
switch(handle_casings)
|
|
if(EJECT_CASINGS) //eject casing onto ground.
|
|
if(chambered.caseless)
|
|
qdel(chambered)
|
|
chambered = null
|
|
return 0
|
|
else
|
|
chambered.loc = get_turf(src)
|
|
playsound(src, "casing", 50, 1)
|
|
chambered = null
|
|
return 1
|
|
if(CYCLE_CASINGS) //cycle the casing back to the end.
|
|
if(ammo_magazine)
|
|
ammo_magazine.stored_ammo += chambered
|
|
else
|
|
loaded += chambered
|
|
chambered = null
|
|
return 0
|
|
|
|
if(handle_casings != HOLD_CASINGS)
|
|
chambered = null
|
|
return 0
|
|
|
|
/obj/item/gun/projectile/consume_next_projectile()
|
|
if(!manual_chamber)
|
|
//get the next casing
|
|
if(loaded.len)
|
|
chambered = loaded[1] //load next casing.
|
|
if(handle_casings != HOLD_CASINGS)
|
|
loaded -= chambered
|
|
else if(ammo_magazine && ammo_magazine.stored_ammo.len)
|
|
chambered = ammo_magazine.stored_ammo[ammo_magazine.stored_ammo.len]
|
|
if(handle_casings != HOLD_CASINGS)
|
|
ammo_magazine.stored_ammo -= chambered
|
|
if(manual_chamber && auto_loading_type && CHECK_BITFIELD(auto_loading_type,OPEN_BOLT) && bolt_open)
|
|
chamber_bullet()
|
|
|
|
if(chambered)
|
|
return chambered.BB
|
|
return null
|
|
|
|
/obj/item/gun/projectile/proc/chamber_bullet()
|
|
if(chambered)
|
|
return 0
|
|
var/obj/item/ammo_casing/to_chamber
|
|
if(loaded.len)
|
|
to_chamber = loaded[1] //load next casing.
|
|
if(handle_casings != HOLD_CASINGS)
|
|
loaded -= to_chamber
|
|
else if(ammo_magazine && ammo_magazine.stored_ammo.len)
|
|
to_chamber = ammo_magazine.stored_ammo[ammo_magazine.stored_ammo.len]
|
|
if(handle_casings != HOLD_CASINGS)
|
|
ammo_magazine.stored_ammo -= to_chamber
|
|
chambered = to_chamber
|
|
if(to_chamber)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
/obj/item/gun/projectile/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 || allowed_magazines && !is_type_in_list(A, allowed_magazines))
|
|
to_chat(user, span_warning("[AM] won't load into [src]!"))
|
|
return
|
|
var/loading_method = AM.mag_type & load_method
|
|
if(loading_method == (MAGAZINE & SPEEDLOADER)) loading_method = MAGAZINE //Default to magazine if both are valid
|
|
switch(loading_method)
|
|
if(MAGAZINE)
|
|
if(ammo_magazine)
|
|
to_chat(user, span_warning("[src] already has a magazine loaded.")) //already a magazine here
|
|
return
|
|
if(manual_chamber && CHECK_BITFIELD(auto_loading_type,OPEN_BOLT) && bolt_open)
|
|
to_chat(user, span_warning("This is an open bolt gun. Make sure you close the bolt before inserting a new magazine."))
|
|
return
|
|
user.remove_from_mob(AM)
|
|
AM.loc = src
|
|
ammo_magazine = AM
|
|
user.visible_message("[user] inserts [AM] into [src].", span_notice("You insert [AM] into [src]."))
|
|
if(manual_chamber && CHECK_BITFIELD(auto_loading_type,CHAMBER_ON_RELOAD) && bolt_open && !chambered)
|
|
chamber_bullet()
|
|
bolt_toggle()
|
|
playsound(src, 'sound/weapons/flipblade.ogg', 50, 1)
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
if(SPEEDLOADER)
|
|
if(only_open_load && !bolt_open)
|
|
to_chat(user, span_warning("[src] must have its bolt open to be loaded!"))
|
|
return
|
|
if(loaded.len >= max_shells)
|
|
to_chat(user, span_warning("[src] is full!"))
|
|
return
|
|
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_notice("You load [count] round\s into [src]."))
|
|
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
AM.update_icon()
|
|
else if(istype(A, /obj/item/ammo_casing))
|
|
var/obj/item/ammo_casing/C = A
|
|
if(caliber != C.caliber)
|
|
return
|
|
if(!(load_method & SINGLE_CASING) || (misc_loading_flags & INTERNAL_MAG_SEPARATE)) //INTERNAL_MAG_SEPARATE is pretty much exclusively for the SPAS-12
|
|
if(manual_chamber)
|
|
if(!CHECK_BITFIELD(auto_loading_type,OPEN_BOLT))
|
|
if(!chambered)
|
|
if(bolt_open)
|
|
if(do_after(user, 0.5 SECONDS, src))
|
|
user.visible_message(span_notice("[user] slides \the [C] into the [src]'s chamber."),span_notice("You slide \the [C] into the [src]'s chamber."))
|
|
chambered = C
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
else
|
|
return
|
|
else if(!(CHECK_BITFIELD(auto_loading_type,LOCK_OPEN_EMPTY) || (CHECK_BITFIELD(auto_loading_type,LOCK_MANUAL_LOCK))))
|
|
if(do_after(user, 1.5 SECONDS, src))
|
|
user.visible_message(span_notice("[user] holds open \the [src]'s [bolt_name] and slides [C] into the chamber before letting the bolt close again."),span_notice("You slide \the [C] into the [src]'s chamber."))
|
|
|
|
chambered = C
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
else
|
|
return
|
|
else
|
|
to_chat(user,span_warning("Open the bolt first before chambering a round!"))
|
|
return
|
|
else
|
|
to_chat(user,span_warning("Eject the current chambered round before trying to chamber a new one!"))
|
|
return
|
|
else
|
|
to_chat(user,span_warning("You can't manually chamber rounds with an open bolt gun!"))
|
|
return
|
|
user.remove_from_mob(C)
|
|
C.loc = src
|
|
update_icon()
|
|
return
|
|
else
|
|
return
|
|
if(only_open_load && !bolt_open)
|
|
to_chat(user, span_warning("[src] must have its bolt open to be loaded!"))
|
|
return
|
|
if(loaded.len >= max_shells)
|
|
to_chat(user, span_warning("[src] is full."))
|
|
return
|
|
|
|
user.remove_from_mob(C)
|
|
C.loc = src
|
|
loaded.Insert(1, C) //add to the head of the list
|
|
user.visible_message("[user] inserts \a [C] into [src].", span_notice("You insert \a [C] into [src]."))
|
|
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
|
|
else if(istype(A, /obj/item/storage))
|
|
var/obj/item/storage/storage = A
|
|
if(!(load_method & SINGLE_CASING))
|
|
return //incompatible
|
|
|
|
to_chat(user, span_notice("You start loading \the [src]."))
|
|
sleep(1 SECOND)
|
|
for(var/obj/item/ammo_casing/ammo in storage.contents)
|
|
if(caliber != ammo.caliber)
|
|
continue
|
|
|
|
load_ammo(ammo, user)
|
|
user.hud_used.update_ammo_hud(user, src)
|
|
|
|
if(loaded.len >= max_shells)
|
|
to_chat(user, span_warning("[src] is full."))
|
|
break
|
|
sleep(1 SECOND)
|
|
|
|
update_icon()
|
|
|
|
/obj/item/gun/projectile/afterattack(atom/A, mob/living/user, adjacent, params)
|
|
afteratt(A,user,adjacent,params)
|
|
if(auto_eject && ammo_magazine && ammo_magazine.stored_ammo && !ammo_magazine.stored_ammo.len && !(manual_chamber && chambered && chambered.BB != null))
|
|
ammo_magazine.loc = get_turf(src.loc)
|
|
user.visible_message(
|
|
"[ammo_magazine] falls out and clatters on the floor!",
|
|
span_notice("[ammo_magazine] falls out and clatters on the floor!")
|
|
)
|
|
if(auto_eject_sound)
|
|
playsound(src, auto_eject_sound, 40, 1)
|
|
ammo_magazine.update_icon()
|
|
ammo_magazine = null
|
|
update_icon()
|
|
|
|
/obj/item/gun/projectile/proc/afteratt(atom/A, mob/living/user, adjacent, params)
|
|
if(adjacent) return //A is adjacent, is the user, or is on the user's person
|
|
|
|
if(!user.aiming)
|
|
user.aiming = new(user)
|
|
|
|
if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A)
|
|
PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
|
|
return
|
|
|
|
if(user && user.a_intent == I_HELP && user.read_preference(/datum/preference/toggle/safefiring)) //regardless of what happens, refuse to shoot if help intent is on
|
|
to_chat(user, span_warning("You refrain from firing your [src] as your intent is set to help."))
|
|
return
|
|
|
|
else
|
|
Fire(A, user, params) //Otherwise, fire normally.
|
|
return
|
|
|
|
/obj/item/gun/projectile/special_check(var/mob/user)
|
|
if(..())
|
|
if(manual_chamber)
|
|
if(CHECK_BITFIELD(auto_loading_type,OPEN_BOLT) && !bolt_open)
|
|
to_chat(user,span_warning("This is an open bolt gun! You need to open the bolt before firing it!"))
|
|
return 0
|
|
else if(CHECK_BITFIELD(auto_loading_type,CLOSED_BOLT) && bolt_open)
|
|
to_chat(user,span_warning("This is a closed bolt gun! You need to close the bolt before firing it!"))
|
|
return 0
|
|
else if((!auto_loading_type) && bolt_open)
|
|
to_chat(user,span_warning("This is a manual action gun, the bolt or chamber must be closed before firing it!"))
|
|
return 0
|
|
else
|
|
return 1
|
|
else
|
|
return 1
|
|
|
|
/obj/item/gun/projectile/unload_ammo(mob/user, var/allow_dump=1)
|
|
if(manual_chamber && only_open_load && !bolt_open)
|
|
to_chat(user,span_warning("You must open the bolt to load or unload this gun!"))
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/gun/projectile/handle_click_empty(mob/user)
|
|
if (user)
|
|
user.visible_message("*click click*", span_danger("*click*"))
|
|
else
|
|
src.visible_message("*click click*")
|
|
playsound(src, 'sound/weapons/empty.ogg', 100, 1)
|
|
if(!manual_chamber)
|
|
process_chambered()
|
|
|
|
/obj/item/gun/projectile/Initialize(mapload, var/starts_loaded = 1)
|
|
. = ..()
|
|
if(manual_chamber)
|
|
verbs |= /obj/item/gun/projectile/verb/change_firemode
|
|
update_icon()
|
|
|
|
/obj/item/gun/projectile/verb/change_firemode()
|
|
set name = "Switch firemode"
|
|
set category = "Object"
|
|
set src in view(1)
|
|
|
|
switch_firemodes(usr)
|
|
|
|
/obj/item/gun/projectile/process_accuracy(obj/projectile, mob/living/user, atom/target, var/burst, var/held_twohanded)
|
|
. = ..()
|
|
var/obj/item/projectile/bullet/P = projectile
|
|
if(!istype(P))
|
|
return
|
|
P.velocity = muzzle_velocity
|
|
|
|
//Special ammo handling bullshit
|
|
|
|
/obj/item/gun/projectile/pirate/process_accuracy(obj/projectile, mob/living/user, atom/target, var/burst, var/held_twohanded)
|
|
. = ..()
|
|
var/obj/item/projectile/bullet/P = projectile
|
|
if(!istype(P))
|
|
return
|
|
P.sub_velocity(P.velocity * 0.3) //Yeah, a gun that supposedly shoots any bullet is gonna be pretty shit.
|
|
|
|
/obj/item/gun/projectile/revolver/lemat/process_accuracy(obj/projectile, mob/living/user, atom/target, var/burst, var/held_twohanded)
|
|
. = ..()
|
|
var/obj/item/projectile/bullet/P = projectile
|
|
P.velocity = initial(P.velocity)
|
|
if(!istype(P))
|
|
return
|
|
P.sub_velocity(P.velocity - 35)
|
|
|
|
#undef BOLT_NOEVENT
|
|
#undef BOLT_CLOSED
|
|
#undef BOLT_OPENED
|
|
#undef BOLT_LOCKED
|
|
#undef BOLT_UNLOCKED
|
|
#undef BOLT_CASING_EJECTED
|
|
#undef BOLT_CASING_CHAMBERED
|