[MIRROR] Kills off /obj/item/onetankbomb, assembly bombs now handled by the tank itself (#26343)

* Kills off /obj/item/onetankbomb, assembly bombs now handled by the tank itself (#81218)

* Kills off /obj/item/onetankbomb, assembly bombs now handled by the tank itself

---------

Co-authored-by: SapphicOverload <93578146+SapphicOverload@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-02-03 10:42:30 -05:00
committed by GitHub
co-authored by SapphicOverload
parent 29ff3dbb67
commit a12acadd09
4 changed files with 140 additions and 174 deletions
+140 -17
View File
@@ -1,5 +1,9 @@
/// How much time (in seconds) is assumed to pass while assuming air. Used to scale overpressure/overtemp damage when assuming air.
#define ASSUME_AIR_DT_FACTOR 1
/// Multiplies the pressure of assembly bomb explosions before it's put through THE LOGARITHM
#define ASSEMBLY_BOMB_COEFFICIENT 0.5
/// Base of the logarithmic function used to calculate assembly bomb explosion size
#define ASSEMBLY_BOMB_BASE 2.7
/**
* # Gas Tank
@@ -48,6 +52,10 @@
var/list/reaction_info
/// Mob that is currently breathing from the tank.
var/mob/living/carbon/breathing_mob = null
/// Attached assembly, can either detonate the tank or release its contents when receiving a signal
var/obj/item/assembly_holder/tank_assembly
/// Whether or not it will try to explode when it receives a signal
var/bomb_status = FALSE
/// Closes the tank if dropped while open.
/datum/armor/item_tank
@@ -123,8 +131,16 @@
/obj/item/tank/Destroy()
STOP_PROCESSING(SSobj, src)
air_contents = null
QDEL_NULL(tank_assembly)
return ..()
/obj/item/tank/update_overlays()
. = ..()
if(tank_assembly)
. += tank_assembly.icon_state
. += tank_assembly.overlays
. += "bomb_assembly"
/obj/item/tank/examine(mob/user)
var/obj/icon = src
. = ..()
@@ -155,6 +171,9 @@
. += span_notice("It feels [descriptive].")
if(tank_assembly)
. += span_warning("There is some kind of device [EXAMINE_HINT("rigged")] to the tank!")
/obj/item/tank/deconstruct(disassembled = TRUE)
var/atom/location = loc
if(location)
@@ -176,8 +195,30 @@
/obj/item/tank/attackby(obj/item/attacking_item, mob/user, params)
add_fingerprint(user)
if(istype(attacking_item, /obj/item/assembly_holder))
if(tank_assembly)
balloon_alert(user, "something already attached!")
return ITEM_INTERACT_BLOCKING
bomb_assemble(attacking_item, user)
return TRUE
return ITEM_INTERACT_SUCCESS
return ..()
/obj/item/tank/wrench_act(mob/living/user, obj/item/tool)
if(tank_assembly)
tool.play_tool_sound(src)
bomb_disassemble(user)
return ITEM_INTERACT_SUCCESS
return ..()
/obj/item/tank/welder_act(mob/living/user, obj/item/tool)
if(bomb_status)
balloon_alert(user, "already welded!")
return ITEM_INTERACT_BLOCKING
if(tool.use_tool(src, user, 0, volume=40))
bomb_status = TRUE
balloon_alert(user, "bomb armed")
log_bomber(user, "welded a single tank bomb,", src, "| Temp: [air_contents.temperature] Pressure: [air_contents.return_pressure()]")
add_fingerprint(user)
return ITEM_INTERACT_SUCCESS
return ..()
/obj/item/tank/ui_state(mob/user)
@@ -361,16 +402,87 @@
/obj/item/tank/proc/explosion_information()
return list(TANK_RESULTS_REACTION = reaction_info, TANK_RESULTS_MISC = explosion_info)
/obj/item/tank/proc/ignite() //This happens when a bomb is told to explode
if(igniting)
stack_trace("Attempted to ignite a /obj/item/tank multiple times")
return //no double ignite
igniting = TRUE
// This is done in return_air call, but even then it actually makes zero sense, this tank is going to be deleted
// before ever getting a chance to process.
//START_PROCESSING(SSobj, src)
var/datum/gas_mixture/our_mix = return_air()
/obj/item/tank/on_found(mob/finder) //for mousetraps
. = ..()
if(tank_assembly)
tank_assembly.on_found(finder)
/obj/item/tank/attack_hand() //also for mousetraps
if(..())
return
if(tank_assembly)
tank_assembly.attack_hand()
/obj/item/tank/Move()
. = ..()
if(tank_assembly)
tank_assembly.setDir(dir)
/obj/item/tank/dropped()
. = ..()
if(tank_assembly)
tank_assembly.dropped()
/obj/item/tank/IsSpecialAssembly()
return TRUE
/obj/item/tank/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
audible_message(span_warning("[icon2html(src, hearers(src))] *beep* *beep* *beep*"))
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
addtimer(CALLBACK(src, PROC_REF(ignite)), 1 SECONDS)
/// Attaches an assembly holder to the tank to create a bomb.
/obj/item/tank/proc/bomb_assemble(obj/item/assembly_holder/assembly, mob/living/user)
//Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
var/igniter_count = 0
for(var/obj/item/assembly/igniter/attached_assembly in assembly.assemblies)
igniter_count++
if(LAZYLEN(assembly.assemblies) == igniter_count)
return
if((src in user.get_equipped_items(include_pockets = TRUE, include_accessories = TRUE)) && !user.canUnEquip(src))
balloon_alert(user, "it's stuck!")
return
if(!user.canUnEquip(assembly))
balloon_alert(user, "it's stuck!")
return
if(!user.transferItemToLoc(assembly, src))
balloon_alert(user, "it's stuck!")
return
tank_assembly = assembly //Tell the tank about its assembly part
assembly.master = src //Tell the assembly about its new owner
assembly.on_attach()
balloon_alert(user, "bomb assembled")
update_appearance(UPDATE_OVERLAYS)
/// Detaches an assembly holder from the tank, disarming the bomb
/obj/item/tank/proc/bomb_disassemble(mob/user)
bomb_status = FALSE
balloon_alert(user, "bomb disarmed")
if(!tank_assembly)
CRASH("bomb_disassemble() called on a tank with no assembly!")
user.put_in_hands(tank_assembly)
tank_assembly.master = null
tank_assembly = null
update_appearance(UPDATE_OVERLAYS)
/// Ignites the contents of the tank. Called when receiving a signal if the tank is welded and has an igniter attached.
/obj/item/tank/proc/ignite()
if(!bomb_status) // if it isn't welded, release the gases instead
release()
return
// check to make sure it's not already exploding before exploding it
if(igniting)
CRASH("ignite() called multiple times on [type]")
igniting = TRUE
var/datum/gas_mixture/our_mix = return_air()
our_mix.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
var/fuel_moles = our_mix.gases[/datum/gas/plasma][MOLES] + our_mix.gases[/datum/gas/oxygen][MOLES]/6
our_mix.garbage_collect()
@@ -379,6 +491,14 @@
var/turf/ground_zero = get_turf(loc)
/// Used to determine what the temperature of the hotspot when it isn't able to explode
var/igniter_temperature = 0
for(var/obj/item/assembly/igniter/firestarter in tank_assembly.assemblies)
igniter_temperature = max(igniter_temperature, firestarter.heat)
if(!igniter_temperature)
CRASH("[type] called ignite() without any igniters attached")
if(bomb_mixture.temperature > (T0C + 400))
strength = (fuel_moles/15)
@@ -392,7 +512,7 @@
explosion(ground_zero, devastation_range = -1, light_impact_range = 1, flash_range = 2, explosion_cause = src)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
ground_zero.hotspot_expose(igniter_temperature, 125)
else if(bomb_mixture.temperature > (T0C + 250))
strength = (fuel_moles/20)
@@ -403,7 +523,7 @@
explosion(ground_zero, devastation_range = -1, light_impact_range = 1, flash_range = 2, explosion_cause = src)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
ground_zero.hotspot_expose(igniter_temperature, 125)
else if(bomb_mixture.temperature > (T0C + 100))
strength = (fuel_moles/25)
@@ -412,21 +532,24 @@
explosion(ground_zero, devastation_range = -1, light_impact_range = round(strength,1), flash_range = round(strength*3,1), explosion_cause = src)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
ground_zero.hotspot_expose(igniter_temperature, 125)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
ground_zero.hotspot_expose(igniter_temperature, 125)
if(master)
qdel(master)
qdel(src)
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
/// Releases air stored in the tank. Called when signaled without being welded, or when ignited without enough pressure to explode.
/obj/item/tank/proc/release()
var/datum/gas_mixture/our_mix = return_air()
var/datum/gas_mixture/removed = remove_air(our_mix.total_moles())
var/turf/T = get_turf(src)
if(!T)
return
log_atmos("[type] released its contents of ", air_contents)
T.assume_air(removed)
#undef ASSEMBLY_BOMB_BASE
#undef ASSEMBLY_BOMB_COEFFICIENT
#undef ASSUME_AIR_DT_FACTOR
-155
View File
@@ -1,155 +0,0 @@
/obj/item/onetankbomb
name = "bomb"
icon = 'icons/obj/canisters.dmi'
inhand_icon_state = "assembly"
lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
throwforce = 5
w_class = WEIGHT_CLASS_NORMAL
throw_speed = 2
throw_range = 4
obj_flags = CONDUCTS_ELECTRICITY
var/status = FALSE //0 - not readied //1 - bomb finished with welder
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
/obj/item/onetankbomb/Destroy()
bombassembly = null
bombtank = null
return ..()
/obj/item/onetankbomb/IsSpecialAssembly()
return TRUE
/obj/item/onetankbomb/examine(mob/user)
return bombtank.examine(user)
/obj/item/onetankbomb/update_icon(updates)
icon = bombtank?.icon || initial(icon)
return ..()
/obj/item/onetankbomb/update_icon_state()
icon_state = bombtank?.icon_state || initial(icon_state)
return ..()
/obj/item/onetankbomb/update_overlays()
. = ..()
if(bombassembly)
. += bombassembly.icon_state
. += bombassembly.overlays
. += "bomb_assembly"
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
..()
to_chat(user, span_notice("You disassemble [src]!"))
if(bombassembly)
bombassembly.forceMove(drop_location())
bombassembly.master = null
bombassembly = null
if(bombtank)
bombtank.forceMove(drop_location())
bombtank.master = null
bombtank = null
qdel(src)
return TRUE
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
..()
. = FALSE
if(status)
to_chat(user, span_warning("[bombtank] already has a pressure hole!"))
return
if(!I.tool_start_check(user, amount=1))
return
if(I.use_tool(src, user, 0, volume=40))
status = TRUE
var/datum/gas_mixture/bomb_mix = bombtank.return_air()
log_bomber(user, "welded a single tank bomb,", src, "| Temp: [bomb_mix.temperature]")
to_chat(user, span_notice("A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited."))
add_fingerprint(user)
return TRUE
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, TRUE)
add_fingerprint(user)
return
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
audible_message(span_warning("[icon2html(src, hearers(src))] *beep* *beep* *beep*"))
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
sleep(1 SECONDS)
if(QDELETED(src))
return
if(status)
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
else
bombtank.release()
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
if(bombassembly)
bombassembly.on_found(finder)
/obj/item/onetankbomb/attack_hand(mob/user, list/modifiers) //also for mousetraps
. = ..()
if(.)
return
if(bombassembly)
bombassembly.attack_hand()
/obj/item/onetankbomb/Move()
. = ..()
if(bombassembly)
bombassembly.setDir(dir)
bombassembly.Move()
/obj/item/onetankbomb/dropped()
. = ..()
if(bombassembly)
bombassembly.dropped()
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
//Bomb assembly proc. This turns assembly+tank into a bomb
/obj/item/tank/proc/bomb_assemble(obj/item/assembly_holder/assembly, mob/living/user)
//Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
var/igniter_count = 0
for(var/obj/item/assembly/attached_assembly as anything in assembly.assemblies)
if(isigniter(attached_assembly))
igniter_count += 1
if(LAZYLEN(assembly.assemblies) == igniter_count)
return
if((src in user.get_equipped_items(include_pockets = TRUE, include_accessories = TRUE)) && !user.canUnEquip(src))
to_chat(user, span_warning("[src] is stuck to you!"))
return
if(!user.canUnEquip(assembly))
to_chat(user, span_warning("[assembly] is stuck to your hand!"))
return
var/obj/item/onetankbomb/bomb = new
user.transferItemToLoc(src, bomb)
user.transferItemToLoc(assembly, bomb)
bomb.bombassembly = assembly //Tell the bomb about its assembly part
assembly.master = bomb //Tell the assembly about its new owner
assembly.on_attach()
bomb.bombtank = src //Same for tank
master = bomb
forceMove(bomb)
bomb.update_appearance()
user.put_in_hands(bomb) //Equips the bomb if possible, or puts it on the floor.
to_chat(user, span_notice("You attach [assembly] to [src]."))
return
/obj/item/onetankbomb/return_analyzable_air()
if(bombtank)
return bombtank.return_analyzable_air()
else
return null
-1
View File
@@ -98,7 +98,6 @@
/obj/item/aicard,
/obj/item/storage/backpack/holding,
/obj/item/slime_extract,
/obj/item/onetankbomb,
/obj/item/transfer_valve))
/obj/machinery/rnd/experimentor/RefreshParts()
-1
View File
@@ -3305,7 +3305,6 @@
#include "code\modules\art\paintings.dm"
#include "code\modules\art\statues.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\bomb.dm"
#include "code\modules\assembly\doorcontrol.dm"
#include "code\modules\assembly\flash.dm"
#include "code\modules\assembly\health.dm"