mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-20 11:40:07 +01:00
# MAINTAINER - USE THE BUTTON THAT SAYS "MERGE MASTER" THEN SET THE PR TO AUTO-MERGE! IT'S MUCH EASIER FOR ME TO FIX THINGS BEFORE THEY SKEW RATHER THAN AFTER THE FACT. ## About The Pull Request Hey there, This took a while to do, but here's the gist: Python file now regexes every file in `/code` except for those that have some valid reason to be tacking on more global defines. Some of those reasons are simply just that I don't have the time right now (doing what you see in this PR took a few hours) to refactor and parse what should belong and what should be thrown out. For the time being though, this PR will at least _halt_ people making the mistake of not `#undef`ing any files they `#define` "locally", or within the scope of a file. Most people forget to do this and this leads to a lot of mess later on due to how many variables can be unmanaged on the global level. I've made this mistake, you've made this mistake, it's a common thing. Let's automatically check for it so it can be fixed no-stress. Scenarios this PR corrects: * Forgetting to undef a define but undeffing others. * Not undeffing any defines in your file. * Earmarking a define as a "file local" define, but not defining it. * Having a define be a "file local" define, but having it be used elsewhere. * Having a "local" define not even be in the file that it only shows up in. * Having a completely unused define* (* I kept some of these because they seemed important... Others were junked.) ## Why It's Good For The Game If you wanna use it across multiple files, no reason to not make it a global define (maybe there's a few reasons but let's assume that this is the 95% case). Let me know if you don't like how I re-arranged some of the defines and how you'd rather see it be implemented, and I'd be happy to do that. This was mostly just "eh does it need it or not" sorta stuff. I used a pretty cool way to detect if we should use the standardized GitHub "error" output, you can see the results of that here https://github.com/san7890/bruhstation/actions/runs/4549766579/jobs/8022186846#step:7:792 ## Changelog Nothing that really concerns players. (I fixed up all this stuff using vscode, no regexes beyond what you see in the python script. sorry downstreams)
191 lines
8.3 KiB
Plaintext
191 lines
8.3 KiB
Plaintext
/// How long it takes from the gunpoint is initiated to reach stage 2
|
|
#define GUNPOINT_DELAY_STAGE_2 (2.5 SECONDS)
|
|
/// How long it takes from stage 2 starting to move up to stage 3
|
|
#define GUNPOINT_DELAY_STAGE_3 (7.5 SECONDS)
|
|
/// If the projectile doesn't have a wound_bonus of CANT_WOUND, we add (this * the stage mult) to their wound_bonus and bare_wound_bonus upon triggering
|
|
#define GUNPOINT_BASE_WOUND_BONUS 5
|
|
/// How much the damage and wound bonus mod is multiplied when you're on stage 1
|
|
#define GUNPOINT_MULT_STAGE_1 1
|
|
/// As above, for stage 2
|
|
#define GUNPOINT_MULT_STAGE_2 2
|
|
/// As above, for stage 3
|
|
#define GUNPOINT_MULT_STAGE_3 2.5
|
|
|
|
|
|
/datum/component/gunpoint
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE
|
|
|
|
var/mob/living/target
|
|
var/obj/item/gun/weapon
|
|
|
|
var/stage = 1
|
|
var/damage_mult = GUNPOINT_MULT_STAGE_1
|
|
|
|
var/point_of_no_return = FALSE
|
|
|
|
// *extremely bad russian accent* no!
|
|
/datum/component/gunpoint/Initialize(mob/living/targ, obj/item/gun/wep)
|
|
if(!isliving(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
var/mob/living/shooter = parent
|
|
target = targ
|
|
weapon = wep
|
|
RegisterSignals(targ, list(COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_ITEM_ATTACK, COMSIG_MOVABLE_MOVED, COMSIG_MOB_FIRED_GUN), PROC_REF(trigger_reaction))
|
|
|
|
RegisterSignals(weapon, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED), PROC_REF(cancel))
|
|
|
|
shooter.visible_message(span_danger("[shooter] aims [weapon] point blank at [target]!"), \
|
|
span_danger("You aim [weapon] point blank at [target]!"), ignored_mobs = target)
|
|
to_chat(target, span_userdanger("[shooter] aims [weapon] point blank at you!"))
|
|
add_memory_in_range(target, 7, /datum/memory/held_at_gunpoint, protagonist = target, deuteragonist = shooter, antagonist = weapon)
|
|
|
|
shooter.apply_status_effect(/datum/status_effect/holdup, shooter)
|
|
target.apply_status_effect(/datum/status_effect/grouped/heldup, REF(shooter))
|
|
|
|
if(istype(weapon, /obj/item/gun/ballistic/rocketlauncher) && weapon.chambered)
|
|
if(target.stat == CONSCIOUS && IS_NUKE_OP(shooter) && !IS_NUKE_OP(target) && (locate(/obj/item/disk/nuclear) in target.get_contents()) && shooter.client)
|
|
shooter.client.give_award(/datum/award/achievement/misc/rocket_holdup, shooter)
|
|
|
|
target.do_alert_animation()
|
|
target.playsound_local(target.loc, 'sound/machines/chime.ogg', 50, TRUE)
|
|
target.add_mood_event("gunpoint", /datum/mood_event/gunpoint)
|
|
|
|
addtimer(CALLBACK(src, PROC_REF(update_stage), 2), GUNPOINT_DELAY_STAGE_2)
|
|
|
|
/datum/component/gunpoint/Destroy(force, silent)
|
|
var/mob/living/shooter = parent
|
|
shooter.remove_status_effect(/datum/status_effect/holdup)
|
|
target.remove_status_effect(/datum/status_effect/grouped/heldup, REF(shooter))
|
|
target.clear_mood_event("gunpoint")
|
|
return ..()
|
|
|
|
/datum/component/gunpoint/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(check_deescalate))
|
|
RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(flinch))
|
|
RegisterSignal(parent, COMSIG_MOB_ATTACK_HAND, PROC_REF(check_shove))
|
|
RegisterSignal(parent, COMSIG_MOB_UPDATE_SIGHT, PROC_REF(check_deescalate))
|
|
RegisterSignals(parent, list(COMSIG_LIVING_START_PULL, COMSIG_MOVABLE_BUMP), PROC_REF(check_bump))
|
|
|
|
/datum/component/gunpoint/UnregisterFromParent()
|
|
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED)
|
|
UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE)
|
|
UnregisterSignal(parent, COMSIG_MOB_UPDATE_SIGHT)
|
|
UnregisterSignal(parent, COMSIG_MOB_ATTACK_HAND)
|
|
UnregisterSignal(parent, list(COMSIG_LIVING_START_PULL, COMSIG_MOVABLE_BUMP))
|
|
|
|
///If the shooter bumps the target, cancel the holdup to avoid cheesing and forcing the charged shot
|
|
/datum/component/gunpoint/proc/check_bump(atom/B, atom/A)
|
|
SIGNAL_HANDLER
|
|
|
|
if(A != target)
|
|
return
|
|
var/mob/living/shooter = parent
|
|
shooter.visible_message(span_danger("[shooter] bumps into [target] and fumbles [shooter.p_their()] aim!"), \
|
|
span_danger("You bump into [target] and fumble your aim!"), ignored_mobs = target)
|
|
to_chat(target, span_userdanger("[shooter] bumps into you and fumbles [shooter.p_their()] aim!"))
|
|
qdel(src)
|
|
|
|
///If the shooter shoves or grabs the target, cancel the holdup to avoid cheesing and forcing the charged shot
|
|
/datum/component/gunpoint/proc/check_shove(mob/living/carbon/shooter, mob/shooter_again, mob/living/T, datum/martial_art/attacker_style, modifiers)
|
|
SIGNAL_HANDLER
|
|
|
|
if(T != target || LAZYACCESS(modifiers, RIGHT_CLICK))
|
|
return
|
|
shooter.visible_message(span_danger("[shooter] bumps into [target] and fumbles [shooter.p_their()] aim!"), \
|
|
span_danger("You bump into [target] and fumble your aim!"), ignored_mobs = target)
|
|
to_chat(target, span_userdanger("[shooter] bumps into you and fumbles [shooter.p_their()] aim!"))
|
|
qdel(src)
|
|
|
|
///Update the damage multiplier for whatever stage we're entering into
|
|
/datum/component/gunpoint/proc/update_stage(new_stage)
|
|
if(check_deescalate())
|
|
return
|
|
stage = new_stage
|
|
if(stage == 2)
|
|
to_chat(parent, span_danger("You steady [weapon] on [target]."))
|
|
to_chat(target, span_userdanger("[parent] has steadied [weapon] on you!"))
|
|
damage_mult = GUNPOINT_MULT_STAGE_2
|
|
addtimer(CALLBACK(src, PROC_REF(update_stage), 3), GUNPOINT_DELAY_STAGE_3)
|
|
else if(stage == 3)
|
|
to_chat(parent, span_danger("You have fully steadied [weapon] on [target]."))
|
|
to_chat(target, span_userdanger("[parent] has fully steadied [weapon] on you!"))
|
|
damage_mult = GUNPOINT_MULT_STAGE_3
|
|
|
|
///Cancel the holdup if the shooter moves out of sight or out of range of the target
|
|
/datum/component/gunpoint/proc/check_deescalate()
|
|
SIGNAL_HANDLER
|
|
|
|
if(!can_see(parent, target, GUNPOINT_SHOOTER_STRAY_RANGE))
|
|
cancel()
|
|
return TRUE
|
|
|
|
///Bang bang, we're firing a charged shot off
|
|
/datum/component/gunpoint/proc/trigger_reaction()
|
|
SIGNAL_HANDLER
|
|
INVOKE_ASYNC(src, PROC_REF(async_trigger_reaction))
|
|
|
|
/datum/component/gunpoint/proc/async_trigger_reaction()
|
|
var/mob/living/shooter = parent
|
|
shooter.remove_status_effect(/datum/status_effect/holdup) // try doing these before the trigger gets pulled since the target (or shooter even) may not exist after pulling the trigger, dig?
|
|
target.remove_status_effect(/datum/status_effect/grouped/heldup, REF(shooter))
|
|
target.clear_mood_event("gunpoint")
|
|
|
|
if(point_of_no_return)
|
|
return
|
|
point_of_no_return = TRUE
|
|
|
|
if(weapon.chambered && weapon.chambered.loaded_projectile)
|
|
weapon.chambered.loaded_projectile.damage *= damage_mult
|
|
if(weapon.chambered.loaded_projectile.wound_bonus != CANT_WOUND)
|
|
weapon.chambered.loaded_projectile.wound_bonus += damage_mult * GUNPOINT_BASE_WOUND_BONUS
|
|
weapon.chambered.loaded_projectile.bare_wound_bonus += damage_mult * GUNPOINT_BASE_WOUND_BONUS
|
|
|
|
var/fired = weapon.fire_gun(target, shooter)
|
|
if(!fired && weapon.chambered?.loaded_projectile)
|
|
weapon.chambered.loaded_projectile.damage /= damage_mult
|
|
if(weapon.chambered.loaded_projectile.wound_bonus != CANT_WOUND)
|
|
weapon.chambered.loaded_projectile.wound_bonus -= damage_mult * GUNPOINT_BASE_WOUND_BONUS
|
|
weapon.chambered.loaded_projectile.bare_wound_bonus -= damage_mult * GUNPOINT_BASE_WOUND_BONUS
|
|
|
|
qdel(src)
|
|
|
|
///Shooter canceled their shot, either by dropping/equipping their weapon, leaving sight/range, or clicking on the alert
|
|
/datum/component/gunpoint/proc/cancel()
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/shooter = parent
|
|
shooter.visible_message(span_danger("[shooter] breaks [shooter.p_their()] aim on [target]!"), \
|
|
span_danger("You are no longer aiming [weapon] at [target]."), ignored_mobs = target)
|
|
to_chat(target, span_userdanger("[shooter] breaks [shooter.p_their()] aim on you!"))
|
|
qdel(src)
|
|
|
|
///If the shooter is hit by an attack, they have a 50% chance to flinch and fire. If it hit the arm holding the trigger, it's an 80% chance to fire instead
|
|
/datum/component/gunpoint/proc/flinch(attacker, damage, damagetype, def_zone)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/shooter = parent
|
|
if(attacker == shooter)
|
|
return // somehow this wasn't checked for months but no one tried punching themselves to initiate the shot, amazing
|
|
|
|
var/flinch_chance = 50
|
|
var/gun_hand = LEFT_HANDS
|
|
|
|
if(shooter.held_items[RIGHT_HANDS] == weapon)
|
|
gun_hand = RIGHT_HANDS
|
|
|
|
if((def_zone == BODY_ZONE_L_ARM && gun_hand == LEFT_HANDS) || (def_zone == BODY_ZONE_R_ARM && gun_hand == RIGHT_HANDS))
|
|
flinch_chance = 80
|
|
|
|
if(prob(flinch_chance))
|
|
shooter.visible_message(span_danger("[shooter] flinches!"), \
|
|
span_danger("You flinch!"))
|
|
INVOKE_ASYNC(src, PROC_REF(trigger_reaction))
|
|
|
|
#undef GUNPOINT_DELAY_STAGE_2
|
|
#undef GUNPOINT_DELAY_STAGE_3
|
|
#undef GUNPOINT_BASE_WOUND_BONUS
|
|
#undef GUNPOINT_MULT_STAGE_1
|
|
#undef GUNPOINT_MULT_STAGE_2
|
|
#undef GUNPOINT_MULT_STAGE_3
|