Files
Bubberstation/code/modules/projectiles/ammunition/_firing.dm
SkyratBot 57af94957d [MIRROR] Different pen types have unique behavior when used in foam darts. [MDB IGNORE] (#25183)
* Different pen types have unique behavior when used in foam darts. (#79587)

## About The Pull Request

This PR makes the following changes:
- Refactors inserting items into foam darts into a component on items
that can be inserted into darts
- Adds the aforementioned component to pens
- Provides an inspection tip for how to modify a foam dart
- Gives different pen types specific behavior when used in a foam dart

Pens typically give a foam dart 5 brute and 50% embed chance (affected
by falloff). The following types of pens give the specified properties
(usually directly derived from the pen's stats and additional
functions):
- Red pen (and four-color pen set to red): Slightly faster dart
- Captain's fountain pen: Slightly faster dart, and 75% base embed
chance
- Sleepypen: Tries to inject its reagents into the hit mob, but doesn't
penetrate thick clothing like syringe guns do
- Energy Dagger: 35 brute, 100% base embed chance, and slightly faster
dart
- Survival Pen: Mines rocks on impact
- Fine Tip Pen (if someone somehow manages to get one): 100 bare wound
bonus and 9000 demolition modifier

## Why It's Good For The Game

Expands the emergent gameplay possibilities of using pens in foam darts.

While there are balance risks involved with traitors being able to buy
the equivalent of reusable 45u syringe shots and 35 brute bullets, you
are not likely to get your pen back once it hits its target, unless you
somehow have the recall spell and have bound the pen to it. There are
probably more TC-efficient ways to achieve comparable projectile
weaponry, but foam dart guns have an air of subtlety to them... at least
until your skin is pierced by a pointy writing implement that may also
be something more deadly. If maintainers still have balance concerns,
please let me know.

## Changelog

🆑
add: Certain types of pens now function like you expect they would when
inserted into a foam dart
qol: Examining a foam dart closely will show you how to modify it, or
what it is modified with
/🆑

* Different pen types have unique behavior when used in foam darts.

---------

Co-authored-by: Y0SH1M4S73R <legoboyo@earthlink.net>
2023-11-21 22:54:35 -05:00

97 lines
4.1 KiB
Plaintext

/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
distro += variance
var/targloc = get_turf(target)
ready_proj(target, user, quiet, zone_override, fired_from)
var/obj/projectile/thrown_proj
if(pellets == 1)
if(distro) //We have to spread a pixel-precision bullet. throw_proj was called before so angles should exist by now...
if(randomspread)
spread = round((rand() - 0.5) * distro)
else //Smart spread
spread = round(1 - 0.5) * distro
thrown_proj = throw_proj(target, targloc, user, params, spread, fired_from)
if(isnull(thrown_proj))
return FALSE
else
if(isnull(loaded_projectile))
return FALSE
AddComponent(/datum/component/pellet_cloud, projectile_type, pellets)
//var/next_delay = click_cooldown_override || CLICK_CD_RANGE // ORIGINAL
var/next_delay = click_cooldown_override || ((user.staminaloss <= STAMINA_THRESHOLD_TIRED_CLICK_CD) ? CLICK_CD_RANGE : CLICK_CD_RANGE_TIRED) // SKYRAT EDIT CHANGE
if(HAS_TRAIT(user, TRAIT_DOUBLE_TAP))
next_delay = round(next_delay * 0.5)
user.changeNext_move(next_delay)
if(!tk_firing(user, fired_from))
user.newtonian_move(get_dir(target, user))
else if(ismovable(fired_from))
var/atom/movable/firer = fired_from
if(!firer.newtonian_move(get_dir(target, fired_from), instant = TRUE))
var/throwtarget = get_step(fired_from, get_dir(target, fired_from))
firer.safe_throw_at(throwtarget, 1, 2)
update_appearance()
SEND_SIGNAL(src, COMSIG_FIRE_CASING, target, user, fired_from, randomspread, spread, zone_override, params, distro, thrown_proj)
return TRUE
/obj/item/ammo_casing/proc/tk_firing(mob/living/user, atom/fired_from)
return fired_from != user && !user.contains(fired_from)
/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", atom/fired_from)
if (!loaded_projectile)
return
loaded_projectile.original = target
loaded_projectile.firer = user
loaded_projectile.fired_from = fired_from
loaded_projectile.hit_prone_targets = user.combat_mode
if (zone_override)
loaded_projectile.def_zone = zone_override
else
loaded_projectile.def_zone = user.zone_selected
loaded_projectile.suppressed = quiet
if(isgun(fired_from))
var/obj/item/gun/G = fired_from
loaded_projectile.damage *= G.projectile_damage_multiplier
loaded_projectile.stamina *= G.projectile_damage_multiplier
loaded_projectile.wound_bonus += G.projectile_wound_bonus
loaded_projectile.bare_wound_bonus += G.projectile_wound_bonus
if(tk_firing(user, fired_from))
loaded_projectile.ignore_source_check = TRUE
if(reagents && loaded_projectile.reagents)
reagents.trans_to(loaded_projectile, reagents.total_volume, transferred_by = user) //For chemical darts/bullets
qdel(reagents)
SEND_SIGNAL(src, COMSIG_CASING_READY_PROJECTILE, target, user, quiet, zone_override, fired_from)
/obj/item/ammo_casing/proc/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread, atom/fired_from)
var/turf/curloc = get_turf(fired_from)
if (!istype(targloc) || !istype(curloc) || !loaded_projectile)
return null
var/firing_dir
if(loaded_projectile.firer)
firing_dir = get_dir(fired_from, target)
if(!loaded_projectile.suppressed && firing_effect_type && !tk_firing(user, fired_from))
new firing_effect_type(get_turf(src), firing_dir)
var/direct_target
if(target && curloc.Adjacent(targloc, target=targloc, mover=src)) //if the target is right on our location or adjacent (including diagonally if reachable) we'll skip the travelling code in the proj's fire()
direct_target = target
if(!direct_target)
var/modifiers = params2list(params)
loaded_projectile.preparePixelProjectile(target, fired_from, modifiers, spread)
var/obj/projectile/loaded_projectile_cache = loaded_projectile
loaded_projectile = null
loaded_projectile_cache.fire(null, direct_target)
return loaded_projectile_cache
/obj/item/ammo_casing/proc/spread(turf/target, turf/current, distro)
var/dx = abs(target.x - current.x)
var/dy = abs(target.y - current.y)
return locate(target.x + round(gaussian(0, distro) * (dy+2)/8, 1), target.y + round(gaussian(0, distro) * (dx+2)/8, 1), target.z)