Refactors projectile ricochets (#25764)

* same taste, twice the speed

* pulls proc/handle_ricochet() to the atom level. adds var/flags_ricochet and related defines.

* space indentation sneaks its way in yet again

---------

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
This commit is contained in:
chuga-git
2024-06-12 14:08:57 -05:00
committed by GitHub
parent c46630b1ea
commit 438faac253
10 changed files with 86 additions and 37 deletions
@@ -61,16 +61,4 @@
brute_resist = 0.5
explosion_block = 2
point_return = 9
flags_2 = CHECK_RICOCHET_2
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
var/turf/p_turf = get_turf(P)
var/face_direction = get_dir(src, p_turf)
var/face_angle = dir2angle(face_direction)
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180))
if(abs(incidence_s) > 90 && abs(incidence_s) < 270)
return FALSE
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
P.set_angle(new_angle_s)
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
return TRUE
flags_ricochet = RICOCHET_SHINY
+41 -5
View File
@@ -66,9 +66,6 @@
var/immolate = 0
var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all.
var/impact_effect_type //what type of impact effect to show when hitting something
var/ricochets = 0
var/ricochets_max = 2
var/ricochet_chance = 30
var/log_override = FALSE //whether print to admin attack logs or just keep it in the diary
@@ -114,6 +111,27 @@
var/impact_light_color_override
var/hitscan_duration = 0.3 SECONDS
/// how many times we've ricochet'd so far (instance variable, not a stat)
var/ricochets = 0
/// how many times we can ricochet max
var/ricochets_max = 0
/// how many times we have to ricochet min (unless we hit an atom we can ricochet off)
var/min_ricochets = 0
/// 0-100 (or more, I guess), 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
/// Can our ricochet autoaim hit our firer?
var/ricochet_shoots_firer = TRUE
/obj/item/projectile/New()
return ..()
@@ -429,7 +447,21 @@
/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
for(var/mob/living/L in range(ricochet_auto_aim_range, src.loc))
if(L.stat == DEAD || !isInSight(src, L) || (!ricochet_shoots_firer && L == firer))
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)
set_angle(get_angle(src, unlucky_sob.loc))
/obj/item/projectile/proc/check_ricochet()
if(prob(ricochet_chance))
@@ -437,8 +469,12 @@
return FALSE
/obj/item/projectile/proc/check_ricochet_flag(atom/A)
if(A.flags_2 & CHECK_RICOCHET_2)
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
/obj/item/projectile/set_angle(new_angle)