Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
SmiLeYre committed Dec 15, 2024
2 parents edd213e + 4cfeb95 commit 6b4a19b
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 3 deletions.
324 changes: 324 additions & 0 deletions modular_bluemoon/oni3288/code/pipebomb.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,324 @@
/obj/item/projectile/bullet/shrapnel/ied
name = "flying glass shrapnel"
damage = 15
range = 6
ricochets_max = 1
ricochet_chance = 40
shrapnel_type = /obj/item/shard
ricochet_incidence_leeway = 60

/obj/item/grenade/iedcasing
name = "improvised explosive"
desc = "An improvised explosive device."
w_class = WEIGHT_CLASS_SMALL
icon = 'modular_bluemoon/oni3288/icons/weapons/pipebomb/grenade.dmi'
base_icon_state = "pipebomb"
icon_state = "slicedapart"
item_state = "flashbang"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
throw_speed = 3
throw_range = 7
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
active = FALSE
shrapnel_type = /obj/item/projectile/bullet/shrapnel/ied
det_time = 225 SECONDS //this is handled by assemblies now
display_timer = FALSE
/// Explosive power
var/power = 5
/// Our assembly that when activated causes us to explode
var/obj/item/assembly/activator
/// List of effects, the key is a path to compare to and the value is incremented by one everytime theres one that is the same type in our contents
var/list/effects = list(
/obj/item/paper = 0,
/obj/item/shard = 0,
/obj/item/stack/ore/bluespace_crystal/refined = 0,
)
/// Cooldown to prevent spam
COOLDOWN_DECLARE(spam_cd)

/obj/item/grenade/iedcasing/Initialize(mapload)
. = ..()
if(ispath(activator))
var/obj/item/assembly/new_activator = new activator(src)
new_activator.toggle_secure()
activator = null
attach_activator(new_activator)

/obj/item/grenade/iedcasing/proc/setup_effects_from_contents()
for(var/item in contents)
for(var/effect_type in effects)
if(!istype(item, effect_type))
continue
if(isstack(item))
var/obj/item/stack/as_stack = item
effects[effect_type] += as_stack.amount
else
effects[effect_type]++
break

/obj/item/grenade/iedcasing/examine(mob/user)
. = ..()
. += span_notice("Using it in-hand activates the assembly, which means timers start timing and so on.")
. += span_notice("Using it off-hand allows you to configure the assembly, if possible.")
if(contents.len > 1) // above 1, so more than just the activator
. += span_warning("It seems to have something stuffed in it.")
if(isnull(activator))
return
. += activator.examine(user)

// assembly handling

/obj/item/grenade/iedcasing/IsAssemblyHolder()
return TRUE

/obj/item/grenade/iedcasing/on_found(mob/finder)
if(activator)
activator.on_found(finder)

/obj/item/grenade/iedcasing/Move()
. = ..()
if(activator)
activator.holder_movement()

/obj/item/grenade/iedcasing/dropped()
. = ..()
if(activator)
activator.dropped()

/obj/item/grenade/iedcasing/proc/attach_activator(obj/item/assembly/new_one)
if(activator)
return
activator = new_one
activator.holder = src
activator.on_attach()
activator.toggle_secure()
update_icon(UPDATE_ICON_STATE)

/obj/item/grenade/tool_act(mob/living/user, obj/item/I, tool_behaviour)
if(tool_behaviour == TOOL_SCREWDRIVER)
return

//assembly handling end

/obj/item/grenade/iedcasing/attack_hand(mob/user, list/modifiers)
if(loc == user) //if we were picked up already, this opening whenever picked up is not ok
activator.ui_interact(user) //if any
. = ..()
if(.)
return
if(isnull(activator))
return
activator.attack_hand(act_intent = user?.a_intent)

