mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-19 05:26:28 +00:00
## About The Pull Request A gun's projectile damage multiplier is now reflected in its "show combat info" examine, so now the shots-to-crit on guns with a modified projectile damage multiplier (say, the PP-95 SMG, under the slightly inaccurate typepath `automatic/plastikov`) is accurate. This applies to both energy weapons and ballistics. Also, added a new variable that multiplies a fired projectile's wound bonus. Could be used to make guns really bad at wounding or good at wounding innately for... reasons? Not really touched by anything for now. ## Why It's Good For The Game Being able to account for projectile damage multiplier probably helps in regards to "how many bullets DOES it take to crit someone else?", since you don't really get told about it in-game. The wound bonus thing could be used for adminbus as a joke or to make a gun more distinct in regards to "how often do I make someone's blood fall out/leg break/etc." ## Changelog 🆑 fix: Projectile damage multipliers on guns are now reflected in their combat information. admin: Admins can now make a gun's fired projectiles better or worse at wounding by changing the gun's projectile_wound_bonus. Surely this will not have any repercussions. /🆑 --------- Co-authored-by: Hatterhat <Hatterhat@users.noreply.github.com>
160 lines
6.2 KiB
Plaintext
160 lines
6.2 KiB
Plaintext
/obj/item/ammo_casing
|
|
name = "bullet casing"
|
|
desc = "A bullet casing."
|
|
icon = 'icons/obj/weapons/guns/ammo.dmi'
|
|
icon_state = "s-casing"
|
|
worn_icon_state = "bullet"
|
|
flags_1 = CONDUCT_1
|
|
slot_flags = ITEM_SLOT_BELT
|
|
throwforce = 0
|
|
w_class = WEIGHT_CLASS_TINY
|
|
custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT*5)
|
|
override_notes = TRUE
|
|
///What sound should play when this ammo is fired
|
|
var/fire_sound = null
|
|
///Which kind of guns it can be loaded into
|
|
var/caliber = null
|
|
///The bullet type to create when New() is called
|
|
var/projectile_type = null
|
|
///the loaded projectile in this ammo casing
|
|
var/obj/projectile/loaded_projectile = null
|
|
///Pellets for spreadshot
|
|
var/pellets = 1
|
|
///Variance for inaccuracy fundamental to the casing
|
|
var/variance = 0
|
|
///Randomspread for automatics
|
|
var/randomspread = 0
|
|
///Delay for energy weapons
|
|
var/delay = 0
|
|
///Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown.
|
|
var/click_cooldown_override = 0
|
|
///the visual effect appearing when the ammo is fired.
|
|
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect
|
|
///Does this leave a casing behind?
|
|
var/is_cased_ammo = TRUE
|
|
///pacifism check for boolet, set to FALSE if bullet is non-lethal
|
|
var/harmful = TRUE
|
|
|
|
/obj/item/ammo_casing/spent
|
|
name = "spent bullet casing"
|
|
loaded_projectile = null
|
|
|
|
/obj/item/ammo_casing/Initialize(mapload)
|
|
. = ..()
|
|
if(projectile_type)
|
|
loaded_projectile = new projectile_type(src)
|
|
pixel_x = base_pixel_x + rand(-10, 10)
|
|
pixel_y = base_pixel_y + rand(-10, 10)
|
|
setDir(pick(GLOB.alldirs))
|
|
update_appearance()
|
|
|
|
/obj/item/ammo_casing/Destroy()
|
|
var/turf/T = get_turf(src)
|
|
if(T && !loaded_projectile && is_station_level(T.z))
|
|
SSblackbox.record_feedback("tally", "station_mess_destroyed", 1, name)
|
|
QDEL_NULL(loaded_projectile)
|
|
return ..()
|
|
|
|
/obj/item/ammo_casing/add_weapon_description()
|
|
AddElement(/datum/element/weapon_description, attached_proc = PROC_REF(add_notes_ammo))
|
|
|
|
/**
|
|
*
|
|
* Outputs type-specific weapon stats for ammunition based on the projectile loaded inside the casing.
|
|
* Distinguishes between critting and stam-critting in separate lines
|
|
*
|
|
*/
|
|
/obj/item/ammo_casing/proc/add_notes_ammo()
|
|
// Try to get a projectile to derive stats from
|
|
var/obj/projectile/exam_proj = projectile_type
|
|
var/initial_damage = initial(exam_proj.damage)
|
|
var/initial_stamina = initial(exam_proj.stamina)
|
|
// projectile damage multiplier for guns with snowflaked damage multipliers
|
|
var/proj_damage_mult = 1
|
|
if(!ispath(exam_proj) || pellets == 0)
|
|
return
|
|
|
|
// are we in an ammo box?
|
|
if(isammobox(loc))
|
|
var/obj/item/ammo_box/our_box = loc
|
|
// is our ammo box in a gun?
|
|
if(isgun(our_box.loc))
|
|
var/obj/item/gun/our_gun = our_box.loc
|
|
// grab the damage multiplier
|
|
proj_damage_mult = our_gun.projectile_damage_multiplier
|
|
// if not, are we just in a gun e.g. chambered
|
|
else if(isgun(loc))
|
|
var/obj/item/gun/our_gun = loc
|
|
// grab the damage multiplier.
|
|
proj_damage_mult = our_gun.projectile_damage_multiplier
|
|
var/list/readout = list()
|
|
if(proj_damage_mult <= 0 || (initial_damage <= 0 && initial_stamina <= 0))
|
|
return "Our legal team has determined the offensive nature of these [span_warning(caliber)] rounds to be esoteric."
|
|
// No dividing by 0
|
|
if(initial_damage)
|
|
readout += "Most monkeys our legal team subjected to these [span_warning(caliber)] rounds succumbed to their wounds after [span_warning("[HITS_TO_CRIT((initial(exam_proj.damage) * proj_damage_mult) * pellets)] shot\s")] at point-blank, taking [span_warning("[pellets] shot\s")] per round."
|
|
if(initial_stamina)
|
|
readout += "[!readout.len ? "Most monkeys" : "More fortunate monkeys"] collapsed from exhaustion after [span_warning("[HITS_TO_CRIT((initial(exam_proj.stamina) * proj_damage_mult) * pellets)] impact\s")] of these [span_warning("[caliber]")] rounds."
|
|
return readout.Join("\n") // Sending over a single string, rather than the whole list
|
|
|
|
/obj/item/ammo_casing/update_icon_state()
|
|
icon_state = "[initial(icon_state)][loaded_projectile ? "-live" : null]"
|
|
return ..()
|
|
|
|
/obj/item/ammo_casing/update_desc()
|
|
desc = "[initial(desc)][loaded_projectile ? null : " This one is spent."]"
|
|
return ..()
|
|
|
|
/*
|
|
* On accidental consumption, 'spend' the ammo, and add in some gunpowder
|
|
*/
|
|
/obj/item/ammo_casing/on_accidental_consumption(mob/living/carbon/victim, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE)
|
|
if(loaded_projectile)
|
|
loaded_projectile = null
|
|
update_appearance()
|
|
victim.reagents?.add_reagent(/datum/reagent/gunpowder, 3)
|
|
source_item?.reagents?.add_reagent(/datum/reagent/gunpowder, source_item.reagents.total_volume*(2/3))
|
|
|
|
return ..()
|
|
|
|
//proc to magically refill a casing with a new projectile
|
|
/obj/item/ammo_casing/proc/newshot() //For energy weapons, syringe gun, shotgun shells and wands (!).
|
|
if(!loaded_projectile)
|
|
loaded_projectile = new projectile_type(src, src)
|
|
|
|
/obj/item/ammo_casing/attackby(obj/item/I, mob/user, params)
|
|
if(istype(I, /obj/item/ammo_box))
|
|
var/obj/item/ammo_box/box = I
|
|
if(isturf(loc))
|
|
var/boolets = 0
|
|
for(var/obj/item/ammo_casing/bullet in loc)
|
|
if (box.stored_ammo.len >= box.max_ammo)
|
|
break
|
|
if (bullet.loaded_projectile)
|
|
if (box.give_round(bullet, 0))
|
|
boolets++
|
|
else
|
|
continue
|
|
if (boolets > 0)
|
|
box.update_appearance()
|
|
to_chat(user, span_notice("You collect [boolets] shell\s. [box] now contains [box.stored_ammo.len] shell\s."))
|
|
else
|
|
to_chat(user, span_warning("You fail to collect anything!"))
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/ammo_casing/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
|
bounce_away(FALSE, NONE)
|
|
return ..()
|
|
|
|
/obj/item/ammo_casing/proc/bounce_away(still_warm = FALSE, bounce_delay = 3)
|
|
if(!is_cased_ammo)
|
|
return
|
|
update_appearance()
|
|
SpinAnimation(10, 1)
|
|
var/turf/T = get_turf(src)
|
|
if(still_warm && T?.bullet_sizzle)
|
|
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), src, 'sound/items/welder.ogg', 20, 1), bounce_delay) //If the turf is made of water and the shell casing is still hot, make a sizzling sound when it's ejected.
|
|
else if(T?.bullet_bounce_sound)
|
|
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), src, T.bullet_bounce_sound, 20, 1), bounce_delay) //Soft / non-solid turfs that shouldn't make a sound when a shell casing is ejected over them.
|