mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2026-01-06 15:13:22 +00:00
part 2
This commit is contained in:
@@ -1,17 +1,21 @@
|
||||
/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
|
||||
distro += variance
|
||||
for (var/i = max(1, pellets), i > 0, i--)
|
||||
var/targloc = get_turf(target)
|
||||
ready_proj(target, user, quiet, zone_override, fired_from)
|
||||
var/targloc = get_turf(target)
|
||||
ready_proj(target, user, quiet, zone_override, fired_from)
|
||||
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((i / pellets - 0.5) * distro)
|
||||
spread = round(1 - 0.5) * distro
|
||||
if(!throw_proj(target, targloc, user, params, spread))
|
||||
return 0
|
||||
if(i > 1)
|
||||
newshot()
|
||||
return FALSE
|
||||
else
|
||||
if(isnull(BB))
|
||||
return FALSE
|
||||
AddComponent(/datum/component/pellet_cloud, projectile_type, pellets)
|
||||
SEND_SIGNAL(src, COMSIG_PELLET_CLOUD_INIT, target, user, fired_from, randomspread, spread, zone_override, params, distro)
|
||||
|
||||
if(click_cooldown_override)
|
||||
user.changeNext_move(click_cooldown_override)
|
||||
else
|
||||
@@ -31,7 +35,7 @@
|
||||
else
|
||||
BB.def_zone = user.zone_selected
|
||||
BB.suppressed = quiet
|
||||
|
||||
|
||||
if(isgun(fired_from))
|
||||
var/obj/item/gun/G = fired_from
|
||||
BB.damage *= G.projectile_damage_multiplier
|
||||
|
||||
@@ -21,3 +21,16 @@
|
||||
name = "1.95x129mm incendiary bullet casing"
|
||||
desc = "A 1.95x129mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames."
|
||||
projectile_type = /obj/item/projectile/bullet/incendiary/mm195x129
|
||||
|
||||
/obj/item/ammo_casing/mm712x82/match
|
||||
name = "7.12x82mm match bullet casing"
|
||||
desc = "A 7.12x82mm bullet casing manufactured to unfailingly high standards, you could pull off some cool trickshots with this."
|
||||
projectile_type = /obj/projectile/bullet/mm712x82_match
|
||||
|
||||
/obj/projectile/bullet/mm712x82_match
|
||||
name = "7.12x82mm match bullet"
|
||||
damage = 40
|
||||
ricochets_max = 2
|
||||
ricochet_chance = 60
|
||||
ricochet_auto_aim_range = 4
|
||||
ricochet_incidence_leeway = 35
|
||||
@@ -11,6 +11,12 @@
|
||||
desc = "A .357 armor-piercing bullet casing."
|
||||
projectile_type = /obj/item/projectile/bullet/a357/ap
|
||||
|
||||
/obj/item/ammo_casing/a357/match
|
||||
name = ".357 match bullet casing"
|
||||
desc = "A .357 bullet casing, manufactured to exceedingly high standards."
|
||||
caliber = "357"
|
||||
projectile_type = /obj/projectile/bullet/a357/match
|
||||
|
||||
// 7.62x38mmR (Nagant Revolver)
|
||||
|
||||
/obj/item/ammo_casing/n762
|
||||
@@ -47,4 +53,19 @@
|
||||
name = ".38 Iceblox bullet casing"
|
||||
desc = "A .38 Iceblox bullet casing."
|
||||
caliber = "38"
|
||||
projectile_type = /obj/item/projectile/bullet/c38/iceblox
|
||||
projectile_type = /obj/item/projectile/bullet/c38/iceblox
|
||||
|
||||
/obj/item/ammo_casing/c38/match
|
||||
name = ".38 Match bullet casing"
|
||||
desc = "A .38 bullet casing, manufactured to exceedingly high standards."
|
||||
projectile_type = /obj/projectile/bullet/c38/match
|
||||
|
||||
/obj/item/ammo_casing/c38/match/bouncy
|
||||
name = ".38 Rubber bullet casing"
|
||||
desc = "A .38 rubber bullet casing, manufactured to exceedingly high standards."
|
||||
projectile_type = /obj/projectile/bullet/c38/match/bouncy
|
||||
|
||||
/obj/item/ammo_casing/c38/dumdum
|
||||
name = ".38 DumDum bullet casing"
|
||||
desc = "A .38 DumDum bullet casing."
|
||||
projectile_type = /obj/projectile/bullet/c38/dumdum
|
||||
@@ -7,6 +7,11 @@
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_box/a357/match
|
||||
name = "speed loader (.357 Match)"
|
||||
desc = "Designed to quickly reload revolvers. These rounds are manufactured within extremely tight tolerances, making them easy to show off trickshots with."
|
||||
ammo_type = /obj/item/ammo_casing/a357/match
|
||||
|
||||
/obj/item/ammo_box/a357/ap
|
||||
name = "speed loader (.357 AP)"
|
||||
ammo_type = /obj/item/ammo_casing/a357/ap
|
||||
|
||||
@@ -20,3 +20,7 @@
|
||||
/obj/item/ammo_box/magazine/mm195x129/update_icon()
|
||||
..()
|
||||
icon_state = "a762-[round(ammo_count(),10)]"
|
||||
|
||||
/obj/item/ammo_box/magazine/mm712x82/match
|
||||
name = "box magazine (Match 7.12x82mm)"
|
||||
ammo_type = /obj/item/ammo_casing/mm712x82/match
|
||||
@@ -56,9 +56,25 @@
|
||||
var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle
|
||||
var/spread = 0 //amount (in degrees) of projectile spread
|
||||
animate_movement = 0 //Use SLIDE_STEPS in conjunction with legacy
|
||||
/// how many times we've ricochet'd so far (instance variable, not a stat)
|
||||
var/ricochets = 0
|
||||
var/ricochets_max = 2
|
||||
var/ricochet_chance = 30
|
||||
/// how many times we can ricochet max
|
||||
var/ricochets_max = 0
|
||||
/// 0-100, the base chance of ricocheting, before being modified by the atom we shoot and our chance decay
|
||||
var/ricochet_chance = 0
|
||||
/// 0-1 (or more, I guess) multiplier, the ricochet_chance is modified by multiplying this after each ricochet
|
||||
var/ricochet_decay_chance = 0.7
|
||||
/// 0-1 (or more, I guess) multiplier, the projectile's damage is modified by multiplying this after each ricochet
|
||||
var/ricochet_decay_damage = 0.7
|
||||
/// On ricochet, if nonzero, we consider all mobs within this range of our projectile at the time of ricochet to home in on like Revolver Ocelot, as governed by ricochet_auto_aim_angle
|
||||
var/ricochet_auto_aim_range = 0
|
||||
/// On ricochet, if ricochet_auto_aim_range is nonzero, we'll consider any mobs within this range of the normal angle of incidence to home in on, higher = more auto aim
|
||||
var/ricochet_auto_aim_angle = 30
|
||||
/// the angle of impact must be within this many degrees of the struck surface, set to 0 to allow any angle
|
||||
var/ricochet_incidence_leeway = 40
|
||||
|
||||
///If the object being hit can pass ths damage on to something else, it should not do it for this bullet
|
||||
var/force_hit = FALSE
|
||||
|
||||
//Hitscan
|
||||
var/hitscan = FALSE //Whether this is hitscan. If it is, speed is basically ignored.
|
||||
@@ -131,6 +147,11 @@
|
||||
|
||||
var/temporary_unstoppable_movement = FALSE
|
||||
|
||||
///If defined, on hit we create an item of this type then call hitby() on the hit target with this
|
||||
var/shrapnel_type
|
||||
///If TRUE, hit mobs even if they're on the floor and not our target
|
||||
var/hit_stunned_targets = FALSE
|
||||
|
||||
/obj/item/projectile/Initialize()
|
||||
. = ..()
|
||||
permutated = list()
|
||||
@@ -146,6 +167,7 @@
|
||||
on_range()
|
||||
|
||||
/obj/item/projectile/proc/on_range() //if we want there to be effects when they reach the end of their range
|
||||
SEND_SIGNAL(src, COMSIG_PROJECTILE_RANGE_OUT)
|
||||
qdel(src)
|
||||
|
||||
//to get the correct limb (if any) for the projectile hit message
|
||||
@@ -165,6 +187,10 @@
|
||||
/obj/item/projectile/proc/on_hit(atom/target, blocked = FALSE)
|
||||
if(fired_from)
|
||||
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle)
|
||||
|
||||
// i know that this is probably more with wands and gun mods in mind, but it's a bit silly that the projectile on_hit signal doesn't ping the projectile itself.
|
||||
// maybe we care what the projectile thinks! See about combining these via args some time when it's not 5AM
|
||||
SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle)
|
||||
var/turf/target_loca = get_turf(target)
|
||||
|
||||
var/hitx
|
||||
@@ -219,7 +245,10 @@
|
||||
var/limb_hit = L.check_limb_hit(def_zone)//to get the correct message info.
|
||||
if(limb_hit)
|
||||
organ_hit_text = " in \the [parse_zone(limb_hit)]"
|
||||
if(suppressed)
|
||||
|
||||
if(suppressed==SUPPRESSED_VERY)
|
||||
playsound(loc, hitsound, 5, TRUE, -1)
|
||||
else if(suppressed)
|
||||
playsound(loc, hitsound, 5, 1, -1)
|
||||
to_chat(L, "<span class='userdanger'>You're shot by \a [src][organ_hit_text]!</span>")
|
||||
else
|
||||
@@ -250,7 +279,23 @@
|
||||
return 50 //if the projectile doesn't do damage, play its hitsound at 50% volume
|
||||
|
||||
/obj/item/projectile/proc/on_ricochet(atom/A)
|
||||
return
|
||||
if(!ricochet_auto_aim_angle || !ricochet_auto_aim_range)
|
||||
return
|
||||
|
||||
var/mob/living/unlucky_sob
|
||||
var/best_angle = ricochet_auto_aim_angle
|
||||
if(firer && HAS_TRAIT(firer, TRAIT_NICE_SHOT))
|
||||
best_angle += NICE_SHOT_RICOCHET_BONUS
|
||||
for(var/mob/living/L in range(ricochet_auto_aim_range, src.loc))
|
||||
if(L.stat == DEAD || !isInSight(src, L))
|
||||
continue
|
||||
var/our_angle = abs(closer_angle_difference(Angle, Get_Angle(src.loc, L.loc)))
|
||||
if(our_angle < best_angle)
|
||||
best_angle = our_angle
|
||||
unlucky_sob = L
|
||||
|
||||
if(unlucky_sob)
|
||||
setAngle(Get_Angle(src, unlucky_sob.loc))
|
||||
|
||||
/obj/item/projectile/proc/store_hitscan_collision(datum/point/pcache)
|
||||
beam_segments[beam_index] = pcache
|
||||
@@ -259,13 +304,15 @@
|
||||
|
||||
/obj/item/projectile/Bump(atom/A)
|
||||
var/turf/T = get_turf(A)
|
||||
if(trajectory && check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max)
|
||||
if(trajectory && ricochets < ricochets_max && check_ricochet_flag(A) && check_ricochet(A))
|
||||
var/datum/point/pcache = trajectory.copy_to()
|
||||
ricochets++
|
||||
if(A.handle_ricochet(src))
|
||||
on_ricochet(A)
|
||||
ignore_source_check = TRUE
|
||||
decayedRange = max(0, decayedRange - reflect_range_decrease)
|
||||
ricochet_chance *= ricochet_decay_chance
|
||||
damage *= ricochet_decay_damage
|
||||
range = decayedRange
|
||||
if(hitscan)
|
||||
store_hitscan_collision(pcache)
|
||||
@@ -344,13 +391,18 @@
|
||||
return T
|
||||
//Returns null if nothing at all was found.
|
||||
|
||||
/obj/item/projectile/proc/check_ricochet()
|
||||
if(prob(ricochet_chance))
|
||||
/obj/projectile/proc/check_ricochet(atom/A)
|
||||
var/chance = ricochet_chance * A.ricochet_chance_mod
|
||||
if(firer && HAS_TRAIT(firer, TRAIT_NICE_SHOT))
|
||||
chance += NICE_SHOT_RICOCHET_BONUS
|
||||
if(prob(chance))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/projectile/proc/check_ricochet_flag(atom/A)
|
||||
if(A.flags_1 & CHECK_RICOCHET_1)
|
||||
if((flag in list("energy", "laser")) && (A.flags_ricochet & RICOCHET_SHINY))
|
||||
return TRUE
|
||||
if((flag in list("bomb", "bullet")) && (A.flags_ricochet & RICOCHET_HARD))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -391,6 +443,8 @@
|
||||
/obj/item/projectile/proc/fire(angle, atom/direct_target)
|
||||
if(fired_from)
|
||||
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original) //If no angle needs to resolve it from xo/yo!
|
||||
if(shrapnel_type)
|
||||
AddElement(/datum/element/embed, projectile_payload = shrapnel_type)
|
||||
if(!log_override && firer && original)
|
||||
log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]")
|
||||
if(direct_target)
|
||||
|
||||
@@ -15,6 +15,38 @@
|
||||
/obj/item/projectile/bullet/c38
|
||||
name = ".38 bullet"
|
||||
damage = 25
|
||||
ricochets_max = 2
|
||||
ricochet_chance = 50
|
||||
ricochet_auto_aim_angle = 10
|
||||
ricochet_auto_aim_range = 3
|
||||
|
||||
/obj/projectile/bullet/c38/match
|
||||
name = ".38 Match bullet"
|
||||
ricochets_max = 4
|
||||
ricochet_chance = 100
|
||||
ricochet_auto_aim_angle = 40
|
||||
ricochet_auto_aim_range = 5
|
||||
ricochet_incidence_leeway = 50
|
||||
ricochet_decay_chance = 1
|
||||
ricochet_decay_damage = 1
|
||||
|
||||
/obj/projectile/bullet/c38/match/bouncy
|
||||
name = ".38 Rubber bullet"
|
||||
damage = 10
|
||||
stamina = 30
|
||||
armour_penetration = -30
|
||||
ricochets_max = 6
|
||||
ricochet_incidence_leeway = 70
|
||||
ricochet_chance = 130
|
||||
ricochet_decay_damage = 0.8
|
||||
shrapnel_type = NONE
|
||||
|
||||
/obj/projectile/bullet/c38/dumdum
|
||||
name = ".38 DumDum bullet"
|
||||
damage = 15
|
||||
armour_penetration = -30
|
||||
ricochets_max = 0
|
||||
shrapnel_type = /obj/item/shrapnel/bullet/c38/dumdum
|
||||
|
||||
/obj/item/projectile/bullet/c38/rubber
|
||||
name = ".38 rubber bullet"
|
||||
@@ -24,6 +56,7 @@
|
||||
/obj/item/projectile/bullet/c38/trac
|
||||
name = ".38 TRAC bullet"
|
||||
damage = 10
|
||||
ricochets_max = 0
|
||||
|
||||
/obj/item/projectile/bullet/c38/trac/on_hit(atom/target, blocked = FALSE)
|
||||
. = ..()
|
||||
@@ -39,6 +72,7 @@
|
||||
/obj/item/projectile/bullet/c38/hotshot //similar to incendiary bullets, but do not leave a flaming trail
|
||||
name = ".38 Hot Shot bullet"
|
||||
damage = 20
|
||||
ricochets_max = 0
|
||||
|
||||
/obj/item/projectile/bullet/c38/hotshot/on_hit(atom/target, blocked = FALSE)
|
||||
. = ..()
|
||||
@@ -51,6 +85,7 @@
|
||||
name = ".38 Iceblox bullet"
|
||||
damage = 20
|
||||
var/temperature = 100
|
||||
ricochets_max = 0
|
||||
|
||||
/obj/item/projectile/bullet/c38/iceblox/on_hit(atom/target, blocked = FALSE)
|
||||
. = ..()
|
||||
@@ -68,4 +103,14 @@
|
||||
/obj/item/projectile/bullet/a357/ap
|
||||
name = ".357 armor-piercing bullet"
|
||||
damage = 45
|
||||
armour_penetration = 45
|
||||
armour_penetration = 45
|
||||
|
||||
// admin only really, for ocelot memes
|
||||
/obj/projectile/bullet/a357/match
|
||||
name = ".357 match bullet"
|
||||
ricochets_max = 5
|
||||
ricochet_chance = 140
|
||||
ricochet_auto_aim_angle = 50
|
||||
ricochet_auto_aim_range = 6
|
||||
ricochet_incidence_leeway = 80
|
||||
ricochet_decay_chance = 1
|
||||
Reference in New Issue
Block a user