/obj/item/grenade/iedcasing/update_icon_state()
if(isnull(activator))
icon_state = "slicedapart" //this shouldnt happen but should prevent runtimes
return ..()
var/suffix = ""
var/obj/item/assembly/timer/as_timer = activator
var/obj/item/assembly/mousetrap/as_mousetrap = activator
var/obj/item/assembly/prox_sensor/as_prox = activator
if((istype(as_timer) && as_timer.timing) || (istype(as_mousetrap) && as_mousetrap.armed)) //these shouldve just had a common "active" variable or something
suffix = "-a"
else if(istype(as_prox))
suffix = as_prox.timing ? "-arming" : (as_prox.scanning ? "-a" : "")
icon_state = "[base_icon_state]-[initial(activator.name)][suffix]" //signalers detonate instantly so theyre not here
return ..()

/obj/item/grenade/iedcasing/attack_self(mob/user)
if(isnull(activator) || !COOLDOWN_FINISHED(src, spam_cd))
balloon_alert(user, isnull(activator) ? "you shouldnt be seeing this" : "on cooldown!")
return
if(istype(activator, /obj/item/assembly/signaler))
return //no signallers, signallers send a signal and i can imagine this having bad sideeffects if some has multiple of the same frequency in their backpack and uses them inhand by accident
activator.activate()
update_icon(UPDATE_ICON_STATE)
user.balloon_alert_to_viewers("arming!")
COOLDOWN_START(src, spam_cd, 1 SECONDS)

/obj/item/grenade/iedcasing/proc/process_activation()
prime()

/obj/item/grenade/iedcasing/prime(mob/living/lanced_by) //Blowing that can up
if(effects[/obj/item/shard]) //this has to be before so it initializes us a pellet cloud or something
shrapnel_radius = effects[/obj/item/shard]
. = ..()
if(!.)
return

update_mob()
for(var/i = 1 to effects[/obj/item/reagent_containers/food/snacks/meat/slab])
new /obj/effect/gibspawner/generic(loc)
if(effects[/obj/item/paper])
for(var/turf/open/floor in view(effects[/obj/item/paper], loc)) //this couldve been light impact range but fake pipebombs exploding into confetti is funny
new /obj/effect/decal/cleanable/confetti(floor)
var/heavy = floor(power * 0.2)
var/light = round(power * 0.7, 1)
var/flame = round(power + rand(-1, 1), 1)
explosion(
epicenter = loc,
devastation_range = -1,
heavy_impact_range = heavy,
light_impact_range = light,
flame_range = flame)

if(effects[/obj/item/stack/ore/bluespace_crystal/refined])
for(var/mob/living/victim in view(light, loc))
do_teleport(victim, get_turf(victim), min(12, effects[/obj/item/stack/ore/bluespace_crystal/refined] * 3), asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)

qdel(src)

/obj/item/grenade/iedcasing/Destroy()
. = ..()
activator = null

/obj/item/grenade/iedcasing/spawned
power = 2.5 //20u welding fuel
activator = /obj/item/assembly/timer

#define MAX_STUFFINGS 3

/obj/item/sliced_pipe
name = "halved pipe"
desc = "Two half-size pipes made from one."
w_class = WEIGHT_CLASS_SMALL
icon = 'modular_bluemoon/oni3288/icons/weapons/pipebomb/grenade.dmi'
icon_state = "slicedapart"
/// Are wires inserted? If so, we are on the final step
var/wires_are_in = FALSE
/// Typecache of items we are allowed to stuff into the pipebomb for effects, only add items with effects
allowed = list(
/obj/item/reagent_containers/food/snacks/meat/slab,
/obj/item/paper,
/obj/item/shard,
/obj/item/stack/ore/bluespace_crystal/refined,
)
//this probably shouldve been a blacklist instead but god do i not wanna update this anytime a new assembly is added
/// A static list of types of assemblies that are allowed to be used to finish the bomb
var/static/list/allowed_activators = list(
/obj/item/assembly/signaler,
/obj/item/assembly/prox_sensor,
/obj/item/assembly/mousetrap,
/obj/item/assembly/mousetrap/armed,
/obj/item/assembly/timer,
/obj/item/assembly/voice,
)
/// Static list of reagent to explosive power
var/static/list/fuel_power = list(
/datum/reagent/fuel = 0.5,
/datum/reagent/thermite = 1,
/datum/reagent/nitroglycerin = 2,
/datum/reagent/blackpowder = 2.5,
)
/// Explosion power to be transferred to the new pipebomb
var/power = 5

