mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
## About The Pull Request Forgot .dir during the proj refactor, yikes. ## Changelog 🆑 fix: Fixed all parried projectiles only going up or down /🆑
125 lines
5.3 KiB
Plaintext
125 lines
5.3 KiB
Plaintext
/// Add to a projectile to allow it to be parried by mobs with a certain trait (TRAIT_MINING_PARRYING by default)
|
|
/datum/component/parriable_projectile
|
|
/// List of all turfs the projectile passed on its last loop and we assigned comsigs to
|
|
var/list/turf/parry_turfs = list()
|
|
/// List of all mobs who have clicked on a parry turf in last moveloop
|
|
var/list/mob/parriers = list()
|
|
/// When the projectile was created
|
|
var/fire_time = 0
|
|
/// If this projectile has been parried
|
|
var/parried = FALSE
|
|
/// How much this projectile is sped up when parried
|
|
var/parry_speed_mult
|
|
/// How much this projectile's damage is increased when parried
|
|
var/parry_damage_mult
|
|
/// How much this projectile is sped up when boosted (parried by owner)
|
|
var/boost_speed_mult
|
|
/// How much this projectile's damage is increased when boosted (parried by owner)
|
|
var/boost_damage_mult
|
|
/// Trait required to be able to parry this projectile
|
|
var/parry_trait
|
|
/// For how long do valid tiles persist? Acts as clientside lag compensation
|
|
var/grace_period
|
|
/// Callback for special effects upon parrying
|
|
var/datum/callback/parry_callback
|
|
|
|
/datum/component/parriable_projectile/Initialize(parry_speed_mult = 1.25, parry_damage_mult = 1.15, boost_speed_mult = 1.6, boost_damage_mult = 1.5, parry_trait = TRAIT_MINING_PARRYING, grace_period = 0.25 SECONDS, datum/callback/parry_callback = null)
|
|
if(!isprojectile(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
src.parry_speed_mult = parry_speed_mult
|
|
src.parry_damage_mult = parry_damage_mult
|
|
src.boost_speed_mult = boost_speed_mult
|
|
src.boost_damage_mult = boost_damage_mult
|
|
src.parry_trait = parry_trait
|
|
src.grace_period = grace_period
|
|
src.parry_callback = parry_callback
|
|
fire_time = world.time
|
|
|
|
/datum/component/parriable_projectile/Destroy(force)
|
|
for (var/turf/parry_turf as anything in parry_turfs)
|
|
UnregisterSignal(parry_turf, COMSIG_CLICK)
|
|
. = ..()
|
|
|
|
/datum/component/parriable_projectile/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_PROJECTILE_MOVE_PROCESS_STEP, PROC_REF(on_moved))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(before_move))
|
|
RegisterSignal(parent, COMSIG_PROJECTILE_BEFORE_MOVE, PROC_REF(before_move))
|
|
RegisterSignal(parent, COMSIG_PROJECTILE_SELF_PREHIT, PROC_REF(before_hit))
|
|
|
|
/datum/component/parriable_projectile/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_PROJECTILE_MOVE_PROCESS_STEP, COMSIG_MOVABLE_MOVED, COMSIG_PROJECTILE_BEFORE_MOVE, COMSIG_PROJECTILE_SELF_PREHIT))
|
|
|
|
/datum/component/parriable_projectile/proc/before_move(obj/projectile/source)
|
|
SIGNAL_HANDLER
|
|
|
|
var/list/turfs_to_remove = list()
|
|
for (var/turf/parry_turf as anything in parry_turfs)
|
|
if (parry_turfs[parry_turf] < world.time)
|
|
turfs_to_remove += parry_turf
|
|
|
|
for (var/turf/parry_turf as anything in turfs_to_remove)
|
|
parry_turfs -= parry_turf
|
|
UnregisterSignal(parry_turf, COMSIG_CLICK)
|
|
|
|
var/list/parriers_to_remove = list()
|
|
for (var/mob/parrier as anything in parriers)
|
|
if (parriers[parrier] < world.time)
|
|
parriers_to_remove += parrier
|
|
|
|
for (var/mob/parrier as anything in parriers_to_remove)
|
|
parriers_to_remove -= parrier
|
|
|
|
/datum/component/parriable_projectile/proc/on_moved(obj/projectile/source)
|
|
SIGNAL_HANDLER
|
|
if (!isturf(source.loc) || parry_turfs[source.loc])
|
|
return
|
|
parry_turfs[source.loc] = world.time + grace_period
|
|
RegisterSignal(source.loc, COMSIG_CLICK, PROC_REF(on_turf_click))
|
|
|
|
/datum/component/parriable_projectile/proc/on_turf_click(turf/source, atom/location, control, list/params, mob/user)
|
|
SIGNAL_HANDLER
|
|
if (!HAS_TRAIT(user, parry_trait))
|
|
return
|
|
var/obj/projectile/proj_parent = parent
|
|
if (proj_parent.firer == user && (fire_time + grace_period > world.time) && !parried)
|
|
attempt_parry(proj_parent, user)
|
|
return
|
|
parriers[user] = world.time + grace_period
|
|
|
|
/datum/component/parriable_projectile/proc/before_hit(obj/projectile/source, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if (!istype(user) || !parriers[user] || parried)
|
|
return
|
|
|
|
parriers -= user
|
|
return attempt_parry(source, user)
|
|
|
|
/datum/component/parriable_projectile/proc/attempt_parry(obj/projectile/source, mob/user)
|
|
if (QDELETED(source) || source.deletion_queued)
|
|
return NONE
|
|
|
|
if (SEND_SIGNAL(user, COMSIG_LIVING_PROJECTILE_PARRIED, source) & INTERCEPT_PARRY_EFFECTS)
|
|
return NONE
|
|
|
|
parried = TRUE
|
|
if (source.firer != user)
|
|
if (abs(source.angle - dir2angle(user.dir)) < 15)
|
|
source.set_angle((source.angle + 180) % 360 + rand(-3, 3))
|
|
else
|
|
source.set_angle(dir2angle(user.dir) + rand(-3, 3))
|
|
user.visible_message(span_warning("[user] expertly parries [source] with [user.p_their()] bare hand!"), span_warning("You parry [source] with your hand!"))
|
|
else
|
|
user.visible_message(span_warning("[user] boosts [source] with [user.p_their()] bare hand!"), span_warning("You boost [source] with your hand!"))
|
|
source.firer = user
|
|
source.speed *= (source.firer == user) ? boost_speed_mult : parry_speed_mult
|
|
source.damage *= (source.firer == user) ? boost_damage_mult : parry_damage_mult
|
|
source.add_atom_colour(COLOR_RED_LIGHT, TEMPORARY_COLOUR_PRIORITY)
|
|
if (!isnull(parry_callback))
|
|
parry_callback.Invoke(user)
|
|
|
|
user.playsound_local(source.loc, 'sound/effects/parry.ogg', 50, TRUE)
|
|
user.overlay_fullscreen("projectile_parry", /atom/movable/screen/fullscreen/crit/projectile_parry, 2)
|
|
addtimer(CALLBACK(user, TYPE_PROC_REF(/mob, clear_fullscreen), "projectile_parry"), 0.25 SECONDS)
|
|
return PROJECTILE_INTERRUPT_HIT_PHASE
|