mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
[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:
co-authored by
SapphicOverload
parent
29ff3dbb67
commit
a12acadd09
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user