/obj/item/sliced_pipe/Initialize(mapload)
. = ..()
create_reagents(20, OPENCONTAINER)

/obj/item/sliced_pipe/examine(mob/user)
. = ..()
if(!wires_are_in)
. += span_notice("You could stuff something in, or fill it with fuel or some other volatile chemical..")
. += span_notice("Afterwards, add some cable.")
else
. += span_notice("The wires are just dangling from it, you need some sort of <i> activating assembly</i>.")

/obj/item/sliced_pipe/attackby(obj/item/item, mob/user, params)
if(!wires_are_in)
// here we can stuff in additional objects for a cooler effect
if(is_type_in_typecache(item, allowed) && contents.len < MAX_STUFFINGS)
balloon_alert(user, "stuffed in")
var/atom/movable/to_put = item
if(isstack(item))
var/obj/item/stack/as_stack = item
to_put = as_stack.split_stack(user = null, amount = 1)
as_stack.merge_type = null //prevent them from merging inside for contents.len
to_put.forceMove(src)
return

//if the item has reagents lets allow it to transfer
if(item.reagents)
return ..()
if(reagents.total_volume < 5)
balloon_alert(user, "add more fuel!")
return

var/obj/item/stack/cable_coil/coil = item
if(!istype(coil))
return
if (coil.get_amount() < 15)
balloon_alert(user, "need 15 length!")
return
coil.use(15)

var/cur_power = 0
for(var/datum/reagent/reagent as anything in reagents.reagent_list)
if(!(reagent.type in fuel_power))
continue
cur_power += fuel_power[reagent.type] * reagent.volume / reagents.maximum_volume

power *= cur_power
power -= contents.len / 2

balloon_alert(user, "wires attached")
icon_state = "[icon_state]-cable"
reagents.flags = NO_REACT
wires_are_in = TRUE
else // wires are in, lets finish this up
var/obj/item/assembly/assembly = item
if(!istype(assembly) || !(assembly.type in allowed_activators))
return
if(assembly.secured)
balloon_alert(user, "unsecure assembly first!")
return
if(!user.transferItemToLoc(assembly, src))
return
user.balloon_alert(user, "attached")

var/obj/item/grenade/iedcasing/pipebomb = new(drop_location())
for(var/atom/movable/item_inside as anything in contents)
item_inside.forceMove(pipebomb)

pipebomb.power = power
pipebomb.attach_activator(assembly)
pipebomb.setup_effects_from_contents()
var/was_in_hands = (loc == user)
qdel(src)
if(was_in_hands)
user.put_in_hands(pipebomb)

/datum/crafting_recipe/improv_explosive
name = "Improvised Explosive"
result = /obj/item/grenade/iedcasing/spawned
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER)
reqs = list(
/datum/reagent/fuel = 20,
/obj/item/stack/cable_coil = 15,
/obj/item/assembly/timer = 1,
/obj/item/pipe/quaternary = 1,
)
time = 6 SECONDS
category = CAT_OTHER

/obj/item/pipe/welder_act(mob/living/user, obj/item/welder)
. = ..()
if(istype(pipe_type, /obj/machinery/atmospherics/components))
return TRUE
if(!welder.tool_start_check(user, amount=2))
return TRUE
add_fingerprint(user)

