mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 22:19:30 +01:00
## About The Pull Request 50 files. Sorry about that, I was faster today. Just merge without looking, it'll be fine. This is the end of `/machinery/` & `/stack/` `attackby()`s(that aren't actually meant for being attacked) when these are all merged. Like, 200 left? I think? Also, this one will make light replacer reloading slightly more difficult until whichever one converted the light replacer is merged. If, for some ungodly reason, this one gets merged first. Changes beyond conversion: if a `/porta_turret_construct` somehow became anchored out of sync with its construction steps, it's no longer softlocked you can no longer place an infinite amount of blackboxes into the blackbox recorder a TTV will no longer keep its ghost on your back when you cut its wires while wearing it RCLs will properly update their appearance when initially given their first coil The creator of `robot_suit/attackby()` has been cursed to spend a thousand years in the lake of fire ## Why It's Good For The Game Now that all of these are remade, you can find bugs in them and then get GBP for fixing them(not that my code would ever have bugs). ## Changelog 🆑 fix: It's no longer possible to softlock building a turret(if it ever was) fix: you can no longer stuff the blackbox recorder full with as many blackboxes as you've somehow collected fix: TTVs will no longer remain on your back as a ghost when you cut their wire straps fix: RCLs will now properly update their appearance when given their first coil of cleaners code: 50 files have been converted from attackby() to item_interaction() /🆑
290 lines
9.9 KiB
Plaintext
290 lines
9.9 KiB
Plaintext
/obj/item/grenade/iedcasing
|
|
name = "improvised explosive"
|
|
desc = "An improvised explosive device."
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
icon = 'icons/obj/weapons/grenade.dmi'
|
|
base_icon_state = "pipebomb"
|
|
icon_state = "slicedapart"
|
|
inhand_icon_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
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
slot_flags = ITEM_SLOT_BELT
|
|
active = FALSE
|
|
shrapnel_type = /obj/projectile/bullet/shrapnel/ied
|
|
det_time = 225 SECONDS //this is handled by assemblies now
|
|
display_timer = FALSE
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.65, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 2)
|
|
/// 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/food/meat/slab = 0,
|
|
/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(mob/user, silent)
|
|
. = ..()
|
|
if(activator)
|
|
activator.dropped(user, silent)
|
|
|
|
/obj/item/grenade/iedcasing/proc/process_activation(obj/item/assembly)
|
|
detonate()
|
|
|
|
/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/iedcasing/change_det_time()
|
|
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()
|
|
|
|
/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
|
|
log_grenade(user)
|
|
add_fingerprint(user)
|
|
activator.activate()
|
|
update_icon(UPDATE_ICON_STATE)
|
|
user.balloon_alert_to_viewers("arming!")
|
|
COOLDOWN_START(src, spam_cd, 1 SECONDS)
|
|
|
|
/obj/item/grenade/iedcasing/detonate(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/food/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(loc, devastation_range = -1, heavy_impact_range = heavy, light_impact_range = light, flame_range = flame, explosion_cause = src)
|
|
|
|
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 = 'icons/obj/weapons/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
|
|
var/static/list/allowed = typecacheof(list(
|
|
/obj/item/food/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/wiremod,
|
|
/obj/item/assembly/voice,
|
|
)
|
|
/// Static list of reagent to explosive power
|
|
var/static/list/fuel_power = list(
|
|
/datum/reagent/fuel = 0.5,
|
|
/datum/reagent/toxin/plasma = 0.75,
|
|
/datum/reagent/gunpowder = 1,
|
|
/datum/reagent/nitroglycerin = 2,
|
|
/datum/reagent/tatp = 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/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
if(!wires_are_in)
|
|
// here we can stuff in additional objects for a cooler effect
|
|
if(is_type_in_typecache(tool, allowed) && contents.len < MAX_STUFFINGS)
|
|
balloon_alert(user, "stuffed in")
|
|
var/atom/movable/to_put = tool
|
|
if(isstack(tool))
|
|
var/obj/item/stack/as_stack = tool
|
|
var/obj/item/stack/new_stack = as_stack.split_stack(1)
|
|
new_stack.merge_type = null //prevent them from merging inside for contents.len
|
|
to_put = new_stack
|
|
to_put.forceMove(src)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
//if the item has reagents lets allow it to transfer
|
|
if(tool.reagents)
|
|
return NONE
|
|
if(reagents.total_volume < 5)
|
|
balloon_alert(user, "add more fuel!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/obj/item/stack/cable_coil/coil = tool
|
|
if(!istype(coil))
|
|
return ITEM_INTERACT_BLOCKING
|
|
if (coil.get_amount() < 15)
|
|
balloon_alert(user, "need 15 length!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
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 = SEALED_CONTAINER
|
|
wires_are_in = TRUE
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
// wires are in, lets finish this up
|
|
var/obj/item/assembly/assembly = tool
|
|
if(!istype(assembly) || !(assembly.type in allowed_activators))
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(assembly.secured)
|
|
balloon_alert(user, "unsecure assembly first!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(!user.transferItemToLoc(assembly, src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
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)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
#undef MAX_STUFFINGS
|