Files
Bubberstation/code/game/objects/items/grenades/plastic.dm
T
LemonInTheDark 830d2e50b4 Fixes some stupid airlock sleeps (#75961)
## About The Pull Request

[A common problem with explosions is an overabundance of
sleeping](https://github.com/tgstation/tgstation/commit/6499077a09469ff401c224c0510bc184c663b118)

In an attempt to solve this issue, let's not continue to sleep and do
work in door closing if the door is already deleted

(This is caused by firelocks activating due to other adjacent objects
deleting, triggering an atmos update, and closing the firelocks before
they get bombed. I don't have a elegant way of resolving that core
problem, so let's just minimize the impact)

[Nukes a stupid sleep loop in airlock
code](https://github.com/tgstation/tgstation/commit/5b16360520526d6f5aa3b511049456b74f33f430)

When an airlock was depowered, it would enter a sleep loop, decrementing
its delay by 1 second every well, one second, so long as it had the
right wires flipped
This is very stupid

Instead, let's use signals off wire changes and a combo of timer and
remaining time var to do this with JUST a timer

Most of the changes here are just swapping over wires to a setter to
make signal registration work\

## Why It's Good For The Game

Less sleeping around explosions means less dropped ticks after a bomb
goes off. Good just in general
Also this excises dumb boomer code and adds some hooks for other devs to
use (we should use wires more man)
2023-06-19 02:18:48 +00:00

166 lines
6.2 KiB
Plaintext

/obj/item/grenade/c4
name = "C-4 charge"
desc = "Used to put holes in specific areas without too much extra hole. A saboteur's favorite."
icon_state = "plastic-explosive0"
inhand_icon_state = "plastic-explosive"
worn_icon_state = "c4"
lefthand_file = 'icons/mob/inhands/weapons/bombs_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/bombs_righthand.dmi'
item_flags = NOBLUDGEON
flags_1 = NONE
det_time = 10
display_timer = FALSE
w_class = WEIGHT_CLASS_SMALL
gender = PLURAL
var/atom/target = null
var/mutable_appearance/plastic_overlay
var/directional = FALSE
var/aim_dir = NORTH
var/boom_sizes = list(0, 0, 3)
var/full_damage_on_mobs = FALSE
/// Minimum timer for c4 charges
var/minimum_timer = 10
/// Maximum timer for c4 charges
var/maximum_timer = 60000
/obj/item/grenade/c4/Initialize(mapload)
. = ..()
AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES)
plastic_overlay = mutable_appearance(icon, "[inhand_icon_state]2", HIGH_OBJ_LAYER)
set_wires(new /datum/wires/explosive/c4(src))
/obj/item/grenade/c4/Destroy()
qdel(wires)
set_wires(null)
target = null
return ..()
/obj/item/grenade/c4/screwdriver_act(mob/living/user, obj/item/tool)
to_chat(user, span_notice("The wire panel can be accessed without a screwdriver."))
return TRUE
/obj/item/grenade/c4/attackby(obj/item/item, mob/user, params)
if(is_wire_tool(item))
wires.interact(user)
else
return ..()
/obj/item/grenade/c4/detonate(mob/living/lanced_by)
if(QDELETED(src))
return FALSE
if(dud_flags)
active = FALSE
update_appearance()
return FALSE
. = ..()
var/turf/location
if(target)
if(!QDELETED(target))
location = get_turf(target)
target.cut_overlay(plastic_overlay, TRUE)
if(!ismob(target) || full_damage_on_mobs)
EX_ACT(target, EXPLODE_HEAVY, target)
else
location = get_turf(src)
if(location)
if(directional && target?.density)
var/turf/turf = get_step(location, aim_dir)
explosion(get_step(turf, aim_dir), devastation_range = boom_sizes[1], heavy_impact_range = boom_sizes[2], light_impact_range = boom_sizes[3], explosion_cause = src)
else
explosion(location, devastation_range = boom_sizes[1], heavy_impact_range = boom_sizes[2], light_impact_range = boom_sizes[3], explosion_cause = src)
qdel(src)
//assembly stuff
/obj/item/grenade/c4/receive_signal()
detonate()
/obj/item/grenade/c4/attack_self(mob/user)
var/newtime = tgui_input_number(user, "Please set the timer", "C4 Timer", minimum_timer, maximum_timer, minimum_timer)
if(!newtime || QDELETED(user) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH))
return
det_time = newtime
to_chat(user, "Timer set for [det_time] seconds.")
/obj/item/grenade/c4/afterattack(atom/movable/bomb_target, mob/user, flag)
. = ..()
aim_dir = get_dir(user, bomb_target)
if(isdead(bomb_target))
return
if(!flag)
return
. |= AFTERATTACK_PROCESSED_ITEM
if(bomb_target != user && HAS_TRAIT(user, TRAIT_PACIFISM) && isliving(bomb_target))
to_chat(user, span_warning("You don't want to harm other living beings!"))
return .
to_chat(user, span_notice("You start planting [src]. The timer is set to [det_time]..."))
if(do_after(user, 30, target = bomb_target))
if(!user.temporarilyRemoveItemFromInventory(src))
return .
target = bomb_target
active = TRUE
message_admins("[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_VERBOSEJMP(target)] with [det_time] second fuse")
user.log_message("planted [name] on [target.name] with a [det_time] second fuse.", LOG_ATTACK)
notify_ghosts("[user] has planted \a [src] on [target] with a [det_time] second fuse!", source = bomb_target, action = (isturf(target) ? NOTIFY_JUMP : NOTIFY_ORBIT), flashwindow = FALSE, header = "Explosive Planted")
moveToNullspace() //Yep
if(isitem(bomb_target)) //your crappy throwing star can't fly so good with a giant brick of c4 on it.
var/obj/item/thrown_weapon = bomb_target
thrown_weapon.throw_speed = max(1, (thrown_weapon.throw_speed - 3))
thrown_weapon.throw_range = max(1, (thrown_weapon.throw_range - 3))
if(thrown_weapon.embedding)
thrown_weapon.embedding["embed_chance"] = 0
thrown_weapon.updateEmbedding()
else if(isliving(bomb_target))
plastic_overlay.layer = FLOAT_LAYER
target.add_overlay(plastic_overlay)
to_chat(user, span_notice("You plant the bomb. Timer counting down from [det_time]."))
addtimer(CALLBACK(src, PROC_REF(detonate)), det_time*10)
return .
/obj/item/grenade/c4/proc/shout_syndicate_crap(mob/player)
if(!player)
CRASH("[src] proc shout_syndicate_crap called without a mob to shout crap from!")
var/final_message = "FOR NO RAISIN!!"
if(player.mind)
// Give our list of antag datums a shuffle and pick the first one with a suicide_cry to use as our shout.
var/list/shuffled_antag_datums = shuffle(player.mind.antag_datums)
for(var/datum/antagonist/found_antag as anything in shuffled_antag_datums)
if(found_antag.suicide_cry)
final_message = found_antag.suicide_cry
break
player.say(final_message, forced = "C4 suicide")
/obj/item/grenade/c4/suicide_act(mob/living/user)
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [src] at [ADMIN_VERBOSEJMP(user)]")
user.log_message("suicided with [src].", LOG_ATTACK)
log_game("[key_name(user)] suicided with [src] at [AREACOORD(user)]")
user.visible_message(span_suicide("[user] activates [src] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!"))
shout_syndicate_crap(user)
explosion(user, heavy_impact_range = 2, explosion_cause = src) //Cheap explosion imitation because putting detonate() here causes runtimes
user.gib(1, 1)
qdel(src)
// X4 is an upgraded directional variant of c4 which is relatively safe to be standing next to. And much less safe to be standing on the other side of.
// C4 is intended to be used for infiltration, and destroying tech. X4 is intended to be used for heavy breaching and tight spaces.
// Intended to replace C4 for nukeops, and to be a randomdrop in surplus/random traitor purchases.
/obj/item/grenade/c4/x4
name = "X-4 charge"
desc = "A shaped high-explosive breaching charge. Designed to ensure user safety and wall nonsafety."
icon_state = "plasticx40"
inhand_icon_state = "plasticx4"
worn_icon_state = "x4"
directional = TRUE
boom_sizes = list(0, 2, 5)