if(welder.use_tool(src, user, 2 SECONDS, volume=2))
new /obj/item/sliced_pipe(drop_location())
user.visible_message( \
"[user] welds \the [src] in two.", \
span_notice("You weld \the [src] in two."), \
span_hear("You hear welding."))

qdel(src)

#undef MAX_STUFFINGS
Binary file not shown.
7 changes: 4 additions & 3 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1392,7 +1392,6 @@
#include "code\game\objects\items\devices\laserpointer.dm"
#include "code\game\objects\items\devices\lightreplacer.dm"
#include "code\game\objects\items\devices\megaphone.dm"
#include "modular_bluemoon\code\game\objects\items\devices\multitool.dm"
#include "code\game\objects\items\devices\multitool.dm"
#include "code\game\objects\items\devices\paicard.dm"
#include "code\game\objects\items\devices\pipe_painter.dm"
Expand Down Expand Up @@ -4264,6 +4263,7 @@
#include "modular_bluemoon\code\game\objects\items\fleshlight.dm"
#include "modular_bluemoon\code\game\objects\items\pinpointer.dm"
#include "modular_bluemoon\code\game\objects\items\plushes.dm"
#include "modular_bluemoon\code\game\objects\items\devices\multitool.dm"
#include "modular_bluemoon\code\game\objects\items\devices\scanners.dm"
#include "modular_bluemoon\code\game\objects\items\lewd_items\genital_equipment\chastity\flat_chastity_cage.dm"
#include "modular_bluemoon\code\modules\admin\verbs\one_click_antag.dm"
Expand Down Expand Up @@ -4538,6 +4538,7 @@
#include "modular_bluemoon\MRSKO\code\uplink\uplink_items.dm"
#include "modular_bluemoon\nopeingeener\code\donator.dm"
#include "modular_bluemoon\oni3288\code\catcrin_stuff.dm"
#include "modular_bluemoon\oni3288\code\pipebomb.dm"
#include "modular_bluemoon\Painiscupcake\code\game\objects\items\heroin.dm"
#include "modular_bluemoon\phenyamomota\code\modules\cargo\packs\engineering.dm"
#include "modular_bluemoon\phenyamomota\code\modules\clothing\labcoat.dm"
Expand Down Expand Up @@ -4625,9 +4626,9 @@
#include "modular_bluemoon\service_staff\service_staff.dm"
#include "modular_bluemoon\shower_trait\shower_trait.dm"
#include "modular_bluemoon\shriek_trait\shriek_trait.dm"
#include "modular_bluemoon\size_tool\size_tool.dm"
#include "modular_bluemoon\silverfoxpaws_staff\code\demolition_hammer.dm"
#include "modular_bluemoon\silverfoxpaws_staff\code\demolition_hammer_cabinet.dm"
#include "modular_bluemoon\size_tool\size_tool.dm"
#include "modular_bluemoon\SmiLeY\aesthetics\airlock\code\airlock.dm"
#include "modular_bluemoon\SmiLeY\aesthetics\barsign\barsigns.dm"
#include "modular_bluemoon\SmiLeY\aesthetics\connecting_computer\code\_computer.dm"
Expand Down Expand Up @@ -5391,8 +5392,8 @@
#include "modular_splurt\code\game\objects\items\RCD.dm"
#include "modular_splurt\code\game\objects\items\RTL.dm"
#include "modular_splurt\code\game\objects\items\toys.dm"
#include "modular_splurt\code\game\objects\items\weapon_permits.dm"
#include "modular_splurt\code\game\objects\items\trash.dm"
#include "modular_splurt\code\game\objects\items\weapon_permits.dm"
#include "modular_splurt\code\game\objects\items\weaponry.dm"
#include "modular_splurt\code\game\objects\items\carvingstones\carvingstones.dm"
#include "modular_splurt\code\game\objects\items\circuitboards\computer_circuitboards.dm"
Expand Down

0 comments on commit 6b4a19b

Please sign in to comment.