mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-19 22:23:11 +00:00
* Reworks sabotage progression traitor objective (#73750) ## About The Pull Request This one is a little bit of a more abstract change than my last traitor objective rebalancing PR. The idea here is that I think that the objectives which have you sabotage a frequently used machine (lathes or the ORM, but we can maybe expand it to others following this?) are potentially pretty good but limitations in how the objective are tracked mean that people go about them in a boring way which rarely inconveniences anyone. I have reworked these objectives so that you can choose to apply a provided item to the machine over 10 seconds. The next interaction following this (clicking on it, or in the case of the ORM loading any ore into it) will cause the machine to explode, destroying itself and lightly damaging people nearby (explosion damage is... variable, but it's a light explosion so it won't instantly kill anyone). There is a 0.5 second grace period between the bomb triggering and the explosion actually happening, which players can use to perform some kind of tactical reaction or simply to feel regret. Here's a video: https://www.youtube.com/watch?v=xNIaHsA9YFE Trapped machines will intermittently beep, though at a volume which is hard to detect from more than two tiles away, and can be defused by using a screwdriver on the machine. If you choose to do this then you will get a little bonus to TC and reputation, but only if the trap is successfully sprung. This means that sabotaging a machine in an empty department is unlikely to lead to quick success. You can also still do it with screwdriver and crowbar way if you are boring but this means you will only get reputation and not any telecrystals. The two objectives to destroy a radio server or the research machine remain as they were. Also I refactored how we set which machines are targets for these objectives so it doesn't iterate over every machine in the world every time. ## Why It's Good For The Game Traitor objectives (and antagonist objectives in general) should: - Present you with a somewhat engaging task - Encourage you to interact with at least one other player (at least by "attempting to sneak past them") - Move the state of the round forward in some way, usually by creating inconvenience for at least one other person Prior to this change you could, and people often did, complete this objective by accessing a machine that you already _have_ access to, using a screwdriver and crowbar on it, and then reassembling it. This prompts interaction with nobody, and inconveniences nobody. Following this change people will be encouraged to: - Actually destroy the machine. - Probably harm somebody. - Potentially cause some collateral damage. - Make loud sounds and flashing lights to delight people of all ages. Even if you opt to set the device in a little-used department and then blow yourself up, that will prompt you to go and interact with someone in medbay and will also look pretty suspicious in a way that's much harder to track with the previous objective. Also I might reuse this component again in the future, you never know. ## Changelog 🆑 Jacquerel, sprite by J(Clearly Lying) balance: Traitor objectives which ask you to destroy lathes or the ORM provide an optional bonus if you _booby trap_ the machine using a provided tool. This causes the machine to explode the next time it is interacted with. balance: Performing the objective without rigging the machine to explode awards no TC, using it awards more TC than it did previously. /🆑 * Reworks sabotage progression traitor objective --------- Co-authored-by: Jacquerel <hnevard@gmail.com> Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
103 lines
4.0 KiB
Plaintext
103 lines
4.0 KiB
Plaintext
/**
|
|
* Attached to an atom, creates an explosion when it is interacted with
|
|
*/
|
|
/datum/component/interaction_booby_trap
|
|
/// Explosion radius of light damage
|
|
var/explosion_light_range
|
|
/// Explosion radius of heavy damage
|
|
var/explosion_heavy_range
|
|
/// Sound to play when triggered
|
|
var/triggered_sound
|
|
/// Time to wait between being triggered and blowing up
|
|
var/trigger_delay
|
|
/// Looping sound to clue people in that something is up
|
|
var/datum/looping_sound/active_sound_loop
|
|
/// Using this tool on the atom will defuse the explosive
|
|
var/defuse_tool
|
|
/// List of additional signals which should make this explode
|
|
var/list/additional_triggers
|
|
/// Callback to run when we're going to explode
|
|
var/datum/callback/on_triggered_callback
|
|
/// Callback to run when we've been defused
|
|
var/datum/callback/on_defused_callback
|
|
/// Time until we explode
|
|
var/explode_timer
|
|
|
|
/datum/component/interaction_booby_trap/Initialize(
|
|
explosion_light_range = 3,
|
|
explosion_heavy_range = 1, // So we destroy some machine components
|
|
triggered_sound = 'sound/machines/triple_beep.ogg',
|
|
trigger_delay = 0.5 SECONDS,
|
|
sound_loop_type = /datum/looping_sound/trapped_machine_beep,
|
|
defuse_tool = TOOL_SCREWDRIVER,
|
|
additional_triggers = list(),
|
|
datum/callback/on_triggered_callback = null,
|
|
datum/callback/on_defused_callback = null,
|
|
)
|
|
if(!isatom(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.explosion_light_range = explosion_light_range
|
|
src.explosion_heavy_range = explosion_heavy_range
|
|
src.triggered_sound = triggered_sound
|
|
src.trigger_delay = trigger_delay
|
|
src.defuse_tool = defuse_tool
|
|
src.additional_triggers = additional_triggers
|
|
src.on_triggered_callback = on_triggered_callback
|
|
src.on_defused_callback = on_defused_callback
|
|
if (sound_loop_type)
|
|
active_sound_loop = new sound_loop_type(parent)
|
|
active_sound_loop.start()
|
|
|
|
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_touched))
|
|
RegisterSignal(parent, COMSIG_PARENT_EXAMINE_MORE, PROC_REF(on_examine))
|
|
if (defuse_tool)
|
|
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(defuse_tool), PROC_REF(on_defused))
|
|
if (length(additional_triggers))
|
|
RegisterSignals(parent, additional_triggers, PROC_REF(trigger_explosive))
|
|
|
|
/datum/component/interaction_booby_trap/Destroy(force, silent)
|
|
UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_TOOL_ACT(defuse_tool), COMSIG_PARENT_EXAMINE_MORE) + additional_triggers)
|
|
QDEL_NULL(active_sound_loop)
|
|
QDEL_NULL(on_triggered_callback)
|
|
QDEL_NULL(on_defused_callback)
|
|
return ..()
|
|
|
|
/// Called when someone touches the parent atom with their hands, we want to blow up
|
|
/datum/component/interaction_booby_trap/proc/on_touched(atom/source)
|
|
SIGNAL_HANDLER
|
|
trigger_explosive(source)
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
/// Start a countdown until destruction
|
|
/datum/component/interaction_booby_trap/proc/trigger_explosive(atom/source)
|
|
SIGNAL_HANDLER
|
|
if (explode_timer)
|
|
return
|
|
explode_timer = addtimer(CALLBACK(src, PROC_REF(explode), source), 0.5 SECONDS)
|
|
source.balloon_alert_to_viewers("beep")
|
|
playsound(parent, triggered_sound, 50, FALSE)
|
|
return
|
|
|
|
/// Blow up the parent atom and delete ourselves
|
|
/datum/component/interaction_booby_trap/proc/explode(atom/source)
|
|
on_triggered_callback?.Invoke(source)
|
|
var/turf/origin_turf = get_turf(source)
|
|
new /obj/effect/temp_visual/explosion/fast(origin_turf)
|
|
EX_ACT(source, EXPLODE_HEAVY, source)
|
|
explosion(origin = origin_turf, light_impact_range = explosion_light_range, heavy_impact_range = explosion_heavy_range, explosion_cause = src)
|
|
qdel(src)
|
|
|
|
/// Defuse the bomb and delete ourselves
|
|
/datum/component/interaction_booby_trap/proc/on_defused(atom/source, mob/user, obj/item/tool)
|
|
SIGNAL_HANDLER
|
|
on_defused_callback?.Invoke(source, user, tool)
|
|
qdel(src)
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
/// Give people a little hint
|
|
/datum/component/interaction_booby_trap/proc/on_examine(atom/source, mob/examiner, list/examine_list)
|
|
SIGNAL_HANDLER
|
|
var/defuse_hint = (defuse_tool) ? "Perhaps [tool_behaviour_name(defuse_tool)] could help..." : ""
|
|
examine_list += span_warning("There's a light flashing red inside the maintenance panel. [defuse_hint]")
|