Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -194,6 +194,7 @@ GLOBAL_PROTECT(admin_verbs_debug)
|
||||
// /client/proc/check_missing_sprites,
|
||||
// #endif
|
||||
/datum/admins/proc/create_or_modify_area,
|
||||
/datum/admins/proc/fixcorruption,
|
||||
#ifdef REFERENCE_TRACKING
|
||||
/datum/admins/proc/view_refs,
|
||||
/datum/admins/proc/view_del_failures,
|
||||
|
||||
@@ -581,7 +581,7 @@
|
||||
if(Rad.anchored)
|
||||
if(!Rad.loaded_tank)
|
||||
var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad)
|
||||
Plasma.air_contents.set_moles(/datum/gas/plasma,70)
|
||||
Plasma.air_contents.set_moles(GAS_PLASMA,70)
|
||||
Rad.drainratio = 0
|
||||
Rad.loaded_tank = Plasma
|
||||
Plasma.forceMove(Rad)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
for(var/id in env.get_gases())
|
||||
var/moles = env.get_moles(id)
|
||||
if (moles >= 0.00001)
|
||||
lines += "[GLOB.meta_gas_names[id]]: [moles] mol"
|
||||
lines += "[GLOB.gas_data.names[id]]: [moles] mol"
|
||||
to_chat(usr, lines.Join("\n"))
|
||||
|
||||
/client/proc/air_status(turf/target)
|
||||
|
||||
@@ -4,7 +4,7 @@ GLOBAL_LIST_EMPTY(deletion_failures)
|
||||
|
||||
/world/proc/enable_reference_tracking()
|
||||
if (fexists(EXTOOLS))
|
||||
call(EXTOOLS, "ref_tracking_initialize")()
|
||||
//call(EXTOOLS, "ref_tracking_initialize")()
|
||||
|
||||
/proc/get_back_references(datum/D)
|
||||
CRASH("/proc/get_back_references not hooked by extools, reference tracking will not function!")
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
result++
|
||||
. -= result - 1
|
||||
|
||||
/obj/structure/blob/BlockSuperconductivity()
|
||||
/obj/structure/blob/BlockThermalConductivity()
|
||||
return atmosblock
|
||||
|
||||
/obj/structure/blob/CanPass(atom/movable/mover, turf/target)
|
||||
|
||||
@@ -466,7 +466,7 @@
|
||||
block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + remaining_uses
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/changeling/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
/obj/item/shield/changeling/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
. = ..()
|
||||
if(--remaining_uses < 1)
|
||||
if(ishuman(loc))
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/servant_blocker/BlockSuperconductivity()
|
||||
/obj/effect/clockwork/servant_blocker/BlockThermalConductivity()
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/servant_blocker/singularity_act()
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
parry_time_perfect = 2
|
||||
parry_efficiency_perfect = 110 //Very low leeway for counterattacks...
|
||||
parry_efficiency_considered_successful = 0.8
|
||||
parry_efficiency_to_counterattack = 1
|
||||
parry_efficiency_to_counterattack = 110
|
||||
parry_cooldown = 15 //But also very low cooldown..
|
||||
parry_failed_stagger_duration = 2 SECONDS //And relatively small penalties for failing.
|
||||
parry_failed_clickcd_duration = 1 SECONDS
|
||||
|
||||
+9
-3
@@ -181,9 +181,15 @@
|
||||
make_glow()
|
||||
glow.icon_state = "clockwork_gateway_disrupted"
|
||||
resistance_flags |= INDESTRUCTIBLE
|
||||
sleep(27)
|
||||
explosion(src, 1, 3, 8, 8)
|
||||
sound_to_playing_players('sound/effects/explosion_distant.ogg', volume = 50)
|
||||
addtimer(CALLBACK(src, .proc/go_boom), 2.7 SECONDS)
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/go_boom()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
explosion(src, 1, 3, 8, 8)
|
||||
sound_to_playing_players('sound/effects/explosion_distant.ogg', volume = 50)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/make_glow()
|
||||
|
||||
@@ -647,7 +647,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
GLOB.wall_runes -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/rune/wall/BlockSuperconductivity()
|
||||
/obj/effect/rune/wall/BlockThermalConductivity()
|
||||
return density
|
||||
|
||||
/obj/effect/rune/wall/invoke(var/list/invokers)
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
return
|
||||
|
||||
/obj/item/tank/proc/ignite() //This happens when a bomb is told to explode
|
||||
var/fuel_moles = air_contents.get_moles(/datum/gas/plasma) + air_contents.get_moles(/datum/gas/oxygen)/6
|
||||
var/fuel_moles = air_contents.get_moles(GAS_PLASMA) + air_contents.get_moles(GAS_O2)/6
|
||||
var/datum/gas_mixture/bomb_mixture = air_contents.copy()
|
||||
var/strength = 1
|
||||
|
||||
@@ -196,9 +196,8 @@
|
||||
ground_zero.air_update_turf()
|
||||
|
||||
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
|
||||
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(removed)
|
||||
T.assume_air(air_contents)
|
||||
air_update_turf()
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Breathing classes are, yes, just a list of gases, associated with numbers.
|
||||
// But they're very simple: pluoxium's status as O2 * 8 is represented here,
|
||||
// with a single line of code, no hardcoding and special-casing across the codebase.
|
||||
// Not only that, but they're very general: you could have a negative value
|
||||
// to simulate asphyxiants, e.g. if I add krypton it could go into the oxygen
|
||||
// breathing class at -7, simulating krypton narcosis.
|
||||
|
||||
/datum/breathing_class
|
||||
var/list/gases = null
|
||||
var/list/products = null
|
||||
var/danger_reagent = null
|
||||
var/low_alert_category = "not_enough_oxy"
|
||||
var/low_alert_datum = /obj/screen/alert/not_enough_oxy
|
||||
var/high_alert_category = "too_much_oxy"
|
||||
var/high_alert_datum = /obj/screen/alert/too_much_oxy
|
||||
|
||||
/datum/breathing_class/oxygen
|
||||
gases = list(
|
||||
GAS_O2 = 1,
|
||||
GAS_PLUOXIUM = 8,
|
||||
GAS_CO2 = -0.7, // CO2 isn't actually toxic, just an asphyxiant
|
||||
)
|
||||
products = list(
|
||||
GAS_CO2 = 1,
|
||||
)
|
||||
|
||||
/datum/breathing_class/plasma
|
||||
gases = list(
|
||||
GAS_PLASMA = 1
|
||||
)
|
||||
products = list(
|
||||
GAS_CO2 = 1
|
||||
)
|
||||
low_alert_category = "not_enough_tox"
|
||||
low_alert_datum = /obj/screen/alert/not_enough_tox
|
||||
high_alert_category = "too_much_tox"
|
||||
high_alert_datum = /obj/screen/alert/too_much_tox
|
||||
@@ -0,0 +1,169 @@
|
||||
/datum/gas/oxygen
|
||||
id = GAS_O2
|
||||
specific_heat = 20
|
||||
name = "Oxygen"
|
||||
oxidation_temperature = T0C - 100 // it checks max of this and fire temperature, so rarely will things spontaneously combust
|
||||
|
||||
/datum/gas/nitrogen
|
||||
id = GAS_N2
|
||||
specific_heat = 20
|
||||
breath_alert_info = list(
|
||||
not_enough_alert = list(
|
||||
alert_category = "not_enough_nitro",
|
||||
alert_type = /obj/screen/alert/not_enough_nitro
|
||||
),
|
||||
too_much_alert = list(
|
||||
alert_category = "too_much_nitro",
|
||||
alert_type = /obj/screen/alert/too_much_nitro
|
||||
)
|
||||
)
|
||||
name = "Nitrogen"
|
||||
|
||||
/datum/gas/carbon_dioxide //what the fuck is this?
|
||||
id = GAS_CO2
|
||||
specific_heat = 30
|
||||
name = "Carbon Dioxide"
|
||||
breath_results = GAS_O2
|
||||
breath_alert_info = list(
|
||||
not_enough_alert = list(
|
||||
alert_category = "not_enough_co2",
|
||||
alert_type = /obj/screen/alert/not_enough_co2
|
||||
),
|
||||
too_much_alert = list(
|
||||
alert_category = "too_much_co2",
|
||||
alert_type = /obj/screen/alert/too_much_co2
|
||||
)
|
||||
)
|
||||
fusion_power = 3
|
||||
|
||||
/datum/gas/plasma
|
||||
id = GAS_PLASMA
|
||||
specific_heat = 200
|
||||
name = "Plasma"
|
||||
gas_overlay = "plasma"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
// no fire info cause it has its own bespoke reaction for trit generation reasons
|
||||
|
||||
/datum/gas/water_vapor
|
||||
id = GAS_H2O
|
||||
specific_heat = 40
|
||||
name = "Water Vapor"
|
||||
gas_overlay = "water_vapor"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
fusion_power = 8
|
||||
breath_reagent = /datum/reagent/water
|
||||
|
||||
/datum/gas/hypernoblium
|
||||
id = GAS_HYPERNOB
|
||||
specific_heat = 2000
|
||||
name = "Hyper-noblium"
|
||||
gas_overlay = "freon"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
|
||||
/datum/gas/nitrous_oxide
|
||||
id = GAS_NITROUS
|
||||
specific_heat = 40
|
||||
name = "Nitrous Oxide"
|
||||
gas_overlay = "nitrous_oxide"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 2
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fire_products = list(GAS_N2 = 1)
|
||||
oxidation_rate = 0.5
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100
|
||||
|
||||
/datum/gas/nitryl
|
||||
id = GAS_NITRYL
|
||||
specific_heat = 20
|
||||
name = "Nitryl"
|
||||
gas_overlay = "nitryl"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fusion_power = 15
|
||||
fire_products = list(GAS_N2 = 0.5)
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
|
||||
/datum/gas/tritium
|
||||
id = GAS_TRITIUM
|
||||
specific_heat = 10
|
||||
name = "Tritium"
|
||||
gas_overlay = "tritium"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fusion_power = 1
|
||||
/*
|
||||
these are for when we add hydrogen, trit gets to keep its hardcoded fire for legacy reasons
|
||||
fire_provides = list(GAS_H2O = 2)
|
||||
fire_burn_rate = 2
|
||||
fire_energy_released = FIRE_HYDROGEN_ENERGY_RELEASED
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
*/
|
||||
|
||||
/datum/gas/bz
|
||||
id = GAS_BZ
|
||||
specific_heat = 20
|
||||
name = "BZ"
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fusion_power = 8
|
||||
|
||||
/datum/gas/stimulum
|
||||
id = GAS_STIMULUM
|
||||
specific_heat = 5
|
||||
name = "Stimulum"
|
||||
fusion_power = 7
|
||||
|
||||
/datum/gas/pluoxium
|
||||
id = GAS_PLUOXIUM
|
||||
specific_heat = 80
|
||||
name = "Pluoxium"
|
||||
fusion_power = 10
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 1000 // it is VERY stable
|
||||
oxidation_rate = 8
|
||||
|
||||
/datum/gas/miasma
|
||||
id = GAS_MIASMA
|
||||
specific_heat = 20
|
||||
fusion_power = 50
|
||||
name = "Miasma"
|
||||
gas_overlay = "miasma"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 60
|
||||
|
||||
/datum/gas/methane
|
||||
id = GAS_METHANE
|
||||
specific_heat = 30
|
||||
name = "Methane"
|
||||
breath_results = GAS_METHYL_BROMIDE
|
||||
fire_products = list(GAS_CO2 = 1, GAS_H2O = 2)
|
||||
fire_burn_rate = 0.5
|
||||
breath_alert_info = list(
|
||||
not_enough_alert = list(
|
||||
alert_category = "not_enough_ch4",
|
||||
alert_type = /obj/screen/alert/not_enough_ch4
|
||||
),
|
||||
too_much_alert = list(
|
||||
alert_category = "too_much_ch4",
|
||||
alert_type = /obj/screen/alert/too_much_ch4
|
||||
)
|
||||
)
|
||||
fire_energy_released = FIRE_CARBON_ENERGY_RELEASED
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
|
||||
/datum/gas/methyl_bromide
|
||||
id = GAS_METHYL_BROMIDE
|
||||
specific_heat = 42
|
||||
name = "Methyl Bromide"
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
breath_alert_info = list(
|
||||
not_enough_alert = list(
|
||||
alert_category = "not_enough_ch3br",
|
||||
alert_type = /obj/screen/alert/not_enough_ch3br
|
||||
),
|
||||
too_much_alert = list(
|
||||
alert_category = "too_much_ch3br",
|
||||
alert_type = /obj/screen/alert/too_much_ch3br
|
||||
)
|
||||
)
|
||||
fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5, GAS_BZ = 0.5)
|
||||
fire_energy_released = FIRE_CARBON_ENERGY_RELEASED
|
||||
fire_burn_rate = 0.5
|
||||
fire_temperature = 808 // its autoignition, it apparently doesn't spark readily, so i don't put it lower
|
||||
@@ -13,28 +13,21 @@
|
||||
if(!air)
|
||||
return
|
||||
|
||||
var/oxy = air.get_moles(/datum/gas/oxygen)
|
||||
if (oxy < 0.5)
|
||||
if (air.get_oxidation_power(exposed_temperature) < 0.5)
|
||||
return
|
||||
var/tox = air.get_moles(/datum/gas/plasma)
|
||||
var/trit = air.get_moles(/datum/gas/tritium)
|
||||
var/has_fuel = air.get_moles(GAS_PLASMA) > 0.5 || air.get_moles(GAS_TRITIUM) > 0.5 || air.get_fuel_amount(exposed_temperature) > 0.5
|
||||
if(active_hotspot)
|
||||
if(soh)
|
||||
if(tox > 0.5 || trit > 0.5)
|
||||
if(has_fuel)
|
||||
if(active_hotspot.temperature < exposed_temperature)
|
||||
active_hotspot.temperature = exposed_temperature
|
||||
if(active_hotspot.volume < exposed_volume)
|
||||
active_hotspot.volume = exposed_volume
|
||||
return
|
||||
|
||||
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (tox > 0.5 || trit > 0.5))
|
||||
|
||||
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && has_fuel)
|
||||
active_hotspot = new /obj/effect/hotspot(src, exposed_volume*25, exposed_temperature)
|
||||
|
||||
active_hotspot.just_spawned = (current_cycle < SSair.times_fired)
|
||||
//remove just_spawned protection if no longer processing this cell
|
||||
SSair.add_to_active(src, 0)
|
||||
|
||||
//This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile
|
||||
/obj/effect/hotspot
|
||||
anchored = TRUE
|
||||
@@ -48,7 +41,6 @@
|
||||
|
||||
var/volume = 125
|
||||
var/temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
var/just_spawned = TRUE
|
||||
var/bypassing = FALSE
|
||||
var/visual_update_tick = 0
|
||||
|
||||
@@ -70,7 +62,7 @@
|
||||
|
||||
location.active_hotspot = src
|
||||
|
||||
bypassing = !just_spawned && (volume > CELL_VOLUME*0.95)
|
||||
bypassing = volume > CELL_VOLUME*0.95
|
||||
|
||||
if(bypassing)
|
||||
volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE
|
||||
@@ -150,10 +142,6 @@
|
||||
|
||||
#define INSUFFICIENT(path) (location.air.get_moles(path) < 0.5)
|
||||
/obj/effect/hotspot/process()
|
||||
if(just_spawned)
|
||||
just_spawned = FALSE
|
||||
return
|
||||
|
||||
var/turf/open/location = loc
|
||||
if(!istype(location))
|
||||
qdel(src)
|
||||
@@ -164,13 +152,7 @@
|
||||
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
|
||||
qdel(src)
|
||||
return
|
||||
if(!location.air || (INSUFFICIENT(/datum/gas/plasma) && INSUFFICIENT(/datum/gas/tritium)) || INSUFFICIENT(/datum/gas/oxygen))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
//Not enough to burn
|
||||
// god damn it previous coder you made the INSUFFICIENT macro for a fucking reason why didn't you use it here smh
|
||||
if((INSUFFICIENT(/datum/gas/plasma) && INSUFFICIENT(/datum/gas/tritium)) || INSUFFICIENT(/datum/gas/oxygen))
|
||||
if(!location.air || location.air.get_oxidation_power() < 0.5 || (INSUFFICIENT(GAS_PLASMA) && INSUFFICIENT(GAS_TRITIUM) && location.air.get_fuel_amount() < 0.5))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -19,57 +19,58 @@
|
||||
/turf/open/CanAtmosPass(turf/T, vertical = FALSE)
|
||||
var/dir = vertical? get_dir_multiz(src, T) : get_dir(src, T)
|
||||
var/opp = REVERSE_DIR(dir)
|
||||
var/R = FALSE
|
||||
. = TRUE
|
||||
if(vertical && !(zAirOut(dir, T) && T.zAirIn(dir, src)))
|
||||
R = TRUE
|
||||
. = FALSE
|
||||
if(blocks_air || T.blocks_air)
|
||||
R = TRUE
|
||||
. = FALSE
|
||||
if (T == src)
|
||||
return !R
|
||||
return .
|
||||
for(var/obj/O in contents+T.contents)
|
||||
var/turf/other = (O.loc == src ? T : src)
|
||||
if(!(vertical? (CANVERTICALATMOSPASS(O, other)) : (CANATMOSPASS(O, other))))
|
||||
R = TRUE
|
||||
if(O.BlockSuperconductivity()) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments
|
||||
atmos_supeconductivity |= dir
|
||||
T.atmos_supeconductivity |= opp
|
||||
return FALSE //no need to keep going, we got all we asked
|
||||
. = FALSE
|
||||
if(O.BlockThermalConductivity()) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments
|
||||
conductivity_blocked_directions |= dir
|
||||
T.conductivity_blocked_directions |= opp
|
||||
if(!.)
|
||||
return .
|
||||
|
||||
atmos_supeconductivity &= ~dir
|
||||
T.atmos_supeconductivity &= ~opp
|
||||
|
||||
return !R
|
||||
|
||||
/atom/movable/proc/BlockSuperconductivity() // objects that block air and don't let superconductivity act. Only firelocks atm.
|
||||
/atom/movable/proc/BlockThermalConductivity() // Objects that don't let heat through.
|
||||
return FALSE
|
||||
|
||||
/turf/proc/ImmediateCalculateAdjacentTurfs()
|
||||
if(SSair.thread_running())
|
||||
CALCULATE_ADJACENT_TURFS(src)
|
||||
return
|
||||
var/canpass = CANATMOSPASS(src, src)
|
||||
var/canvpass = CANVERTICALATMOSPASS(src, src)
|
||||
for(var/direction in GLOB.cardinals_multiz)
|
||||
var/turf/T = get_step_multiz(src, direction)
|
||||
var/opp_dir = REVERSE_DIR(direction)
|
||||
if(!isopenturf(T))
|
||||
if(!istype(T))
|
||||
continue
|
||||
if(!(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) )
|
||||
var/opp_dir = REVERSE_DIR(direction)
|
||||
if(isopenturf(T) && !(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) )
|
||||
LAZYINITLIST(atmos_adjacent_turfs)
|
||||
LAZYINITLIST(T.atmos_adjacent_turfs)
|
||||
atmos_adjacent_turfs[T] = direction
|
||||
T.atmos_adjacent_turfs[src] = opp_dir
|
||||
T.__update_extools_adjacent_turfs()
|
||||
else
|
||||
if (atmos_adjacent_turfs)
|
||||
atmos_adjacent_turfs -= T
|
||||
if (T.atmos_adjacent_turfs)
|
||||
T.atmos_adjacent_turfs -= src
|
||||
T.__update_extools_adjacent_turfs()
|
||||
UNSETEMPTY(T.atmos_adjacent_turfs)
|
||||
T.set_sleeping(T.blocks_air)
|
||||
T.__update_auxtools_turf_adjacency_info(isspaceturf(T.get_z_base_turf()), -1)
|
||||
UNSETEMPTY(atmos_adjacent_turfs)
|
||||
src.atmos_adjacent_turfs = atmos_adjacent_turfs
|
||||
__update_extools_adjacent_turfs()
|
||||
set_sleeping(blocks_air)
|
||||
__update_auxtools_turf_adjacency_info(isspaceturf(get_z_base_turf()))
|
||||
|
||||
/turf/proc/__update_extools_adjacent_turfs()
|
||||
/turf/proc/set_sleeping(should_sleep)
|
||||
|
||||
/turf/proc/__update_auxtools_turf_adjacency_info()
|
||||
|
||||
//returns a list of adjacent turfs that can share air with this one.
|
||||
//alldir includes adjacent diagonal tiles that can share
|
||||
@@ -111,7 +112,6 @@
|
||||
/turf/air_update_turf(command = 0)
|
||||
if(command)
|
||||
ImmediateCalculateAdjacentTurfs()
|
||||
SSair.add_to_active(src,command)
|
||||
|
||||
/atom/movable/proc/move_update_air(turf/T)
|
||||
if(isturf(T))
|
||||
@@ -130,7 +130,4 @@
|
||||
|
||||
var/datum/gas_mixture/G = new
|
||||
G.parse_gas_string(text)
|
||||
|
||||
air.merge(G)
|
||||
archive()
|
||||
SSair.add_to_active(src, 0)
|
||||
assume_air(G)
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
/turf
|
||||
//used for temperature calculations
|
||||
var/thermal_conductivity = 0.005
|
||||
//conductivity is divided by 10 when interacting with air for balance purposes
|
||||
var/thermal_conductivity = 0.05
|
||||
var/heat_capacity = 1
|
||||
var/temperature_archived
|
||||
|
||||
//list of open turfs adjacent to us
|
||||
var/list/atmos_adjacent_turfs
|
||||
//bitfield of dirs in which we are superconducitng
|
||||
var/atmos_supeconductivity = NONE
|
||||
var/is_openturf = FALSE // used by extools shizz.
|
||||
|
||||
//used to determine whether we should archive
|
||||
var/archived_cycle = 0
|
||||
var/current_cycle = 0
|
||||
//bitfield of dirs in which we thermal conductivity is blocked
|
||||
var/conductivity_blocked_directions = NONE
|
||||
|
||||
//used for mapping and for breathing while in walls (because that's a thing that needs to be accounted for...)
|
||||
//string parsed by /datum/gas/proc/copy_from_turf
|
||||
@@ -32,21 +27,17 @@
|
||||
var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time
|
||||
|
||||
var/list/atmos_overlay_types //gas IDs of current active gas overlays
|
||||
is_openturf = TRUE
|
||||
|
||||
/turf/open/Initialize()
|
||||
if(!blocks_air)
|
||||
air = new
|
||||
air = new(2500,src)
|
||||
air.copy_from_turf(src)
|
||||
update_air_ref()
|
||||
update_air_ref(planetary_atmos ? 1 : 2)
|
||||
. = ..()
|
||||
|
||||
/turf/open/Destroy()
|
||||
if(active_hotspot)
|
||||
QDEL_NULL(active_hotspot)
|
||||
// Adds the adjacent turfs to the current atmos processing
|
||||
for(var/T in atmos_adjacent_turfs)
|
||||
SSair.add_to_active(T)
|
||||
return ..()
|
||||
|
||||
/// Function for Extools Atmos
|
||||
@@ -55,10 +46,46 @@
|
||||
/////////////////GAS MIXTURE PROCS///////////////////
|
||||
|
||||
/turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
|
||||
return assume_air_ratio(giver, 1)
|
||||
|
||||
/turf/open/assume_air_moles(datum/gas_mixture/giver, moles)
|
||||
if(!giver)
|
||||
return FALSE
|
||||
air.merge(giver)
|
||||
update_visuals()
|
||||
if(SSair.thread_running())
|
||||
SSair.deferred_airs += list(list(giver, air, moles / giver.total_moles()))
|
||||
else
|
||||
giver.transfer_to(air, moles)
|
||||
update_visuals()
|
||||
return TRUE
|
||||
|
||||
/turf/open/assume_air_ratio(datum/gas_mixture/giver, ratio)
|
||||
if(!giver)
|
||||
return FALSE
|
||||
if(SSair.thread_running())
|
||||
SSair.deferred_airs += list(list(giver, air, ratio))
|
||||
else
|
||||
giver.transfer_ratio_to(air, ratio)
|
||||
update_visuals()
|
||||
return TRUE
|
||||
|
||||
/turf/open/transfer_air(datum/gas_mixture/taker, moles)
|
||||
if(!taker || !return_air()) // shouldn't transfer from space
|
||||
return FALSE
|
||||
if(SSair.thread_running())
|
||||
SSair.deferred_airs += list(list(air, taker, moles / air.total_moles()))
|
||||
else
|
||||
air.transfer_to(taker, moles)
|
||||
update_visuals()
|
||||
return TRUE
|
||||
|
||||
/turf/open/transfer_air_ratio(datum/gas_mixture/taker, ratio)
|
||||
if(!taker || !return_air())
|
||||
return FALSE
|
||||
if(SSair.thread_running())
|
||||
SSair.deferred_airs += list(list(air, taker, ratio))
|
||||
else
|
||||
air.transfer_ratio_to(taker, ratio)
|
||||
update_visuals()
|
||||
return TRUE
|
||||
|
||||
/turf/open/remove_air(amount)
|
||||
@@ -67,6 +94,12 @@
|
||||
update_visuals()
|
||||
return removed
|
||||
|
||||
/turf/open/remove_air_ratio(ratio)
|
||||
var/datum/gas_mixture/ours = return_air()
|
||||
var/datum/gas_mixture/removed = ours.remove_ratio(ratio)
|
||||
update_visuals()
|
||||
return removed
|
||||
|
||||
/turf/open/proc/copy_air_with_tile(turf/open/T)
|
||||
if(istype(T))
|
||||
air.copy_from(T.air)
|
||||
@@ -86,17 +119,9 @@
|
||||
return air
|
||||
|
||||
/turf/temperature_expose()
|
||||
if(temperature > heat_capacity)
|
||||
if(return_temperature() > heat_capacity)
|
||||
to_be_destroyed = TRUE
|
||||
|
||||
/turf/proc/archive()
|
||||
temperature_archived = temperature
|
||||
|
||||
/turf/open/archive()
|
||||
air.archive()
|
||||
archived_cycle = SSair.times_fired
|
||||
temperature_archived = temperature
|
||||
|
||||
/turf/open/proc/eg_reset_cooldowns()
|
||||
/turf/open/proc/eg_garbage_collect()
|
||||
/turf/open/proc/get_excited()
|
||||
@@ -121,8 +146,8 @@
|
||||
for(var/id in air.get_gases())
|
||||
if (nonoverlaying_gases[id])
|
||||
continue
|
||||
var/gas_overlay = GLOB.meta_gas_overlays[id]
|
||||
if(gas_overlay && air.get_moles(id) > GLOB.meta_gas_visibility[META_GAS_MOLES_VISIBLE])
|
||||
var/gas_overlay = GLOB.gas_data.overlays[id]
|
||||
if(gas_overlay && air.get_moles(id) > GLOB.gas_data.visibility[id])
|
||||
new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(air.get_moles(id) / MOLES_GAS_VISIBLE_STEP, 1))]
|
||||
|
||||
if (atmos_overlay_types)
|
||||
@@ -156,7 +181,7 @@
|
||||
for (var/gastype in subtypesof(/datum/gas))
|
||||
var/datum/gas/gasvar = gastype
|
||||
if (!initial(gasvar.gas_overlay))
|
||||
.[gastype] = TRUE
|
||||
.[initial(gasvar.id)] = TRUE
|
||||
|
||||
/////////////////////////////SIMULATION///////////////////////////////////
|
||||
|
||||
@@ -171,7 +196,6 @@
|
||||
}
|
||||
*/
|
||||
/turf/proc/process_cell(fire_count)
|
||||
SSair.remove_from_active(src)
|
||||
|
||||
/turf/open/proc/equalize_pressure_in_zone(cyclenum)
|
||||
/turf/open/proc/consider_firelocks(turf/T2)
|
||||
@@ -198,7 +222,10 @@
|
||||
|
||||
//////////////////////////SPACEWIND/////////////////////////////
|
||||
|
||||
/turf/open/proc/consider_pressure_difference(turf/T, difference)
|
||||
/turf/proc/consider_pressure_difference()
|
||||
return
|
||||
|
||||
/turf/open/consider_pressure_difference(turf/T, difference)
|
||||
if(difference > pressure_difference)
|
||||
pressure_direction = get_dir(src, T)
|
||||
pressure_difference = difference
|
||||
@@ -236,117 +263,3 @@
|
||||
if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO))))
|
||||
step(src, direction)
|
||||
|
||||
////////////////////////SUPERCONDUCTIVITY/////////////////////////////
|
||||
/turf/proc/conductivity_directions()
|
||||
if(archived_cycle < SSair.times_fired)
|
||||
archive()
|
||||
return NORTH|SOUTH|EAST|WEST
|
||||
|
||||
/turf/open/conductivity_directions()
|
||||
if(blocks_air)
|
||||
return ..()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/T = get_step(src, direction)
|
||||
if(!(T in atmos_adjacent_turfs) && !(atmos_supeconductivity & direction))
|
||||
. |= direction
|
||||
|
||||
/turf/proc/neighbor_conduct_with_src(turf/open/other)
|
||||
if(!other.blocks_air) //Open but neighbor is solid
|
||||
other.temperature_share_open_to_solid(src)
|
||||
else //Both tiles are solid
|
||||
other.share_temperature_mutual_solid(src, thermal_conductivity)
|
||||
temperature_expose(null, temperature, null)
|
||||
|
||||
/turf/open/neighbor_conduct_with_src(turf/other)
|
||||
if(blocks_air)
|
||||
..()
|
||||
return
|
||||
|
||||
if(!other.blocks_air) //Both tiles are open
|
||||
var/turf/open/T = other
|
||||
T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
|
||||
else //Solid but neighbor is open
|
||||
temperature_share_open_to_solid(other)
|
||||
SSair.add_to_active(src, 0)
|
||||
|
||||
/turf/proc/super_conduct()
|
||||
var/conductivity_directions = conductivity_directions()
|
||||
archive()
|
||||
if(conductivity_directions)
|
||||
//Conduct with tiles around me
|
||||
for(var/direction in GLOB.cardinals)
|
||||
if(conductivity_directions & direction)
|
||||
var/turf/neighbor = get_step(src,direction)
|
||||
|
||||
if(!neighbor.thermal_conductivity)
|
||||
continue
|
||||
|
||||
if(neighbor.archived_cycle < SSair.times_fired)
|
||||
neighbor.archive()
|
||||
|
||||
neighbor.neighbor_conduct_with_src(src)
|
||||
|
||||
neighbor.consider_superconductivity()
|
||||
|
||||
radiate_to_spess()
|
||||
|
||||
finish_superconduction()
|
||||
|
||||
/turf/proc/finish_superconduction(temp = temperature)
|
||||
//Make sure still hot enough to continue conducting heat
|
||||
if(temp < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)
|
||||
SSair.active_super_conductivity -= src
|
||||
return FALSE
|
||||
|
||||
/turf/open/finish_superconduction()
|
||||
//Conduct with air on my tile if I have it
|
||||
if(!blocks_air)
|
||||
temperature = air.temperature_share(null, thermal_conductivity, temperature, heat_capacity)
|
||||
..((blocks_air ? temperature : air.return_temperature()))
|
||||
|
||||
/turf/proc/consider_superconductivity()
|
||||
if(!thermal_conductivity)
|
||||
return FALSE
|
||||
|
||||
SSair.active_super_conductivity[src] = TRUE
|
||||
|
||||
return TRUE
|
||||
|
||||
/turf/open/consider_superconductivity(starting)
|
||||
if(planetary_atmos)
|
||||
return FALSE
|
||||
if(air.return_temperature() < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
|
||||
return FALSE
|
||||
if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant.
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/turf/closed/consider_superconductivity(starting)
|
||||
if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/turf/proc/radiate_to_spess() //Radiate excess tile heat to space
|
||||
if(temperature > T0C) //Considering 0 degC as te break even point for radiation in and out
|
||||
var/delta_temperature = (temperature_archived - TCMB) //hardcoded space temperature
|
||||
if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER))
|
||||
|
||||
var/heat = thermal_conductivity*delta_temperature* \
|
||||
(heat_capacity*HEAT_CAPACITY_VACUUM/(heat_capacity+HEAT_CAPACITY_VACUUM))
|
||||
temperature -= heat/heat_capacity
|
||||
temperature = max(temperature,T0C) //otherwise we just sorta get stuck at super cold temps forever
|
||||
|
||||
/turf/open/proc/temperature_share_open_to_solid(turf/sharer)
|
||||
sharer.temperature = air.temperature_share(null, sharer.thermal_conductivity, sharer.temperature, sharer.heat_capacity)
|
||||
|
||||
/turf/proc/share_temperature_mutual_solid(turf/sharer, conduction_coefficient) //to be understood
|
||||
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
|
||||
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER && heat_capacity && sharer.heat_capacity)
|
||||
|
||||
var/heat = conduction_coefficient*delta_temperature* \
|
||||
(heat_capacity*sharer.heat_capacity/(heat_capacity+sharer.heat_capacity))
|
||||
|
||||
temperature -= heat/heat_capacity
|
||||
sharer.temperature += heat/sharer.heat_capacity
|
||||
temperature = max(temperature,T0C)
|
||||
sharer.temperature = max(sharer.temperature,T0C)
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
GLOBAL_LIST_INIT(hardcoded_gases, list(GAS_O2, GAS_N2, GAS_CO2, GAS_PLASMA)) //the main four gases, which were at one time hardcoded
|
||||
GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GAS_PLUOXIUM, GAS_STIMULUM, GAS_NITRYL))) //unable to react amongst themselves
|
||||
|
||||
// Auxgm
|
||||
// It's a send-up of XGM, like what baystation got.
|
||||
// It's got the same architecture as XGM, but it's structured
|
||||
// differently to make it more convenient for auxmos.
|
||||
|
||||
// Most important compared to TG is that it does away with hardcoded typepaths,
|
||||
// which lead to problems on the auxmos end anyway. We cache the string value
|
||||
// references on the Rust end, so no performance is lost here.
|
||||
|
||||
// Also allows you to add new gases at runtime
|
||||
|
||||
/proc/_auxtools_register_gas(datum/gas/gas) // makes sure auxtools knows stuff about this gas
|
||||
|
||||
/datum/auxgm
|
||||
var/list/datums = list()
|
||||
var/list/specific_heats = list()
|
||||
var/list/names = list()
|
||||
var/list/visibility = list()
|
||||
var/list/overlays = list()
|
||||
var/list/flags = list()
|
||||
var/list/ids = list()
|
||||
var/list/typepaths = list()
|
||||
var/list/fusion_powers = list()
|
||||
var/list/breathing_classes = list()
|
||||
var/list/breath_results = list()
|
||||
var/list/breath_reagents = list()
|
||||
var/list/breath_reagents_dangerous = list()
|
||||
var/list/breath_alert_info = list()
|
||||
var/list/oxidation_temperatures = list()
|
||||
var/list/oxidation_rates = list()
|
||||
var/list/fire_temperatures = list()
|
||||
var/list/fire_enthalpies = list()
|
||||
var/list/fire_products = list()
|
||||
var/list/fire_burn_rates = list()
|
||||
|
||||
|
||||
/datum/gas
|
||||
var/id = ""
|
||||
var/specific_heat = 0
|
||||
var/name = ""
|
||||
var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi
|
||||
var/moles_visible = null
|
||||
var/flags = NONE //currently used by canisters
|
||||
var/fusion_power = 0 // How much the gas destabilizes a fusion reaction
|
||||
var/breath_results = GAS_CO2 // what breathing this breathes out
|
||||
var/breath_reagent = null // what breathing this adds to your reagents
|
||||
var/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold
|
||||
var/list/breath_alert_info = null // list for alerts that pop up when you have too much/not enough of something
|
||||
var/oxidation_temperature = null // temperature above which this gas is an oxidizer; null for none
|
||||
var/oxidation_rate = 1 // how many moles of this can oxidize how many moles of material
|
||||
var/fire_temperature = null // temperature above which gas may catch fire; null for none
|
||||
var/list/fire_products = null // what results when this gas is burned (oxidizer or fuel); null for none
|
||||
var/fire_energy_released = 0 // how much energy is released per mole of fuel burned
|
||||
var/fire_burn_rate = 1 // how many moles are burned per product released
|
||||
|
||||
/datum/gas/proc/breath(partial_pressure, light_threshold, heavy_threshold, moles, mob/living/carbon/C, obj/item/organ/lungs/lungs)
|
||||
// This is only called on gases with the GAS_FLAG_BREATH_PROC flag. When possible, do NOT use this--
|
||||
// greatly prefer just adding a reagent. This is mostly around for legacy reasons.
|
||||
return null
|
||||
|
||||
/datum/auxgm/proc/add_gas(datum/gas/gas)
|
||||
var/g = gas.id
|
||||
if(g)
|
||||
datums[g] = gas
|
||||
specific_heats[g] = gas.specific_heat
|
||||
names[g] = gas.name
|
||||
if(gas.moles_visible)
|
||||
visibility[g] = gas.moles_visible
|
||||
overlays[g] = new /list(FACTOR_GAS_VISIBLE_MAX)
|
||||
for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX)
|
||||
overlays[g][i] = new /obj/effect/overlay/gas(gas.gas_overlay, i * 255 / FACTOR_GAS_VISIBLE_MAX)
|
||||
else
|
||||
visibility[g] = 0
|
||||
overlays[g] = 0
|
||||
flags[g] = gas.flags
|
||||
ids[g] = g
|
||||
typepaths[g] = gas.type
|
||||
fusion_powers[g] = gas.fusion_power
|
||||
|
||||
if(gas.breath_alert_info)
|
||||
breath_alert_info[g] = gas.breath_alert_info
|
||||
breath_results[g] = gas.breath_results
|
||||
if(gas.breath_reagent)
|
||||
breath_reagents[g] = gas.breath_reagent
|
||||
if(gas.breath_reagent_dangerous)
|
||||
breath_reagents_dangerous[g] = gas.breath_reagent_dangerous
|
||||
|
||||
if(gas.oxidation_temperature)
|
||||
oxidation_temperatures[g] = gas.oxidation_temperature
|
||||
oxidation_rates[g] = gas.oxidation_rate
|
||||
if(gas.fire_products)
|
||||
fire_products[g] = gas.fire_products
|
||||
fire_enthalpies[g] = gas.fire_energy_released
|
||||
else if(gas.fire_temperature)
|
||||
fire_temperatures[g] = gas.fire_temperature
|
||||
fire_burn_rates[g] = gas.fire_burn_rate
|
||||
if(gas.fire_products)
|
||||
fire_products[g] = gas.fire_products
|
||||
fire_enthalpies[g] = gas.fire_energy_released
|
||||
|
||||
_auxtools_register_gas(gas)
|
||||
|
||||
/proc/finalize_gas_refs()
|
||||
|
||||
/datum/auxgm/New()
|
||||
for(var/gas_path in subtypesof(/datum/gas))
|
||||
var/datum/gas/gas = new gas_path
|
||||
add_gas(gas)
|
||||
for(var/breathing_class_path in subtypesof(/datum/breathing_class))
|
||||
var/datum/breathing_class/class = new breathing_class_path
|
||||
breathing_classes[breathing_class_path] = class
|
||||
finalize_gas_refs()
|
||||
|
||||
|
||||
GLOBAL_DATUM_INIT(gas_data, /datum/auxgm, new)
|
||||
|
||||
/obj/effect/overlay/gas
|
||||
icon = 'icons/effects/atmospherics.dmi'
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
anchored = TRUE // should only appear in vis_contents, but to be safe
|
||||
layer = FLY_LAYER
|
||||
appearance_flags = TILE_BOUND
|
||||
vis_flags = NONE
|
||||
|
||||
/obj/effect/overlay/gas/New(state, alph)
|
||||
. = ..()
|
||||
icon_state = state
|
||||
alpha = alph
|
||||
@@ -6,27 +6,24 @@ What are the archived variables for?
|
||||
#define MINIMUM_HEAT_CAPACITY 0.0003
|
||||
#define MINIMUM_MOLE_COUNT 0.01
|
||||
|
||||
//Unomos - global list inits for all of the meta gas lists.
|
||||
//This setup allows procs to only look at one list instead of trying to dig around in lists-within-lists
|
||||
GLOBAL_LIST_INIT(meta_gas_specific_heats, meta_gas_heat_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_names, meta_gas_name_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_visibility, meta_gas_visibility_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_overlays, meta_gas_overlay_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_dangers, meta_gas_danger_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_ids, meta_gas_id_list())
|
||||
GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
/datum/gas_mixture
|
||||
/// Never ever set this variable, hooked into vv_get_var for view variables viewing.
|
||||
var/gas_list_view_only
|
||||
var/initial_volume = CELL_VOLUME //liters
|
||||
var/list/reaction_results
|
||||
var/list/analyzer_results //used for analyzer feedback - not initialized until its used
|
||||
var/_extools_pointer_gasmixture = 0 // Contains the memory address of the shared_ptr object for this gas mixture in c++ land. Don't. Touch. This. Var.
|
||||
var/_extools_pointer_gasmixture // Contains the index in the gas vector for this gas mixture in rust land. Don't. Touch. This. Var.
|
||||
|
||||
GLOBAL_LIST_INIT(auxtools_atmos_initialized,FALSE)
|
||||
|
||||
/proc/auxtools_atmos_init()
|
||||
|
||||
/datum/gas_mixture/New(volume)
|
||||
if (!isnull(volume))
|
||||
initial_volume = volume
|
||||
ATMOS_EXTOOLS_CHECK
|
||||
AUXTOOLS_CHECK(AUXMOS)
|
||||
if(!GLOB.auxtools_atmos_initialized && auxtools_atmos_init())
|
||||
GLOB.auxtools_atmos_initialized = TRUE
|
||||
__gasmixture_register()
|
||||
reaction_results = new
|
||||
|
||||
@@ -43,6 +40,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
var/list/dummy = get_gases()
|
||||
for(var/gas in dummy)
|
||||
dummy[gas] = get_moles(gas)
|
||||
dummy["CAP [gas]"] = partial_heat_capacity(gas)
|
||||
dummy["TEMP"] = return_temperature()
|
||||
dummy["PRESSURE"] = return_pressure()
|
||||
dummy["HEAT CAPACITY"] = heat_capacity()
|
||||
@@ -79,16 +77,16 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
var/list/gases = get_gases()
|
||||
for(var/gas in gases)
|
||||
gases[gas] = get_moles(gas)
|
||||
var/gastype = input(usr, "What kind of gas?", "Set Gas") as null|anything in subtypesof(/datum/gas)
|
||||
if(!ispath(gastype, /datum/gas))
|
||||
var/gasid = input(usr, "What kind of gas?", "Set Gas") as null|anything in GLOB.gas_data.ids
|
||||
if(!gasid)
|
||||
return
|
||||
var/amount = input(usr, "Input amount", "Set Gas", gases[gastype] || 0) as num|null
|
||||
var/amount = input(usr, "Input amount", "Set Gas", gases[gasid] || 0) as num|null
|
||||
if(!isnum(amount))
|
||||
return
|
||||
amount = max(0, amount)
|
||||
log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set gas type [gastype] to [amount] moles.")
|
||||
message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set gas type [gastype] to [amount] moles.")
|
||||
set_moles(gastype, amount)
|
||||
log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set gas [gasid] to [amount] moles.")
|
||||
message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set gas [gasid] to [amount] moles.")
|
||||
set_moles(gasid, amount)
|
||||
if(href_list[VV_HK_SET_TEMPERATURE])
|
||||
var/temp = input(usr, "Set the temperature of this mixture to?", "Set Temperature", return_temperature()) as num|null
|
||||
if(!isnum(temp))
|
||||
@@ -107,9 +105,11 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
set_volume(volume)
|
||||
|
||||
/*
|
||||
we use a hook instead
|
||||
/datum/gas_mixture/Del()
|
||||
__gasmixture_unregister()
|
||||
. = ..()*/
|
||||
. = ..()
|
||||
*/
|
||||
|
||||
/datum/gas_mixture/proc/__gasmixture_unregister()
|
||||
/datum/gas_mixture/proc/__gasmixture_register()
|
||||
@@ -123,6 +123,8 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
|
||||
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
|
||||
|
||||
/datum/gas_mixture/proc/partial_heat_capacity(gas_type)
|
||||
|
||||
/datum/gas_mixture/proc/total_moles()
|
||||
|
||||
/datum/gas_mixture/proc/return_pressure() //kilopascals
|
||||
@@ -147,7 +149,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
/datum/gas_mixture/proc/vv_react(datum/holder)
|
||||
return react(holder)
|
||||
|
||||
/datum/gas_mixture/proc/scrub_into(datum/gas_mixture/target, list/gases)
|
||||
/datum/gas_mixture/proc/scrub_into(datum/gas_mixture/target, ratio, list/gases)
|
||||
/datum/gas_mixture/proc/mark_immutable()
|
||||
/datum/gas_mixture/proc/get_gases()
|
||||
/datum/gas_mixture/proc/multiply(factor)
|
||||
@@ -155,7 +157,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
/datum/gas_mixture/proc/clear()
|
||||
|
||||
/datum/gas_mixture/proc/adjust_moles(gas_type, amt = 0)
|
||||
set_moles(gas_type, get_moles(gas_type) + amt)
|
||||
set_moles(gas_type, clamp(get_moles(gas_type) + amt,0,INFINITY))
|
||||
|
||||
/datum/gas_mixture/proc/return_volume() //liters
|
||||
|
||||
@@ -175,7 +177,9 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
|
||||
/datum/gas_mixture/proc/transfer_to(datum/gas_mixture/target, amount)
|
||||
//Transfers amount of gas to target. Equivalent to target.merge(remove(amount)) but faster.
|
||||
//Removes amount of gas from the gas_mixture
|
||||
|
||||
/datum/gas_mixture/proc/transfer_ratio_to(datum/gas_mixture/target, ratio)
|
||||
//Transfers ratio of gas to target. Equivalent to target.merge(remove_ratio(amount)) but faster.
|
||||
|
||||
/datum/gas_mixture/proc/remove_ratio(ratio)
|
||||
//Proportionally removes amount of gas from the gas_mixture
|
||||
@@ -213,6 +217,24 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
//Performs various reactions such as combustion or fusion (LOL)
|
||||
//Returns: 1 if any reaction took place; 0 otherwise
|
||||
|
||||
/datum/gas_mixture/proc/adjust_heat(amt)
|
||||
//Adjusts the thermal energy of the gas mixture, rather than having to do the full calculation.
|
||||
//Returns: null
|
||||
|
||||
/datum/gas_mixture/proc/equalize_with(datum/gas_mixture/giver)
|
||||
//Makes this mix have the same temperature and gas ratios as the giver, but with the same pressure, accounting for volume.
|
||||
//Returns: null
|
||||
|
||||
/datum/gas_mixture/proc/get_oxidation_power(temp)
|
||||
//Gets how much oxidation this gas can do, optionally at a given temperature.
|
||||
|
||||
/datum/gas_mixture/proc/get_fuel_amount(temp)
|
||||
//Gets how much fuel for fires (not counting trit/plasma!) this gas has, optionally at a given temperature.
|
||||
|
||||
/proc/equalize_all_gases_in_list(list/L)
|
||||
//Makes every gas in the given list have the same pressure, temperature and gas proportions.
|
||||
//Returns: null
|
||||
|
||||
/datum/gas_mixture/proc/__remove()
|
||||
/datum/gas_mixture/remove(amount)
|
||||
var/datum/gas_mixture/removed = new type
|
||||
@@ -234,26 +256,21 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
return copy
|
||||
|
||||
/datum/gas_mixture/copy_from_turf(turf/model)
|
||||
set_temperature(initial(model.initial_temperature))
|
||||
parse_gas_string(model.initial_gas_mix)
|
||||
|
||||
//acounts for changes in temperature
|
||||
var/turf/model_parent = model.parent_type
|
||||
if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
|
||||
set_temperature(model.temperature)
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/parse_gas_string(gas_string)
|
||||
var/list/gas = params2list(gas_string)
|
||||
if(gas["TEMP"])
|
||||
set_temperature(text2num(gas["TEMP"]))
|
||||
var/temp = text2num(gas["TEMP"])
|
||||
gas -= "TEMP"
|
||||
if(!isnum(temp) || temp < 2.7)
|
||||
temp = 2.7
|
||||
set_temperature(temp)
|
||||
clear()
|
||||
for(var/id in gas)
|
||||
var/path = id
|
||||
if(!ispath(path))
|
||||
path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around
|
||||
set_moles(path, text2num(gas[id]))
|
||||
set_moles(id, text2num(gas[id]))
|
||||
archive()
|
||||
return 1
|
||||
/*
|
||||
@@ -305,17 +322,11 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
if (. & STOP_REACTIONS)
|
||||
break
|
||||
*/
|
||||
//Takes the amount of the gas you want to PP as an argument
|
||||
//So I don't have to do some hacky switches/defines/magic strings
|
||||
//eg:
|
||||
//Tox_PP = get_partial_pressure(gas_mixture.toxins)
|
||||
//O2_PP = get_partial_pressure(gas_mixture.oxygen)
|
||||
|
||||
/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
|
||||
return (gas_pressure * R_IDEAL_GAS_EQUATION * return_temperature()) / BREATH_VOLUME
|
||||
//inverse
|
||||
/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure)
|
||||
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * return_temperature())
|
||||
/datum/gas_mixture/proc/set_analyzer_results(instability)
|
||||
if(!analyzer_results)
|
||||
analyzer_results = new
|
||||
analyzer_results["fusion"] = instability
|
||||
|
||||
//Mathematical proofs:
|
||||
/*
|
||||
@@ -379,8 +390,7 @@ get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
|
||||
var/transfer_moles = pressure_delta*output_air.return_volume()/(input_air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = input_air.remove(transfer_moles)
|
||||
output_air.merge(removed)
|
||||
input_air.transfer_to(output_air, transfer_moles)
|
||||
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
GLOBAL_LIST_INIT(hardcoded_gases, list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma)) //the main four gases, which were at one time hardcoded
|
||||
GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/pluoxium, /datum/gas/stimulum, /datum/gas/nitryl))) //unable to react amongst themselves
|
||||
|
||||
/proc/gas_id2path(id)
|
||||
var/list/meta_gas = GLOB.meta_gas_ids
|
||||
if(id in meta_gas)
|
||||
return id
|
||||
for(var/path in meta_gas)
|
||||
if(meta_gas[path] == id)
|
||||
return path
|
||||
return ""
|
||||
|
||||
//Unomos - oh god oh fuck oh shit oh lord have mercy this is messy as fuck oh god
|
||||
//my addiction to seeing better performance numbers isn't healthy, kids
|
||||
//you see this shit, children?
|
||||
//i am not a good idol. don't take after me.
|
||||
//this is literally worse than my alcohol addiction
|
||||
/proc/meta_gas_heat_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = initial(gas.specific_heat)
|
||||
|
||||
/proc/meta_gas_name_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = initial(gas.name)
|
||||
|
||||
/proc/meta_gas_visibility_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = initial(gas.moles_visible)
|
||||
|
||||
/proc/meta_gas_overlay_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = 0 //gotta make sure if(GLOB.meta_gas_overlays[gaspath]) doesn't break
|
||||
if(initial(gas.moles_visible) != null)
|
||||
.[gas_path] = new /list(FACTOR_GAS_VISIBLE_MAX)
|
||||
for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX)
|
||||
.[gas_path][i] = new /obj/effect/overlay/gas(initial(gas.gas_overlay), i * 255 / FACTOR_GAS_VISIBLE_MAX)
|
||||
|
||||
/proc/meta_gas_danger_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = initial(gas.dangerous)
|
||||
|
||||
/proc/meta_gas_id_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = initial(gas.id)
|
||||
|
||||
/proc/meta_gas_fusion_list()
|
||||
. = subtypesof(/datum/gas)
|
||||
for(var/gas_path in .)
|
||||
var/datum/gas/gas = gas_path
|
||||
.[gas_path] = initial(gas.fusion_power)
|
||||
|
||||
/*||||||||||||||/----------\||||||||||||||*\
|
||||
||||||||||||||||[GAS DATUMS]||||||||||||||||
|
||||
||||||||||||||||\__________/||||||||||||||||
|
||||
||||These should never be instantiated. ||||
|
||||
||||They exist only to make it easier ||||
|
||||
||||to add a new gas. They are accessed ||||
|
||||
||||only by meta_gas_list(). ||||
|
||||
\*||||||||||||||||||||||||||||||||||||||||*/
|
||||
|
||||
/datum/gas
|
||||
var/id = ""
|
||||
var/specific_heat = 0
|
||||
var/name = ""
|
||||
var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi
|
||||
var/moles_visible = null
|
||||
var/dangerous = FALSE //currently used by canisters
|
||||
var/fusion_power = 0 //How much the gas accelerates a fusion reaction
|
||||
var/rarity = 0 // relative rarity compared to other gases, used when setting up the reactions list.
|
||||
|
||||
/datum/gas/oxygen
|
||||
id = "o2"
|
||||
specific_heat = 20
|
||||
name = "Oxygen"
|
||||
rarity = 900
|
||||
|
||||
/datum/gas/nitrogen
|
||||
id = "n2"
|
||||
specific_heat = 20
|
||||
name = "Nitrogen"
|
||||
rarity = 1000
|
||||
|
||||
/datum/gas/carbon_dioxide //what the fuck is this?
|
||||
id = "co2"
|
||||
specific_heat = 30
|
||||
name = "Carbon Dioxide"
|
||||
fusion_power = 3
|
||||
rarity = 700
|
||||
|
||||
/datum/gas/plasma
|
||||
id = "plasma"
|
||||
specific_heat = 200
|
||||
name = "Plasma"
|
||||
gas_overlay = "plasma"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
dangerous = TRUE
|
||||
rarity = 800
|
||||
|
||||
/datum/gas/water_vapor
|
||||
id = "water_vapor"
|
||||
specific_heat = 40
|
||||
name = "Water Vapor"
|
||||
gas_overlay = "water_vapor"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
fusion_power = 8
|
||||
rarity = 500
|
||||
|
||||
/datum/gas/hypernoblium
|
||||
id = "nob"
|
||||
specific_heat = 2000
|
||||
name = "Hyper-noblium"
|
||||
gas_overlay = "freon"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
dangerous = TRUE
|
||||
rarity = 50
|
||||
|
||||
/datum/gas/nitrous_oxide
|
||||
id = "n2o"
|
||||
specific_heat = 40
|
||||
name = "Nitrous Oxide"
|
||||
gas_overlay = "nitrous_oxide"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 2
|
||||
dangerous = TRUE
|
||||
rarity = 600
|
||||
|
||||
/datum/gas/nitryl
|
||||
id = "no2"
|
||||
specific_heat = 20
|
||||
name = "Nitryl"
|
||||
gas_overlay = "nitryl"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
dangerous = TRUE
|
||||
fusion_power = 15
|
||||
rarity = 100
|
||||
|
||||
/datum/gas/tritium
|
||||
id = "tritium"
|
||||
specific_heat = 10
|
||||
name = "Tritium"
|
||||
gas_overlay = "tritium"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
dangerous = TRUE
|
||||
fusion_power = 1
|
||||
rarity = 300
|
||||
|
||||
/datum/gas/bz
|
||||
id = "bz"
|
||||
specific_heat = 20
|
||||
name = "BZ"
|
||||
dangerous = TRUE
|
||||
fusion_power = 8
|
||||
rarity = 400
|
||||
|
||||
/datum/gas/stimulum
|
||||
id = "stim"
|
||||
specific_heat = 5
|
||||
name = "Stimulum"
|
||||
fusion_power = 7
|
||||
rarity = 1
|
||||
|
||||
/datum/gas/pluoxium
|
||||
id = "pluox"
|
||||
specific_heat = 80
|
||||
name = "Pluoxium"
|
||||
fusion_power = 10
|
||||
rarity = 200
|
||||
|
||||
/datum/gas/miasma
|
||||
id = "miasma"
|
||||
specific_heat = 20
|
||||
fusion_power = 50
|
||||
name = "Miasma"
|
||||
gas_overlay = "miasma"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 60
|
||||
rarity = 250
|
||||
|
||||
/datum/gas/methane
|
||||
id = "methane"
|
||||
specific_heat = 30
|
||||
name = "Methane"
|
||||
rarity = 320
|
||||
|
||||
/datum/gas/methyl_bromide
|
||||
id = "methyl_bromide"
|
||||
specific_heat = 42
|
||||
name = "Methyl Bromide"
|
||||
dangerous = TRUE
|
||||
rarity = 310
|
||||
|
||||
|
||||
/obj/effect/overlay/gas
|
||||
icon = 'icons/effects/atmospherics.dmi'
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
anchored = TRUE // should only appear in vis_contents, but to be safe
|
||||
layer = FLY_LAYER
|
||||
appearance_flags = TILE_BOUND
|
||||
vis_flags = NONE
|
||||
|
||||
/obj/effect/overlay/gas/New(state, alph)
|
||||
. = ..()
|
||||
icon_state = state
|
||||
alpha = alph
|
||||
@@ -27,4 +27,4 @@
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/populate()
|
||||
..()
|
||||
set_moles(/datum/gas/nitrogen, MOLES_O2STANDARD + MOLES_N2STANDARD)
|
||||
set_moles(GAS_N2, MOLES_O2STANDARD + MOLES_N2STANDARD)
|
||||
|
||||
@@ -8,13 +8,6 @@
|
||||
if(initial(reaction.exclude))
|
||||
continue
|
||||
reaction = new r
|
||||
var/datum/gas/reaction_key
|
||||
for (var/req in reaction.min_requirements)
|
||||
if (ispath(req))
|
||||
var/datum/gas/req_gas = req
|
||||
if (!reaction_key || initial(reaction_key.rarity) > initial(req_gas.rarity))
|
||||
reaction_key = req_gas
|
||||
reaction.major_gas = reaction_key
|
||||
. += reaction
|
||||
sortTim(., /proc/cmp_gas_reaction)
|
||||
|
||||
@@ -26,7 +19,6 @@
|
||||
//when in doubt, use MINIMUM_MOLE_COUNT.
|
||||
var/list/min_requirements
|
||||
var/list/max_requirements
|
||||
var/major_gas //the highest rarity gas used in the reaction.
|
||||
var/exclude = FALSE //do it this way to allow for addition/removal of reactions midmatch in the future
|
||||
var/priority = 100 //lower numbers are checked/react later than higher numbers. if two reactions have the same priority they may happen in either order
|
||||
var/name = "reaction"
|
||||
@@ -49,7 +41,7 @@
|
||||
id = "nobstop"
|
||||
|
||||
/datum/gas_reaction/nobliumsupression/init_reqs()
|
||||
min_requirements = list(/datum/gas/hypernoblium = REACTION_OPPRESSION_THRESHOLD)
|
||||
min_requirements = list(GAS_HYPERNOB = REACTION_OPPRESSION_THRESHOLD)
|
||||
|
||||
/datum/gas_reaction/nobliumsupression/react()
|
||||
return STOP_REACTIONS
|
||||
@@ -61,7 +53,7 @@
|
||||
id = "vapor"
|
||||
|
||||
/datum/gas_reaction/water_vapor/init_reqs()
|
||||
min_requirements = list(/datum/gas/water_vapor = MOLES_GAS_VISIBLE)
|
||||
min_requirements = list(GAS_H2O = MOLES_GAS_VISIBLE)
|
||||
|
||||
/datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder)
|
||||
var/turf/open/location = isturf(holder) ? holder : null
|
||||
@@ -70,7 +62,7 @@
|
||||
if(location && location.freon_gas_act())
|
||||
. = REACTING
|
||||
else if(location && location.water_vapor_gas_act())
|
||||
air.adjust_moles(/datum/gas/water_vapor,-MOLES_GAS_VISIBLE)
|
||||
air.adjust_moles(GAS_H2O,-MOLES_GAS_VISIBLE)
|
||||
. = REACTING
|
||||
|
||||
// no test cause it's entirely based on location
|
||||
@@ -84,10 +76,22 @@
|
||||
/datum/gas_reaction/tritfire/init_reqs()
|
||||
min_requirements = list(
|
||||
"TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST,
|
||||
/datum/gas/tritium = MINIMUM_MOLE_COUNT,
|
||||
/datum/gas/oxygen = MINIMUM_MOLE_COUNT
|
||||
GAS_TRITIUM = MINIMUM_MOLE_COUNT,
|
||||
GAS_O2 = MINIMUM_MOLE_COUNT
|
||||
)
|
||||
|
||||
/proc/fire_expose(turf/open/location, datum/gas_mixture/air, temperature)
|
||||
if(istype(location) && temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
|
||||
location.hotspot_expose(temperature, CELL_VOLUME)
|
||||
for(var/I in location)
|
||||
var/atom/movable/item = I
|
||||
item.temperature_expose(air, temperature, CELL_VOLUME)
|
||||
location.temperature_expose(air, temperature, CELL_VOLUME)
|
||||
|
||||
/proc/radiation_burn(turf/open/location, energy_released)
|
||||
if(istype(location) && prob(10))
|
||||
radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR)
|
||||
|
||||
/datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder)
|
||||
var/energy_released = 0
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
@@ -97,20 +101,20 @@
|
||||
var/turf/open/location = isturf(holder) ? holder : null
|
||||
|
||||
var/burned_fuel = 0
|
||||
if(air.get_moles(/datum/gas/oxygen) < air.get_moles(/datum/gas/tritium))
|
||||
burned_fuel = air.get_moles(/datum/gas/oxygen)/TRITIUM_BURN_OXY_FACTOR
|
||||
air.adjust_moles(/datum/gas/tritium, -burned_fuel)
|
||||
if(air.get_moles(GAS_O2) < air.get_moles(GAS_TRITIUM))
|
||||
burned_fuel = air.get_moles(GAS_O2)/TRITIUM_BURN_OXY_FACTOR
|
||||
air.adjust_moles(GAS_TRITIUM, -burned_fuel)
|
||||
else
|
||||
burned_fuel = air.get_moles(/datum/gas/tritium)*TRITIUM_BURN_TRIT_FACTOR
|
||||
air.adjust_moles(/datum/gas/tritium, -air.get_moles(/datum/gas/tritium)/TRITIUM_BURN_TRIT_FACTOR)
|
||||
air.adjust_moles(/datum/gas/oxygen,-air.get_moles(/datum/gas/tritium))
|
||||
burned_fuel = air.get_moles(GAS_TRITIUM)*TRITIUM_BURN_TRIT_FACTOR
|
||||
air.adjust_moles(GAS_TRITIUM, -air.get_moles(GAS_TRITIUM)/TRITIUM_BURN_TRIT_FACTOR)
|
||||
air.adjust_moles(GAS_O2,-air.get_moles(GAS_TRITIUM))
|
||||
|
||||
if(burned_fuel)
|
||||
energy_released += (FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel)
|
||||
if(location && prob(10) && burned_fuel > TRITIUM_MINIMUM_RADIATION_ENERGY) //woah there let's not crash the server
|
||||
radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR)
|
||||
|
||||
air.adjust_moles(/datum/gas/water_vapor, burned_fuel/TRITIUM_BURN_OXY_FACTOR)
|
||||
air.adjust_moles(GAS_H2O, burned_fuel/TRITIUM_BURN_OXY_FACTOR)
|
||||
|
||||
cached_results["fire"] += burned_fuel
|
||||
|
||||
@@ -133,8 +137,8 @@
|
||||
|
||||
/datum/gas_reaction/tritfire/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/tritium,50)
|
||||
G.set_moles(/datum/gas/oxygen,50)
|
||||
G.set_moles(GAS_TRITIUM,50)
|
||||
G.set_moles(GAS_O2,50)
|
||||
G.set_temperature(500)
|
||||
var/result = G.react()
|
||||
if(result != REACTING)
|
||||
@@ -152,8 +156,8 @@
|
||||
/datum/gas_reaction/plasmafire/init_reqs()
|
||||
min_requirements = list(
|
||||
"TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST,
|
||||
/datum/gas/plasma = MINIMUM_MOLE_COUNT,
|
||||
/datum/gas/oxygen = MINIMUM_MOLE_COUNT
|
||||
GAS_PLASMA = MINIMUM_MOLE_COUNT,
|
||||
GAS_O2 = MINIMUM_MOLE_COUNT
|
||||
)
|
||||
|
||||
/datum/gas_reaction/plasmafire/react(datum/gas_mixture/air, datum/holder)
|
||||
@@ -178,21 +182,21 @@
|
||||
temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
|
||||
if(temperature_scale > 0)
|
||||
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
|
||||
if(air.get_moles(/datum/gas/oxygen) / air.get_moles(/datum/gas/plasma) > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
|
||||
if(air.get_moles(GAS_O2) / air.get_moles(GAS_PLASMA) > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
|
||||
super_saturation = TRUE
|
||||
if(air.get_moles(/datum/gas/oxygen) > air.get_moles(/datum/gas/plasma)*PLASMA_OXYGEN_FULLBURN)
|
||||
plasma_burn_rate = (air.get_moles(/datum/gas/plasma)*temperature_scale)/PLASMA_BURN_RATE_DELTA
|
||||
if(air.get_moles(GAS_O2) > air.get_moles(GAS_PLASMA)*PLASMA_OXYGEN_FULLBURN)
|
||||
plasma_burn_rate = (air.get_moles(GAS_PLASMA)*temperature_scale)/PLASMA_BURN_RATE_DELTA
|
||||
else
|
||||
plasma_burn_rate = (temperature_scale*(air.get_moles(/datum/gas/oxygen)/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
|
||||
plasma_burn_rate = (temperature_scale*(air.get_moles(GAS_O2)/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
|
||||
|
||||
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
|
||||
plasma_burn_rate = min(plasma_burn_rate,air.get_moles(/datum/gas/plasma),air.get_moles(/datum/gas/oxygen)/oxygen_burn_rate) //Ensures matter is conserved properly
|
||||
air.set_moles(/datum/gas/plasma, QUANTIZE(air.get_moles(/datum/gas/plasma) - plasma_burn_rate))
|
||||
air.set_moles(/datum/gas/oxygen, QUANTIZE(air.get_moles(/datum/gas/oxygen) - (plasma_burn_rate * oxygen_burn_rate)))
|
||||
plasma_burn_rate = min(plasma_burn_rate,air.get_moles(GAS_PLASMA),air.get_moles(GAS_O2)/oxygen_burn_rate) //Ensures matter is conserved properly
|
||||
air.set_moles(GAS_PLASMA, QUANTIZE(air.get_moles(GAS_PLASMA) - plasma_burn_rate))
|
||||
air.set_moles(GAS_O2, QUANTIZE(air.get_moles(GAS_O2) - (plasma_burn_rate * oxygen_burn_rate)))
|
||||
if (super_saturation)
|
||||
air.adjust_moles(/datum/gas/tritium, plasma_burn_rate)
|
||||
air.adjust_moles(GAS_TRITIUM, plasma_burn_rate)
|
||||
else
|
||||
air.adjust_moles(/datum/gas/carbon_dioxide, plasma_burn_rate)
|
||||
air.adjust_moles(GAS_CO2, plasma_burn_rate)
|
||||
|
||||
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
|
||||
|
||||
@@ -217,8 +221,8 @@
|
||||
|
||||
/datum/gas_reaction/plasmafire/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/plasma,50)
|
||||
G.set_moles(/datum/gas/oxygen,50)
|
||||
G.set_moles(GAS_PLASMA,50)
|
||||
G.set_moles(GAS_O2,50)
|
||||
G.set_volume(1000)
|
||||
G.set_temperature(500)
|
||||
var/result = G.react()
|
||||
@@ -226,21 +230,114 @@
|
||||
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
|
||||
if(!G.reaction_results["fire"])
|
||||
return list("success" = FALSE, "message" = "Plasma fires aren't setting fire results correctly!")
|
||||
if(!G.get_moles(/datum/gas/carbon_dioxide))
|
||||
if(!G.get_moles(GAS_CO2))
|
||||
return list("success" = FALSE, "message" = "Plasma fires aren't making CO2!")
|
||||
G.clear()
|
||||
G.set_moles(/datum/gas/plasma,10)
|
||||
G.set_moles(/datum/gas/oxygen,1000)
|
||||
G.set_moles(GAS_PLASMA,10)
|
||||
G.set_moles(GAS_O2,1000)
|
||||
G.set_temperature(500)
|
||||
result = G.react()
|
||||
if(!G.get_moles(/datum/gas/tritium))
|
||||
if(!G.get_moles(GAS_TRITIUM))
|
||||
return list("success" = FALSE, "message" = "Plasma fires aren't making trit!")
|
||||
return ..()
|
||||
|
||||
/datum/gas_reaction/genericfire
|
||||
priority = -3 // very last reaction
|
||||
name = "Combustion"
|
||||
id = "genericfire"
|
||||
|
||||
/datum/gas_reaction/genericfire/init_reqs()
|
||||
var/lowest_fire_temp = INFINITY
|
||||
var/list/fire_temperatures = GLOB.gas_data.fire_temperatures
|
||||
for(var/gas in fire_temperatures)
|
||||
lowest_fire_temp = min(lowest_fire_temp, fire_temperatures[gas])
|
||||
var/lowest_oxi_temp = INFINITY
|
||||
var/list/oxidation_temperatures = GLOB.gas_data.oxidation_temperatures
|
||||
for(var/gas in oxidation_temperatures)
|
||||
lowest_oxi_temp = min(lowest_oxi_temp, oxidation_temperatures[gas])
|
||||
min_requirements = list(
|
||||
"TEMP" = max(lowest_oxi_temp, lowest_fire_temp),
|
||||
"FIRE_REAGENTS" = MINIMUM_MOLE_COUNT
|
||||
)
|
||||
|
||||
// no requirements, always runs
|
||||
// bad idea? maybe
|
||||
// this is overridden by auxmos but, hey, good idea to have it readable
|
||||
|
||||
/datum/gas_reaction/genericfire/react(datum/gas_mixture/air, datum/holder)
|
||||
var/temperature = air.return_temperature()
|
||||
var/list/oxidation_temps = GLOB.gas_data.oxidation_temperatures
|
||||
var/list/oxidation_rates = GLOB.gas_data.oxidation_rates
|
||||
var/oxidation_power = 0
|
||||
var/list/burn_results = list()
|
||||
var/list/fuels = list()
|
||||
var/list/oxidizers = list()
|
||||
var/list/fuel_rates = GLOB.gas_data.fire_burn_rates
|
||||
var/list/fuel_temps = GLOB.gas_data.fire_temperatures
|
||||
var/total_fuel = 0
|
||||
var/energy_released = 0
|
||||
for(var/G in air.get_gases())
|
||||
var/oxidation_temp = oxidation_temps[G]
|
||||
if(oxidation_temp && oxidation_temp > temperature)
|
||||
var/temperature_scale = max(0, 1-(temperature / oxidation_temp))
|
||||
var/amt = air.get_moles(G) * temperature_scale
|
||||
oxidizers[G] = amt
|
||||
oxidation_power += amt * oxidation_rates[G]
|
||||
else
|
||||
var/fuel_temp = fuel_temps[G]
|
||||
if(fuel_temp && fuel_temp > temperature)
|
||||
var/amt = (air.get_moles(G) / fuel_rates[G]) * max(0, 1-(temperature / fuel_temp))
|
||||
fuels[G] = amt // we have to calculate the actual amount we're using after we get all oxidation together
|
||||
total_fuel += amt
|
||||
if(oxidation_power <= 0 || total_fuel <= 0)
|
||||
return NO_REACTION
|
||||
var/oxidation_ratio = oxidation_power / total_fuel
|
||||
if(oxidation_ratio > 1)
|
||||
for(var/oxidizer in oxidizers)
|
||||
oxidizers[oxidizer] /= oxidation_ratio
|
||||
else if(oxidation_ratio < 1)
|
||||
for(var/fuel in fuels)
|
||||
fuels[fuel] *= oxidation_ratio
|
||||
fuels += oxidizers
|
||||
var/list/fire_products = GLOB.gas_data.fire_products
|
||||
var/list/fire_enthalpies = GLOB.gas_data.fire_enthalpies
|
||||
for(var/fuel in fuels + oxidizers)
|
||||
var/amt = fuels[fuel]
|
||||
if(!burn_results[fuel])
|
||||
burn_results[fuel] = 0
|
||||
burn_results[fuel] -= amt
|
||||
energy_released += amt * fire_enthalpies[fuel]
|
||||
for(var/product in fire_products[fuel])
|
||||
if(!burn_results[product])
|
||||
burn_results[product] = 0
|
||||
burn_results[product] += amt
|
||||
var/final_energy = air.thermal_energy() + energy_released
|
||||
for(var/result in burn_results)
|
||||
air.adjust_moles(result, burn_results[result])
|
||||
air.set_temperature(final_energy / air.heat_capacity())
|
||||
var/list/cached_results = air.reaction_results
|
||||
cached_results["fire"] = min(total_fuel, oxidation_power) * 2
|
||||
return cached_results["fire"] ? REACTING : NO_REACTION
|
||||
|
||||
|
||||
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again). Again!
|
||||
//Fusion Rework Counter: Please increment this if you make a major overhaul to this system again.
|
||||
//6 reworks
|
||||
|
||||
/proc/fusion_ball(datum/holder, reaction_energy, instability)
|
||||
var/turf/open/location
|
||||
if (istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet.
|
||||
var/datum/pipeline/fusion_pipenet = holder
|
||||
location = get_turf(pick(fusion_pipenet.members))
|
||||
else
|
||||
location = get_turf(holder)
|
||||
if(location)
|
||||
var/particle_chance = ((PARTICLE_CHANCE_CONSTANT)/(reaction_energy-PARTICLE_CHANCE_CONSTANT)) + 1//Asymptopically approaches 100% as the energy of the reaction goes up.
|
||||
if(prob(PERCENT(particle_chance)))
|
||||
location.fire_nuclear_particle()
|
||||
var/rad_power = max((FUSION_RAD_COEFFICIENT/instability) + FUSION_RAD_MAX,0)
|
||||
radiation_pulse(location,rad_power)
|
||||
|
||||
/datum/gas_reaction/fusion
|
||||
exclude = FALSE
|
||||
priority = 2
|
||||
@@ -250,9 +347,9 @@
|
||||
/datum/gas_reaction/fusion/init_reqs()
|
||||
min_requirements = list(
|
||||
"TEMP" = FUSION_TEMPERATURE_THRESHOLD,
|
||||
/datum/gas/tritium = FUSION_TRITIUM_MOLES_USED,
|
||||
/datum/gas/plasma = FUSION_MOLE_THRESHOLD,
|
||||
/datum/gas/carbon_dioxide = FUSION_MOLE_THRESHOLD)
|
||||
GAS_TRITIUM = FUSION_TRITIUM_MOLES_USED,
|
||||
GAS_PLASMA = FUSION_MOLE_THRESHOLD,
|
||||
GAS_CO2 = FUSION_MOLE_THRESHOLD)
|
||||
|
||||
/datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder)
|
||||
var/turf/open/location
|
||||
@@ -268,12 +365,12 @@
|
||||
var/list/cached_scan_results = air.analyzer_results
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/reaction_energy = 0 //Reaction energy can be negative or positive, for both exothermic and endothermic reactions.
|
||||
var/initial_plasma = air.get_moles(/datum/gas/plasma)
|
||||
var/initial_carbon = air.get_moles(/datum/gas/carbon_dioxide)
|
||||
var/initial_plasma = air.get_moles(GAS_PLASMA)
|
||||
var/initial_carbon = air.get_moles(GAS_CO2)
|
||||
var/scale_factor = (air.return_volume())/(PI) //We scale it down by volume/Pi because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions.
|
||||
var/toroidal_size = (2*PI)+TORADIANS(arctan((air.return_volume()-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus
|
||||
var/gas_power = 0
|
||||
var/list/gas_fusion_powers = GLOB.meta_gas_fusions
|
||||
var/list/gas_fusion_powers = GLOB.gas_data.fusion_powers
|
||||
for (var/gas_id in air.get_gases())
|
||||
gas_power += (gas_fusion_powers[gas_id]*air.get_moles(gas_id))
|
||||
var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is
|
||||
@@ -287,9 +384,9 @@
|
||||
carbon = MODULUS(carbon - plasma, toroidal_size)
|
||||
|
||||
|
||||
air.set_moles(/datum/gas/plasma, plasma*scale_factor + FUSION_MOLE_THRESHOLD) //Scales the gases back up
|
||||
air.set_moles(/datum/gas/carbon_dioxide , carbon*scale_factor + FUSION_MOLE_THRESHOLD)
|
||||
var/delta_plasma = initial_plasma - air.get_moles(/datum/gas/plasma)
|
||||
air.set_moles(GAS_PLASMA, plasma*scale_factor + FUSION_MOLE_THRESHOLD) //Scales the gases back up
|
||||
air.set_moles(GAS_CO2 , carbon*scale_factor + FUSION_MOLE_THRESHOLD)
|
||||
var/delta_plasma = initial_plasma - air.get_moles(GAS_PLASMA)
|
||||
|
||||
reaction_energy += delta_plasma*PLASMA_BINDING_ENERGY //Energy is gained or lost corresponding to the creation or destruction of mass.
|
||||
if(instability < FUSION_INSTABILITY_ENDOTHERMALITY)
|
||||
@@ -298,17 +395,17 @@
|
||||
reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5
|
||||
|
||||
if(air.thermal_energy() + reaction_energy < 0) //No using energy that doesn't exist.
|
||||
air.set_moles(/datum/gas/plasma,initial_plasma)
|
||||
air.set_moles(/datum/gas/carbon_dioxide, initial_carbon)
|
||||
air.set_moles(GAS_PLASMA,initial_plasma)
|
||||
air.set_moles(GAS_CO2, initial_carbon)
|
||||
return NO_REACTION
|
||||
air.adjust_moles(/datum/gas/tritium, -FUSION_TRITIUM_MOLES_USED)
|
||||
air.adjust_moles(GAS_TRITIUM, -FUSION_TRITIUM_MOLES_USED)
|
||||
//The decay of the tritium and the reaction's energy produces waste gases, different ones depending on whether the reaction is endo or exothermic
|
||||
if(reaction_energy > 0)
|
||||
air.adjust_moles(/datum/gas/oxygen, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
air.adjust_moles(/datum/gas/nitrous_oxide, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
air.adjust_moles(GAS_O2, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
air.adjust_moles(GAS_NITROUS, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
else
|
||||
air.adjust_moles(/datum/gas/bz, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
air.adjust_moles(/datum/gas/nitryl, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
air.adjust_moles(GAS_BZ, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
air.adjust_moles(GAS_NITRYL, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT))
|
||||
|
||||
if(reaction_energy)
|
||||
if(location)
|
||||
@@ -325,10 +422,10 @@
|
||||
|
||||
/datum/gas_reaction/fusion/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/carbon_dioxide,300)
|
||||
G.set_moles(/datum/gas/plasma,1000)
|
||||
G.set_moles(/datum/gas/tritium,100.61)
|
||||
G.set_moles(/datum/gas/nitryl,1)
|
||||
G.set_moles(GAS_CO2,300)
|
||||
G.set_moles(GAS_PLASMA,1000)
|
||||
G.set_moles(GAS_TRITIUM,100.61)
|
||||
G.set_moles(GAS_NITRYL,1)
|
||||
G.set_temperature(15000)
|
||||
G.set_volume(1000)
|
||||
var/result = G.react()
|
||||
@@ -337,11 +434,11 @@
|
||||
if(abs(G.analyzer_results["fusion"] - 3) > 0.0000001)
|
||||
var/instability = G.analyzer_results["fusion"]
|
||||
return list("success" = FALSE, "message" = "Fusion is not calculating analyzer results correctly, should be 3.000000045, is instead [instability]")
|
||||
if(abs(G.get_moles(/datum/gas/plasma) - 850.616) > 0.5)
|
||||
var/plas = G.get_moles(/datum/gas/plasma)
|
||||
if(abs(G.get_moles(GAS_PLASMA) - 850.616) > 0.5)
|
||||
var/plas = G.get_moles(GAS_PLASMA)
|
||||
return list("success" = FALSE, "message" = "Fusion is not calculating plasma correctly, should be 850.616, is instead [plas]")
|
||||
if(abs(G.get_moles(/datum/gas/carbon_dioxide) - 1699.384) > 0.5)
|
||||
var/co2 = G.get_moles(/datum/gas/carbon_dioxide)
|
||||
if(abs(G.get_moles(GAS_CO2) - 1699.384) > 0.5)
|
||||
var/co2 = G.get_moles(GAS_CO2)
|
||||
return list("success" = FALSE, "message" = "Fusion is not calculating co2 correctly, should be 1699.384, is instead [co2]")
|
||||
if(abs(G.return_temperature() - 27600) > 200) // calculating this manually sucks dude
|
||||
var/temp = G.return_temperature()
|
||||
@@ -355,9 +452,9 @@
|
||||
|
||||
/datum/gas_reaction/nitrylformation/init_reqs()
|
||||
min_requirements = list(
|
||||
/datum/gas/oxygen = 20,
|
||||
/datum/gas/nitrogen = 20,
|
||||
/datum/gas/nitrous_oxide = 5,
|
||||
GAS_O2 = 20,
|
||||
GAS_N2 = 20,
|
||||
GAS_NITROUS = 5,
|
||||
"TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST*25
|
||||
)
|
||||
|
||||
@@ -365,13 +462,13 @@
|
||||
var/temperature = air.return_temperature()
|
||||
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),air.get_moles(/datum/gas/oxygen),air.get_moles(/datum/gas/nitrogen))
|
||||
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),air.get_moles(GAS_O2),air.get_moles(GAS_N2))
|
||||
var/energy_used = heat_efficency*NITRYL_FORMATION_ENERGY
|
||||
if ((air.get_moles(/datum/gas/oxygen) - heat_efficency < 0 )|| (air.get_moles(/datum/gas/nitrogen) - heat_efficency < 0)) //Shouldn't produce gas from nothing.
|
||||
if ((air.get_moles(GAS_O2) - heat_efficency < 0 )|| (air.get_moles(GAS_N2) - heat_efficency < 0)) //Shouldn't produce gas from nothing.
|
||||
return NO_REACTION
|
||||
air.adjust_moles(/datum/gas/oxygen, -heat_efficency)
|
||||
air.adjust_moles(/datum/gas/nitrogen, -heat_efficency)
|
||||
air.adjust_moles(/datum/gas/nitryl, heat_efficency*2)
|
||||
air.adjust_moles(GAS_O2, -heat_efficency)
|
||||
air.adjust_moles(GAS_N2, -heat_efficency)
|
||||
air.adjust_moles(GAS_NITRYL, heat_efficency*2)
|
||||
|
||||
if(energy_used > 0)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
@@ -381,15 +478,15 @@
|
||||
|
||||
/datum/gas_reaction/nitrylformation/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/oxygen,30)
|
||||
G.set_moles(/datum/gas/nitrogen,30)
|
||||
G.set_moles(/datum/gas/nitrous_oxide,10)
|
||||
G.set_moles(GAS_O2,30)
|
||||
G.set_moles(GAS_N2,30)
|
||||
G.set_moles(GAS_NITROUS,10)
|
||||
G.set_volume(1000)
|
||||
G.set_temperature(150000)
|
||||
var/result = G.react()
|
||||
if(result != REACTING)
|
||||
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
|
||||
if(!G.get_moles(/datum/gas/nitryl) < 0.8)
|
||||
if(!G.get_moles(GAS_NITRYL) < 0.8)
|
||||
return list("success" = FALSE, "message" = "Nitryl isn't being generated correctly!")
|
||||
return ..()
|
||||
|
||||
@@ -400,8 +497,8 @@
|
||||
|
||||
/datum/gas_reaction/bzformation/init_reqs()
|
||||
min_requirements = list(
|
||||
/datum/gas/nitrous_oxide = 10,
|
||||
/datum/gas/plasma = 10
|
||||
GAS_NITROUS = 10,
|
||||
GAS_PLASMA = 10
|
||||
)
|
||||
|
||||
|
||||
@@ -409,16 +506,16 @@
|
||||
var/temperature = air.return_temperature()
|
||||
var/pressure = air.return_pressure()
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(air.get_moles(/datum/gas/plasma)/air.get_moles(/datum/gas/nitrous_oxide),1))),air.get_moles(/datum/gas/nitrous_oxide),air.get_moles(/datum/gas/plasma)/2)
|
||||
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(air.get_moles(GAS_PLASMA)/air.get_moles(GAS_NITROUS),1))),air.get_moles(GAS_NITROUS),air.get_moles(GAS_PLASMA)/2)
|
||||
var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
|
||||
if ((air.get_moles(/datum/gas/nitrous_oxide) - reaction_efficency < 0 )|| (air.get_moles(/datum/gas/plasma) - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing.
|
||||
if ((air.get_moles(GAS_NITROUS) - reaction_efficency < 0 )|| (air.get_moles(GAS_PLASMA) - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing.
|
||||
return NO_REACTION
|
||||
air.adjust_moles(/datum/gas/bz, reaction_efficency)
|
||||
if(reaction_efficency == air.get_moles(/datum/gas/nitrous_oxide))
|
||||
air.adjust_moles(/datum/gas/bz, -min(pressure,1))
|
||||
air.adjust_moles(/datum/gas/oxygen, min(pressure,1))
|
||||
air.adjust_moles(/datum/gas/nitrous_oxide, -reaction_efficency)
|
||||
air.adjust_moles(/datum/gas/plasma, -2*reaction_efficency)
|
||||
air.adjust_moles(GAS_BZ, reaction_efficency)
|
||||
if(reaction_efficency == air.get_moles(GAS_NITROUS))
|
||||
air.adjust_moles(GAS_BZ, -min(pressure,1))
|
||||
air.adjust_moles(GAS_O2, min(pressure,1))
|
||||
air.adjust_moles(GAS_NITROUS, -reaction_efficency)
|
||||
air.adjust_moles(GAS_PLASMA, -2*reaction_efficency)
|
||||
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((reaction_efficency**2)*BZ_RESEARCH_SCALE),BZ_RESEARCH_MAX_AMOUNT)
|
||||
|
||||
@@ -430,14 +527,14 @@
|
||||
|
||||
/datum/gas_reaction/bzformation/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/plasma,15)
|
||||
G.set_moles(/datum/gas/nitrous_oxide,15)
|
||||
G.set_moles(GAS_PLASMA,15)
|
||||
G.set_moles(GAS_NITROUS,15)
|
||||
G.set_volume(1000)
|
||||
G.set_temperature(10)
|
||||
var/result = G.react()
|
||||
if(result != REACTING)
|
||||
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
|
||||
if(!G.get_moles(/datum/gas/bz) < 4) // efficiency is 4.0643 and bz generation == efficiency
|
||||
if(!G.get_moles(GAS_BZ) < 4) // efficiency is 4.0643 and bz generation == efficiency
|
||||
return list("success" = FALSE, "message" = "Nitryl isn't being generated correctly!")
|
||||
return ..()
|
||||
|
||||
@@ -448,23 +545,23 @@
|
||||
|
||||
/datum/gas_reaction/stimformation/init_reqs()
|
||||
min_requirements = list(
|
||||
/datum/gas/tritium = 30,
|
||||
/datum/gas/plasma = 10,
|
||||
/datum/gas/bz = 20,
|
||||
/datum/gas/nitryl = 30,
|
||||
GAS_TRITIUM = 30,
|
||||
GAS_PLASMA = 10,
|
||||
GAS_BZ = 20,
|
||||
GAS_NITRYL = 30,
|
||||
"TEMP" = STIMULUM_HEAT_SCALE/2)
|
||||
|
||||
/datum/gas_reaction/stimformation/react(datum/gas_mixture/air)
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/heat_scale = min(air.return_temperature()/STIMULUM_HEAT_SCALE,air.get_moles(/datum/gas/tritium),air.get_moles(/datum/gas/plasma),air.get_moles(/datum/gas/nitryl))
|
||||
var/heat_scale = min(air.return_temperature()/STIMULUM_HEAT_SCALE,air.get_moles(GAS_TRITIUM),air.get_moles(GAS_PLASMA),air.get_moles(GAS_NITRYL))
|
||||
var/stim_energy_change = heat_scale + STIMULUM_FIRST_RISE*(heat_scale**2) - STIMULUM_FIRST_DROP*(heat_scale**3) + STIMULUM_SECOND_RISE*(heat_scale**4) - STIMULUM_ABSOLUTE_DROP*(heat_scale**5)
|
||||
|
||||
if ((air.get_moles(/datum/gas/tritium) - heat_scale < 0 )|| (air.get_moles(/datum/gas/plasma) - heat_scale < 0) || (air.get_moles(/datum/gas/nitryl) - heat_scale < 0)) //Shouldn't produce gas from nothing.
|
||||
if ((air.get_moles(GAS_TRITIUM) - heat_scale < 0 )|| (air.get_moles(GAS_PLASMA) - heat_scale < 0) || (air.get_moles(GAS_NITRYL) - heat_scale < 0)) //Shouldn't produce gas from nothing.
|
||||
return NO_REACTION
|
||||
air.adjust_moles(/datum/gas/stimulum, heat_scale/10)
|
||||
air.adjust_moles(/datum/gas/tritium, -heat_scale)
|
||||
air.adjust_moles(/datum/gas/plasma, -heat_scale)
|
||||
air.adjust_moles(/datum/gas/nitryl, -heat_scale)
|
||||
air.adjust_moles(GAS_STIMULUM, heat_scale/10)
|
||||
air.adjust_moles(GAS_TRITIUM, -heat_scale)
|
||||
air.adjust_moles(GAS_PLASMA, -heat_scale)
|
||||
air.adjust_moles(GAS_NITRYL, -heat_scale)
|
||||
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, STIMULUM_RESEARCH_AMOUNT*max(stim_energy_change,0))
|
||||
if(stim_energy_change)
|
||||
@@ -476,17 +573,17 @@
|
||||
/datum/gas_reaction/stimformation/test()
|
||||
//above mentioned "strange pattern" is a basic quintic polynomial, it's fine, can calculate it manually
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/bz,30)
|
||||
G.set_moles(/datum/gas/plasma,1000)
|
||||
G.set_moles(/datum/gas/tritium,1000)
|
||||
G.set_moles(/datum/gas/nitryl,1000)
|
||||
G.set_moles(GAS_BZ,30)
|
||||
G.set_moles(GAS_PLASMA,1000)
|
||||
G.set_moles(GAS_TRITIUM,1000)
|
||||
G.set_moles(GAS_NITRYL,1000)
|
||||
G.set_volume(1000)
|
||||
G.set_temperature(12998000) // yeah, really
|
||||
|
||||
var/result = G.react()
|
||||
if(result != REACTING)
|
||||
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
|
||||
if(!G.get_moles(/datum/gas/stimulum) < 900)
|
||||
if(!G.get_moles(GAS_STIMULUM) < 900)
|
||||
return list("success" = FALSE, "message" = "Stimulum isn't being generated correctly!")
|
||||
return ..()
|
||||
|
||||
@@ -497,19 +594,19 @@
|
||||
|
||||
/datum/gas_reaction/nobliumformation/init_reqs()
|
||||
min_requirements = list(
|
||||
/datum/gas/nitrogen = 10,
|
||||
/datum/gas/tritium = 5,
|
||||
GAS_N2 = 10,
|
||||
GAS_TRITIUM = 5,
|
||||
"ENER" = NOBLIUM_FORMATION_ENERGY)
|
||||
|
||||
/datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air)
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/nob_formed = min((air.get_moles(/datum/gas/nitrogen)+air.get_moles(/datum/gas/tritium))/100,air.get_moles(/datum/gas/tritium)/10,air.get_moles(/datum/gas/nitrogen)/20)
|
||||
var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(air.get_moles(/datum/gas/bz),1)))
|
||||
if ((air.get_moles(/datum/gas/tritium) - 10*nob_formed < 0) || (air.get_moles(/datum/gas/nitrogen) - 20*nob_formed < 0))
|
||||
var/nob_formed = min((air.get_moles(GAS_N2)+air.get_moles(GAS_TRITIUM))/100,air.get_moles(GAS_TRITIUM)/10,air.get_moles(GAS_N2)/20)
|
||||
var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(air.get_moles(GAS_BZ),1)))
|
||||
if ((air.get_moles(GAS_TRITIUM) - 10*nob_formed < 0) || (air.get_moles(GAS_N2) - 20*nob_formed < 0))
|
||||
return NO_REACTION
|
||||
air.adjust_moles(/datum/gas/tritium, -10*nob_formed)
|
||||
air.adjust_moles(/datum/gas/nitrogen, -20*nob_formed)
|
||||
air.adjust_moles(/datum/gas/hypernoblium,nob_formed)
|
||||
air.adjust_moles(GAS_TRITIUM, -10*nob_formed)
|
||||
air.adjust_moles(GAS_N2, -20*nob_formed)
|
||||
air.adjust_moles(GAS_HYPERNOB,nob_formed)
|
||||
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, nob_formed*NOBLIUM_RESEARCH_AMOUNT)
|
||||
|
||||
@@ -520,8 +617,8 @@
|
||||
|
||||
/datum/gas_reaction/nobliumformation/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/nitrogen,100)
|
||||
G.set_moles(/datum/gas/tritium,500)
|
||||
G.set_moles(GAS_N2,100)
|
||||
G.set_moles(GAS_TRITIUM,500)
|
||||
G.set_volume(1000)
|
||||
G.set_temperature(5000000) // yeah, really
|
||||
var/result = G.react()
|
||||
@@ -540,18 +637,18 @@
|
||||
/datum/gas_reaction/miaster/init_reqs()
|
||||
min_requirements = list(
|
||||
"TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST+70,
|
||||
/datum/gas/miasma = MINIMUM_MOLE_COUNT
|
||||
GAS_MIASMA = MINIMUM_MOLE_COUNT
|
||||
)
|
||||
|
||||
/datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder)
|
||||
// As the name says it, it needs to be dry
|
||||
if(air.get_moles(/datum/gas/water_vapor) && air.get_moles(/datum/gas/water_vapor)/air.total_moles() > 0.1)
|
||||
if(air.get_moles(GAS_H2O) && air.get_moles(GAS_H2O)/air.total_moles() > 0.1)
|
||||
return
|
||||
|
||||
//Replace miasma with oxygen
|
||||
var/cleaned_air = min(air.get_moles(/datum/gas/miasma), 20 + (air.return_temperature() - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20)
|
||||
air.adjust_moles(/datum/gas/miasma, -cleaned_air)
|
||||
air.adjust_moles(/datum/gas/oxygen, cleaned_air)
|
||||
var/cleaned_air = min(air.get_moles(GAS_MIASMA), 20 + (air.return_temperature() - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20)
|
||||
air.adjust_moles(GAS_MIASMA, -cleaned_air)
|
||||
air.adjust_moles(GAS_O2, cleaned_air)
|
||||
|
||||
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
|
||||
air.set_temperature(air.return_temperature() + cleaned_air * 0.002)
|
||||
@@ -559,16 +656,16 @@
|
||||
|
||||
/datum/gas_reaction/miaster/test()
|
||||
var/datum/gas_mixture/G = new
|
||||
G.set_moles(/datum/gas/miasma,1)
|
||||
G.set_moles(GAS_MIASMA,1)
|
||||
G.set_volume(1000)
|
||||
G.set_temperature(450)
|
||||
var/result = G.react()
|
||||
if(result != REACTING)
|
||||
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
|
||||
G.clear()
|
||||
G.set_moles(/datum/gas/miasma,1)
|
||||
G.set_moles(GAS_MIASMA,1)
|
||||
G.set_temperature(450)
|
||||
G.set_moles(/datum/gas/water_vapor,0.5)
|
||||
G.set_moles(GAS_H2O,0.5)
|
||||
result = G.react()
|
||||
if(result != NO_REACTION)
|
||||
return list("success" = FALSE, "message" = "Miasma sterilization not stopping due to water vapor correctly!")
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
/datum/gas_mixture/heat_capacity() //joules per kelvin
|
||||
var/list/cached_gases = gases
|
||||
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
|
||||
var/list/cached_gasheats = GLOB.gas_data.specific_heats
|
||||
. = 0
|
||||
for(var/id in cached_gases)
|
||||
. += cached_gases[id] * cached_gasheats[id]
|
||||
|
||||
/datum/gas_mixture/turf/heat_capacity() // Same as above except vacuums return HEAT_CAPACITY_VACUUM
|
||||
var/list/cached_gases = gases
|
||||
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
|
||||
var/list/cached_gasheats = GLOB.gas_data.specific_heats
|
||||
for(var/id in cached_gases)
|
||||
. += cached_gases[id] * cached_gasheats[id]
|
||||
if(!.)
|
||||
@@ -56,20 +56,20 @@
|
||||
return gases[gas_type]
|
||||
/datum/gas_mixture/set_moles(gas_type, moles)
|
||||
gases[gas_type] = moles
|
||||
/datum/gas_mixture/scrub_into(datum/gas_mixture/target, list/gases)
|
||||
/datum/gas_mixture/scrub_into(datum/gas_mixture/target, ratio, list/gases)
|
||||
if(isnull(target))
|
||||
return FALSE
|
||||
|
||||
var/list/removed_gases = target.gases
|
||||
var/list/removed_gases = gases
|
||||
|
||||
//Filter it
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
var/list/filtered_gases = filtered_out.gases
|
||||
filtered_out.temperature = removed.temperature
|
||||
for(var/gas in filter_types & removed_gases)
|
||||
filtered_gases[gas] = removed_gases[gas]
|
||||
removed_gases[gas] = 0
|
||||
merge(filtered_out)
|
||||
filtered_gases[gas] = removed_gases[gas] * ratio
|
||||
removed_gases[gas] = removed_gases[gas] * (1 - ratio)
|
||||
target.merge(filtered_out)
|
||||
/datum/gas_mixture/mark_immutable()
|
||||
return
|
||||
/datum/gas_mixture/get_gases()
|
||||
@@ -208,7 +208,7 @@
|
||||
var/delta
|
||||
var/gas_heat_capacity
|
||||
//and also cache this shit rq because that results in sanic speed for reasons byond explanation
|
||||
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
|
||||
var/list/cached_gasheats = GLOB.gas_data.specific_heats
|
||||
//GAS TRANSFER
|
||||
for(var/id in cached_gases | sharer_gases) // transfer gases
|
||||
|
||||
|
||||
@@ -94,63 +94,63 @@
|
||||
var/list/TLV = list( // Breathable air.
|
||||
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
|
||||
"temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66),
|
||||
/datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
|
||||
/datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
|
||||
/datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
|
||||
/datum/gas/miasma = new/datum/tlv(-1, -1, 2, 5),
|
||||
/datum/gas/plasma = new/datum/tlv/dangerous,
|
||||
/datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
|
||||
/datum/gas/bz = new/datum/tlv/dangerous,
|
||||
/datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
|
||||
/datum/gas/water_vapor = new/datum/tlv/dangerous,
|
||||
/datum/gas/tritium = new/datum/tlv/dangerous,
|
||||
/datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
|
||||
/datum/gas/nitryl = new/datum/tlv/dangerous,
|
||||
/datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
|
||||
/datum/gas/methane = new/datum/tlv(-1, -1, 3, 6),
|
||||
/datum/gas/methyl_bromide = new/datum/tlv/dangerous
|
||||
GAS_O2 = new/datum/tlv(16, 19, 40, 50), // Partial pressure, kpa
|
||||
GAS_N2 = new/datum/tlv(-1, -1, 1000, 1000),
|
||||
GAS_CO2 = new/datum/tlv(-1, -1, 5, 10),
|
||||
GAS_MIASMA = new/datum/tlv(-1, -1, 2, 5),
|
||||
GAS_PLASMA = new/datum/tlv/dangerous,
|
||||
GAS_NITROUS = new/datum/tlv/dangerous,
|
||||
GAS_BZ = new/datum/tlv/dangerous,
|
||||
GAS_HYPERNOB = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
|
||||
GAS_H2O = new/datum/tlv/dangerous,
|
||||
GAS_TRITIUM = new/datum/tlv/dangerous,
|
||||
GAS_STIMULUM = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
|
||||
GAS_NITRYL = new/datum/tlv/dangerous,
|
||||
GAS_PLUOXIUM = new/datum/tlv(-1, -1, 5, 6), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
|
||||
GAS_METHANE = new/datum/tlv(-1, -1, 3, 6),
|
||||
GAS_METHYL_BROMIDE = new/datum/tlv/dangerous
|
||||
)
|
||||
|
||||
/obj/machinery/airalarm/server // No checks here.
|
||||
TLV = list(
|
||||
"pressure" = new/datum/tlv/no_checks,
|
||||
"temperature" = new/datum/tlv/no_checks,
|
||||
/datum/gas/oxygen = new/datum/tlv/no_checks,
|
||||
/datum/gas/nitrogen = new/datum/tlv/no_checks,
|
||||
/datum/gas/carbon_dioxide = new/datum/tlv/no_checks,
|
||||
/datum/gas/miasma = new/datum/tlv/no_checks,
|
||||
/datum/gas/plasma = new/datum/tlv/no_checks,
|
||||
/datum/gas/nitrous_oxide = new/datum/tlv/no_checks,
|
||||
/datum/gas/bz = new/datum/tlv/no_checks,
|
||||
/datum/gas/hypernoblium = new/datum/tlv/no_checks,
|
||||
/datum/gas/water_vapor = new/datum/tlv/no_checks,
|
||||
/datum/gas/tritium = new/datum/tlv/no_checks,
|
||||
/datum/gas/stimulum = new/datum/tlv/no_checks,
|
||||
/datum/gas/nitryl = new/datum/tlv/no_checks,
|
||||
/datum/gas/pluoxium = new/datum/tlv/no_checks,
|
||||
/datum/gas/methane = new/datum/tlv/no_checks,
|
||||
/datum/gas/methyl_bromide = new/datum/tlv/no_checks
|
||||
GAS_O2 = new/datum/tlv/no_checks,
|
||||
GAS_N2 = new/datum/tlv/no_checks,
|
||||
GAS_CO2 = new/datum/tlv/no_checks,
|
||||
GAS_MIASMA = new/datum/tlv/no_checks,
|
||||
GAS_PLASMA = new/datum/tlv/no_checks,
|
||||
GAS_NITROUS = new/datum/tlv/no_checks,
|
||||
GAS_BZ = new/datum/tlv/no_checks,
|
||||
GAS_HYPERNOB = new/datum/tlv/no_checks,
|
||||
GAS_H2O = new/datum/tlv/no_checks,
|
||||
GAS_TRITIUM = new/datum/tlv/no_checks,
|
||||
GAS_STIMULUM = new/datum/tlv/no_checks,
|
||||
GAS_NITRYL = new/datum/tlv/no_checks,
|
||||
GAS_PLUOXIUM = new/datum/tlv/no_checks,
|
||||
GAS_METHANE = new/datum/tlv/no_checks,
|
||||
GAS_METHYL_BROMIDE = new/datum/tlv/no_checks
|
||||
)
|
||||
|
||||
/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
|
||||
TLV = list(
|
||||
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
|
||||
"temperature" = new/datum/tlv(T0C-73.15, T0C-63.15, T0C, T0C+10),
|
||||
/datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
|
||||
/datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
|
||||
/datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
|
||||
/datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
|
||||
/datum/gas/plasma = new/datum/tlv/dangerous,
|
||||
/datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
|
||||
/datum/gas/bz = new/datum/tlv/dangerous,
|
||||
/datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
|
||||
/datum/gas/water_vapor = new/datum/tlv/dangerous,
|
||||
/datum/gas/tritium = new/datum/tlv/dangerous,
|
||||
/datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
|
||||
/datum/gas/nitryl = new/datum/tlv/dangerous,
|
||||
/datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
|
||||
/datum/gas/methane = new/datum/tlv(-1, -1, 3, 6),
|
||||
/datum/gas/methyl_bromide = new/datum/tlv/dangerous
|
||||
GAS_O2 = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
|
||||
GAS_N2 = new/datum/tlv(-1, -1, 1000, 1000),
|
||||
GAS_CO2 = new/datum/tlv(-1, -1, 5, 10),
|
||||
GAS_MIASMA = new/datum/tlv/(-1, -1, 2, 5),
|
||||
GAS_PLASMA = new/datum/tlv/dangerous,
|
||||
GAS_NITROUS = new/datum/tlv/dangerous,
|
||||
GAS_BZ = new/datum/tlv/dangerous,
|
||||
GAS_HYPERNOB = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
|
||||
GAS_H2O = new/datum/tlv/dangerous,
|
||||
GAS_TRITIUM = new/datum/tlv/dangerous,
|
||||
GAS_STIMULUM = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
|
||||
GAS_NITRYL = new/datum/tlv/dangerous,
|
||||
GAS_PLUOXIUM = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
|
||||
GAS_METHANE = new/datum/tlv(-1, -1, 3, 6),
|
||||
GAS_METHYL_BROMIDE = new/datum/tlv/dangerous
|
||||
)
|
||||
|
||||
/obj/machinery/airalarm/unlocked
|
||||
@@ -298,7 +298,7 @@
|
||||
continue
|
||||
cur_tlv = TLV[gas_id]
|
||||
data["environment_data"] += list(list(
|
||||
"name" = GLOB.meta_gas_names[gas_id],
|
||||
"name" = GLOB.gas_data.names[gas_id],
|
||||
"value" = environment.get_moles(gas_id) / total_moles * 100,
|
||||
"unit" = "%",
|
||||
"danger_level" = cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure)
|
||||
@@ -368,11 +368,11 @@
|
||||
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
|
||||
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
|
||||
|
||||
for(var/gas_id in GLOB.meta_gas_names)
|
||||
for(var/gas_id in GLOB.gas_data.names)
|
||||
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
|
||||
continue
|
||||
selected = TLV[gas_id]
|
||||
thresholds += list(list("name" = GLOB.meta_gas_names[gas_id], "settings" = list()))
|
||||
thresholds += list(list("name" = GLOB.gas_data.names[gas_id], "settings" = list()))
|
||||
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2))
|
||||
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1))
|
||||
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1))
|
||||
@@ -532,7 +532,7 @@
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma),
|
||||
"set_filters" = list(GAS_CO2, GAS_MIASMA),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 0,
|
||||
))
|
||||
@@ -547,19 +547,19 @@
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"set_filters" = list(
|
||||
/datum/gas/carbon_dioxide,
|
||||
/datum/gas/miasma,
|
||||
/datum/gas/plasma,
|
||||
/datum/gas/water_vapor,
|
||||
/datum/gas/hypernoblium,
|
||||
/datum/gas/nitrous_oxide,
|
||||
/datum/gas/nitryl,
|
||||
/datum/gas/tritium,
|
||||
/datum/gas/bz,
|
||||
/datum/gas/stimulum,
|
||||
/datum/gas/pluoxium,
|
||||
/datum/gas/methane,
|
||||
/datum/gas/methyl_bromide
|
||||
GAS_CO2,
|
||||
GAS_MIASMA,
|
||||
GAS_PLASMA,
|
||||
GAS_H2O,
|
||||
GAS_HYPERNOB,
|
||||
GAS_NITROUS,
|
||||
GAS_NITRYL,
|
||||
GAS_TRITIUM,
|
||||
GAS_BZ,
|
||||
GAS_STIMULUM,
|
||||
GAS_PLUOXIUM,
|
||||
GAS_METHANE,
|
||||
GAS_METHYL_BROMIDE
|
||||
),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 1,
|
||||
@@ -587,7 +587,7 @@
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma),
|
||||
"set_filters" = list(GAS_CO2, GAS_MIASMA),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 0,
|
||||
))
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
var/construction_type
|
||||
var/pipe_state //icon_state as a pipe item
|
||||
var/on = FALSE
|
||||
var/interacts_with_air = FALSE
|
||||
|
||||
/obj/machinery/atmospherics/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -57,7 +58,10 @@
|
||||
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
|
||||
..()
|
||||
if(process)
|
||||
SSair.atmos_machinery += src
|
||||
if(interacts_with_air)
|
||||
SSair.atmos_air_machinery += src
|
||||
else
|
||||
SSair.atmos_machinery += src
|
||||
SetInitDirections()
|
||||
|
||||
/obj/machinery/atmospherics/Destroy()
|
||||
@@ -65,6 +69,7 @@
|
||||
nullifyNode(i)
|
||||
|
||||
SSair.atmos_machinery -= src
|
||||
SSair.atmos_air_machinery -= src
|
||||
SSair.pipenets_needing_rebuilt -= src
|
||||
|
||||
dropContents()
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
desc = "Has a valve and pump attached to it. There are two ports."
|
||||
|
||||
level = 1
|
||||
|
||||
interacts_with_air = TRUE
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
@@ -69,12 +72,7 @@
|
||||
if(air1.return_temperature() > 0)
|
||||
var/transfer_moles = pressure_delta*environment.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
//Removed can be null if there is no atmosphere in air1
|
||||
if(!removed)
|
||||
return
|
||||
|
||||
loc.assume_air(removed)
|
||||
loc.assume_air_moles(air1, transfer_moles)
|
||||
air_update_turf()
|
||||
|
||||
var/datum/pipeline/parent1 = parents[1]
|
||||
@@ -90,11 +88,7 @@
|
||||
moles_delta = min(moles_delta, (input_pressure_min - air2.return_pressure()) * our_multiplier)
|
||||
|
||||
if(moles_delta > 0)
|
||||
var/datum/gas_mixture/removed = loc.remove_air(moles_delta)
|
||||
if (isnull(removed)) // in space
|
||||
return
|
||||
|
||||
air2.merge(removed)
|
||||
loc.transfer_air(air2, moles_delta)
|
||||
air_update_turf()
|
||||
|
||||
var/datum/pipeline/parent2 = parents[2]
|
||||
|
||||
@@ -81,9 +81,7 @@
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles = pressure_delta*air2.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
air2.merge(removed)
|
||||
air1.transfer_to(air2,transfer_moles)
|
||||
|
||||
update_parents()
|
||||
|
||||
|
||||
@@ -67,9 +67,7 @@
|
||||
|
||||
var/transfer_ratio = transfer_rate/air1.return_volume()
|
||||
|
||||
var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
|
||||
|
||||
air2.merge(removed)
|
||||
air1.transfer_ratio_to(air2,transfer_ratio)
|
||||
|
||||
update_parents()
|
||||
|
||||
|
||||
@@ -120,14 +120,9 @@
|
||||
times_lost++
|
||||
var/shared_loss = lost/times_lost
|
||||
|
||||
var/datum/gas_mixture/to_release
|
||||
for(var/i in 1 to device_type)
|
||||
var/datum/gas_mixture/air = airs[i]
|
||||
if(!to_release)
|
||||
to_release = air.remove(shared_loss)
|
||||
continue
|
||||
to_release.merge(air.remove(shared_loss))
|
||||
T.assume_air(to_release)
|
||||
T.assume_air_moles(air, shared_loss)
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/machinery/atmospherics/components/proc/safe_input(var/title, var/text, var/default_set)
|
||||
|
||||
@@ -98,33 +98,11 @@
|
||||
//Actually transfer the gas
|
||||
|
||||
if(transfer_ratio > 0)
|
||||
var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
|
||||
|
||||
if(!removed)
|
||||
return
|
||||
|
||||
var/filtering = TRUE
|
||||
if(!ispath(filter_type))
|
||||
if(filter_type)
|
||||
filter_type = gas_id2path(filter_type) //support for mappers so they don't need to type out paths
|
||||
else
|
||||
filtering = FALSE
|
||||
|
||||
if(filtering && removed.get_moles(filter_type))
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
|
||||
filtered_out.set_temperature(removed.return_temperature())
|
||||
filtered_out.set_moles(filter_type, removed.get_moles(filter_type))
|
||||
|
||||
removed.set_moles(filter_type, 0)
|
||||
|
||||
var/datum/gas_mixture/target = (air2.return_pressure() < 9000 ? air2 : air1)
|
||||
target.merge(filtered_out)
|
||||
|
||||
if(filter_type && air2.return_pressure() <= 9000)
|
||||
air1.scrub_into(air2, transfer_ratio, list(filter_type))
|
||||
if(air3.return_pressure() <= 9000)
|
||||
air3.merge(removed)
|
||||
else
|
||||
air1.merge(removed) // essentially just leaving it in
|
||||
air1.transfer_ratio_to(air3, transfer_ratio)
|
||||
|
||||
update_parents()
|
||||
|
||||
@@ -145,9 +123,9 @@
|
||||
data["max_rate"] = round(MAX_TRANSFER_RATE)
|
||||
|
||||
data["filter_types"] = list()
|
||||
data["filter_types"] += list(list("name" = "Nothing", "path" = "", "selected" = !filter_type))
|
||||
for(var/path in GLOB.meta_gas_ids)
|
||||
data["filter_types"] += list(list("name" = GLOB.meta_gas_names[path], "id" = GLOB.meta_gas_ids[path], "selected" = (path == gas_id2path(filter_type))))
|
||||
data["filter_types"] += list(list("name" = "Nothing", "id" = "", "selected" = !filter_type))
|
||||
for(var/id in GLOB.gas_data.ids)
|
||||
data["filter_types"] += list(list("name" = GLOB.gas_data.names[id], "id" = id, "selected" = (id == filter_type)))
|
||||
|
||||
return data
|
||||
|
||||
@@ -177,10 +155,10 @@
|
||||
if("filter")
|
||||
filter_type = null
|
||||
var/filter_name = "nothing"
|
||||
var/gas = gas_id2path(params["mode"])
|
||||
if(gas in GLOB.meta_gas_names)
|
||||
var/gas = params["mode"]
|
||||
if(gas in GLOB.gas_data.names)
|
||||
filter_type = gas
|
||||
filter_name = GLOB.meta_gas_names[gas]
|
||||
filter_name = GLOB.gas_data.names[gas]
|
||||
investigate_log("was set to filter [filter_name] by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -110,14 +110,12 @@
|
||||
//Actually transfer the gas
|
||||
|
||||
if(transfer_moles1)
|
||||
var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1)
|
||||
air3.merge(removed1)
|
||||
air1.transfer_to(air3, transfer_moles1)
|
||||
var/datum/pipeline/parent1 = parents[1]
|
||||
parent1.update = TRUE
|
||||
|
||||
if(transfer_moles2)
|
||||
var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2)
|
||||
air3.merge(removed2)
|
||||
air2.transfer_to(air3, transfer_moles2)
|
||||
var/datum/pipeline/parent2 = parents[2]
|
||||
parent2.update = TRUE
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
|
||||
beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents.
|
||||
beaker.reagents.reaction(occupant, VAPOR)
|
||||
air1.adjust_moles(/datum/gas/oxygen, -max(0,air1.get_moles(/datum/gas/oxygen) - 2 / efficiency)) //Let's use gas for this
|
||||
air1.adjust_moles(GAS_O2, -max(0,air1.get_moles(GAS_O2) - 2 / efficiency)) //Let's use gas for this
|
||||
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
|
||||
reagent_transfer = 0
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
|
||||
if(!nodes[1] || !airs[1] || air1.get_moles(/datum/gas/oxygen) < 5) // Turn off if the machine won't work.
|
||||
if(!nodes[1] || !airs[1] || air1.get_moles(GAS_O2) < 5) // Turn off if the machine won't work.
|
||||
on = FALSE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
level = 1
|
||||
interacts_with_air = TRUE
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
|
||||
pipe_state = "injector"
|
||||
@@ -65,11 +66,7 @@
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
|
||||
if(air_contents.return_temperature() > 0)
|
||||
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
loc.assume_air_ratio(air_contents, volume_rate / air_contents.return_volume())
|
||||
air_update_turf()
|
||||
|
||||
update_parents()
|
||||
@@ -84,9 +81,7 @@
|
||||
injecting = 1
|
||||
|
||||
if(air_contents.return_temperature() > 0)
|
||||
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
loc.assume_air(removed)
|
||||
loc.assume_air_ratio(air_contents, volume_rate / air_contents.return_volume())
|
||||
update_parents()
|
||||
|
||||
flick("inje_inject", src)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
can_unwrench = TRUE
|
||||
|
||||
level = 1
|
||||
interacts_with_air = TRUE
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
|
||||
pipe_state = "pvent"
|
||||
@@ -29,23 +30,10 @@
|
||||
var/pressure_delta = abs(external_pressure - internal_pressure)
|
||||
|
||||
if(pressure_delta > 0.5)
|
||||
if(external_pressure < internal_pressure)
|
||||
var/air_temperature = (external.return_temperature() > 0) ? external.return_temperature() : internal.return_temperature()
|
||||
var/transfer_moles = (pressure_delta * external.return_volume()) / (air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
var/datum/gas_mixture/removed = internal.remove(transfer_moles)
|
||||
external.merge(removed)
|
||||
else
|
||||
var/air_temperature = (internal.return_temperature() > 0) ? internal.return_temperature() : external.return_temperature()
|
||||
var/transfer_moles = (pressure_delta * internal.return_volume()) / (air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
transfer_moles = min(transfer_moles, external.total_moles() * internal.return_volume() / external.return_volume())
|
||||
var/datum/gas_mixture/removed = external.remove(transfer_moles)
|
||||
if(isnull(removed))
|
||||
return
|
||||
internal.merge(removed)
|
||||
|
||||
equalize_all_gases_in_list(list(internal,external))
|
||||
active = TRUE
|
||||
|
||||
active = internal.temperature_share(external, OPEN_HEAT_TRANSFER_COEFFICIENT) ? TRUE : active
|
||||
active = internal.temperature_share(external, OPEN_HEAT_TRANSFER_COEFFICIENT) || active
|
||||
|
||||
if(active)
|
||||
air_update_turf()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
icon_state = "relief_valve-e-map"
|
||||
can_unwrench = TRUE
|
||||
interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
|
||||
interacts_with_air = TRUE
|
||||
var/opened = FALSE
|
||||
var/open_pressure = ONE_ATMOSPHERE * 3
|
||||
var/close_pressure = ONE_ATMOSPHERE
|
||||
@@ -49,14 +50,11 @@
|
||||
else if(!opened && our_pressure >= open_pressure)
|
||||
opened = TRUE
|
||||
update_icon_nopipes()
|
||||
if(opened && air_contents.return_temperature() > 0)
|
||||
if(opened)
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
var/pressure_delta = our_pressure - environment.return_pressure()
|
||||
var/transfer_moles = pressure_delta*200/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
if(transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
var/pressure_delta = abs(our_pressure - environment.return_pressure())
|
||||
if(pressure_delta > 0.1)
|
||||
equalize_all_gases_in_list(list(air_contents,environment))
|
||||
air_update_turf()
|
||||
|
||||
update_parents()
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
air_contents.set_volume(volume)
|
||||
air_contents.set_temperature(T20C)
|
||||
if(gas_type)
|
||||
air_contents.set_moles(gas_type, AIR_CONTENTS)
|
||||
name = "[name] ([GLOB.meta_gas_names[gas_type]])"
|
||||
air_contents.set_moles(gas_type,AIR_CONTENTS)
|
||||
name = "[name] ([GLOB.gas_data.names[gas_type]])"
|
||||
setPipingLayer(piping_layer)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/air
|
||||
@@ -32,30 +32,30 @@
|
||||
/obj/machinery/atmospherics/components/unary/tank/air/New()
|
||||
..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
air_contents.set_moles(/datum/gas/oxygen, AIR_CONTENTS * 0.21)
|
||||
air_contents.set_moles(/datum/gas/nitrogen, AIR_CONTENTS * 0.79)
|
||||
air_contents.set_moles(GAS_O2, AIR_CONTENTS * 0.21)
|
||||
air_contents.set_moles(GAS_N2, AIR_CONTENTS * 0.79)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide
|
||||
gas_type = /datum/gas/carbon_dioxide
|
||||
gas_type = GAS_CO2
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/toxins
|
||||
icon_state = "orange"
|
||||
gas_type = /datum/gas/plasma
|
||||
gas_type = GAS_PLASMA
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/nitrogen
|
||||
icon_state = "red"
|
||||
gas_type = /datum/gas/nitrogen
|
||||
gas_type = GAS_N2
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/oxygen
|
||||
icon_state = "blue"
|
||||
gas_type = /datum/gas/oxygen
|
||||
gas_type = GAS_O2
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/nitrous
|
||||
icon_state = "red_white"
|
||||
gas_type = /datum/gas/nitrous_oxide
|
||||
gas_type = GAS_NITROUS
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/bz
|
||||
gas_type = /datum/gas/bz
|
||||
gas_type = GAS_BZ
|
||||
|
||||
// /obj/machinery/atmospherics/components/unary/tank/freon
|
||||
// icon_state = "blue"
|
||||
@@ -75,17 +75,17 @@
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/hypernoblium
|
||||
icon_state = "blue"
|
||||
gas_type = /datum/gas/hypernoblium
|
||||
gas_type = GAS_HYPERNOB
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/miasma
|
||||
gas_type = /datum/gas/miasma
|
||||
gas_type = GAS_MIASMA
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/nitryl
|
||||
gas_type = /datum/gas/nitryl
|
||||
gas_type = GAS_NITRYL
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/pluoxium
|
||||
icon_state = "blue"
|
||||
gas_type = /datum/gas/pluoxium
|
||||
gas_type = GAS_PLUOXIUM
|
||||
|
||||
// /obj/machinery/atmospherics/components/unary/tank/proto_nitrate
|
||||
// icon_state = "red"
|
||||
@@ -93,14 +93,14 @@
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/stimulum
|
||||
icon_state = "red"
|
||||
gas_type = /datum/gas/stimulum
|
||||
gas_type = GAS_STIMULUM
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/tritium
|
||||
gas_type = /datum/gas/tritium
|
||||
gas_type = GAS_TRITIUM
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/water_vapor
|
||||
icon_state = "grey"
|
||||
gas_type = /datum/gas/water_vapor
|
||||
gas_type = GAS_H2O
|
||||
|
||||
// /obj/machinery/atmospherics/components/unary/tank/zauker
|
||||
// gas_type = /datum/gas/zauker
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
level = 1
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
|
||||
interacts_with_air = TRUE
|
||||
|
||||
var/id_tag = null
|
||||
var/pump_direction = RELEASING
|
||||
|
||||
@@ -107,9 +109,7 @@
|
||||
if(air_contents.return_temperature() > 0)
|
||||
var/transfer_moles = pressure_delta*environment.return_volume()/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
loc.assume_air_moles(air_contents, transfer_moles)
|
||||
air_update_turf()
|
||||
|
||||
else // external -> internal
|
||||
@@ -122,11 +122,7 @@
|
||||
moles_delta = min(moles_delta, (internal_pressure_bound - air_contents.return_pressure()) * our_multiplier)
|
||||
|
||||
if(moles_delta > 0)
|
||||
var/datum/gas_mixture/removed = loc.remove_air(moles_delta)
|
||||
if (isnull(removed)) // in space
|
||||
return
|
||||
|
||||
air_contents.merge(removed)
|
||||
loc.transfer_air(air_contents, moles_delta)
|
||||
air_update_turf()
|
||||
update_parents()
|
||||
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
level = 1
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
|
||||
interacts_with_air = TRUE
|
||||
|
||||
var/id_tag = null
|
||||
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
|
||||
|
||||
var/filter_types = list(/datum/gas/carbon_dioxide)
|
||||
var/filter_types = list(GAS_CO2)
|
||||
var/volume_rate = 200
|
||||
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
|
||||
var/list/turf/adjacent_turfs = list()
|
||||
@@ -33,11 +35,6 @@
|
||||
if(!id_tag)
|
||||
id_tag = assign_uid_vents()
|
||||
|
||||
for(var/f in filter_types)
|
||||
if(istext(f))
|
||||
filter_types -= f
|
||||
filter_types += gas_id2path(f)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
|
||||
var/area/A = get_base_area(src)
|
||||
if (A)
|
||||
@@ -97,8 +94,8 @@
|
||||
return FALSE
|
||||
|
||||
var/list/f_types = list()
|
||||
for(var/path in GLOB.meta_gas_ids)
|
||||
f_types += list(list("gas_id" = GLOB.meta_gas_ids[path], "gas_name" = GLOB.meta_gas_names[path], "enabled" = (path in filter_types)))
|
||||
for(var/id in GLOB.gas_data.ids)
|
||||
f_types += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.names[id], "enabled" = (id in filter_types)))
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
@@ -150,32 +147,17 @@
|
||||
var/datum/gas_mixture/environment = tile.return_air()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
|
||||
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE)
|
||||
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE || !islist(filter_types))
|
||||
return FALSE
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
var/transfer_moles = min(1, volume_rate/environment.return_volume())*environment.total_moles()
|
||||
environment.scrub_into(air_contents, volume_rate/environment.return_volume(), filter_types)
|
||||
|
||||
//Take a gas sample
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
//Nothing left to remove from the tile
|
||||
if(isnull(removed))
|
||||
return FALSE
|
||||
|
||||
removed.scrub_into(air_contents, filter_types)
|
||||
|
||||
//Remix the resulting gases
|
||||
tile.assume_air(removed)
|
||||
tile.air_update_turf()
|
||||
|
||||
else //Just siphoning all air
|
||||
|
||||
var/transfer_moles = environment.total_moles()*(volume_rate/environment.return_volume())
|
||||
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
air_contents.merge(removed)
|
||||
environment.transfer_ratio_to(air_contents, volume_rate/environment.return_volume())
|
||||
tile.air_update_turf()
|
||||
|
||||
update_parents()
|
||||
@@ -222,12 +204,12 @@
|
||||
investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
|
||||
|
||||
if("toggle_filter" in signal.data)
|
||||
filter_types ^= gas_id2path(signal.data["toggle_filter"])
|
||||
filter_types ^= signal.data["toggle_filter"]
|
||||
|
||||
if("set_filters" in signal.data)
|
||||
filter_types = list()
|
||||
for(var/gas in signal.data["set_filters"])
|
||||
filter_types += gas_id2path(gas)
|
||||
filter_types += gas
|
||||
|
||||
if("init" in signal.data)
|
||||
name = signal.data["init"]
|
||||
|
||||
@@ -241,25 +241,4 @@
|
||||
|
||||
/datum/pipeline/proc/reconcile_air()
|
||||
var/list/datum/gas_mixture/GL = get_all_connected_airs()
|
||||
|
||||
var/total_thermal_energy = 0
|
||||
var/total_heat_capacity = 0
|
||||
var/datum/gas_mixture/total_gas_mixture = new(0)
|
||||
|
||||
for(var/i in GL)
|
||||
var/datum/gas_mixture/G = i
|
||||
total_gas_mixture.set_volume(total_gas_mixture.return_volume() + G.return_volume())
|
||||
|
||||
total_gas_mixture.merge(G)
|
||||
|
||||
total_thermal_energy += G.thermal_energy()
|
||||
total_heat_capacity += G.heat_capacity()
|
||||
|
||||
total_gas_mixture.set_temperature(total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0)
|
||||
|
||||
if(total_gas_mixture.return_volume() > 0)
|
||||
//Update individual gas_mixtures by volume ratio
|
||||
for(var/i in GL)
|
||||
var/datum/gas_mixture/G = i
|
||||
G.copy_from(total_gas_mixture)
|
||||
G.multiply(G.return_volume()/total_gas_mixture.return_volume())
|
||||
equalize_all_gases_in_list(GL)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
icon_state = "miner"
|
||||
density = FALSE
|
||||
resistance_flags = INDESTRUCTIBLE|ACID_PROOF|FIRE_PROOF
|
||||
interacts_with_air = TRUE
|
||||
var/spawn_id = null
|
||||
var/spawn_temp = T20C
|
||||
var/spawn_mol = MOLES_CELLSTANDARD * 10
|
||||
@@ -117,7 +118,7 @@
|
||||
on_overlay.color = overlay_color
|
||||
add_overlay(on_overlay)
|
||||
|
||||
/obj/machinery/atmospherics/miner/process()
|
||||
/obj/machinery/atmospherics/miner/process_atmos()
|
||||
update_power()
|
||||
check_operation()
|
||||
if(active && !broken)
|
||||
@@ -144,34 +145,34 @@
|
||||
/obj/machinery/atmospherics/miner/n2o
|
||||
name = "\improper N2O Gas Miner"
|
||||
overlay_color = "#FFCCCC"
|
||||
spawn_id = /datum/gas/nitrous_oxide
|
||||
spawn_id = GAS_NITROUS
|
||||
|
||||
/obj/machinery/atmospherics/miner/nitrogen
|
||||
name = "\improper N2 Gas Miner"
|
||||
overlay_color = "#CCFFCC"
|
||||
spawn_id = /datum/gas/nitrogen
|
||||
spawn_id = GAS_N2
|
||||
|
||||
/obj/machinery/atmospherics/miner/oxygen
|
||||
name = "\improper O2 Gas Miner"
|
||||
overlay_color = "#007FFF"
|
||||
spawn_id = /datum/gas/oxygen
|
||||
spawn_id = GAS_O2
|
||||
|
||||
/obj/machinery/atmospherics/miner/toxins
|
||||
name = "\improper Plasma Gas Miner"
|
||||
overlay_color = "#FF0000"
|
||||
spawn_id = /datum/gas/plasma
|
||||
spawn_id = GAS_PLASMA
|
||||
|
||||
/obj/machinery/atmospherics/miner/carbon_dioxide
|
||||
name = "\improper CO2 Gas Miner"
|
||||
overlay_color = "#CDCDCD"
|
||||
spawn_id = /datum/gas/carbon_dioxide
|
||||
spawn_id = GAS_CO2
|
||||
|
||||
/obj/machinery/atmospherics/miner/bz
|
||||
name = "\improper BZ Gas Miner"
|
||||
overlay_color = "#FAFF00"
|
||||
spawn_id = /datum/gas/bz
|
||||
spawn_id = GAS_BZ
|
||||
|
||||
/obj/machinery/atmospherics/miner/water_vapor
|
||||
name = "\improper Water Vapor Gas Miner"
|
||||
overlay_color = "#99928E"
|
||||
spawn_id = /datum/gas/water_vapor
|
||||
spawn_id = GAS_H2O
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
buckle_lying = 1
|
||||
var/icon_temperature = T20C //stop small changes in temperature causing icon refresh
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF
|
||||
interacts_with_air = TRUE
|
||||
|
||||
/obj/machinery/atmospherics/pipe/heat_exchanging/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
/obj/machinery/atmospherics/pipe/remove_air(amount)
|
||||
return parent.air.remove(amount)
|
||||
|
||||
/obj/machinery/atmospherics/pipe/remove_air_ratio(ratio)
|
||||
return parent.air.remove_ratio(ratio)
|
||||
|
||||
/obj/machinery/atmospherics/pipe/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/pipe_meter))
|
||||
var/obj/item/pipe_meter/meter = W
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
// var/pressure_limit = 50000
|
||||
|
||||
var/temperature_resistance = 1000 + T0C
|
||||
var/starter_temp
|
||||
var/starter_temp = T20C
|
||||
// Prototype vars
|
||||
var/prototype = FALSE
|
||||
var/valve_timer = null
|
||||
@@ -74,37 +74,37 @@
|
||||
name = "n2 canister"
|
||||
desc = "Nitrogen. Reportedly useful for something."
|
||||
icon_state = "red"
|
||||
gas_type = /datum/gas/nitrogen
|
||||
gas_type = GAS_N2
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/oxygen
|
||||
name = "o2 canister"
|
||||
desc = "Oxygen. Necessary for human life."
|
||||
icon_state = "blue"
|
||||
gas_type = /datum/gas/oxygen
|
||||
gas_type = GAS_O2
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
|
||||
name = "co2 canister"
|
||||
desc = "Carbon dioxide. What the fuck is carbon dioxide?"
|
||||
icon_state = "black"
|
||||
gas_type = /datum/gas/carbon_dioxide
|
||||
gas_type = GAS_CO2
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/toxins
|
||||
name = "plasma canister"
|
||||
desc = "Plasma. The reason YOU are here. Highly toxic."
|
||||
icon_state = "orange"
|
||||
gas_type = /datum/gas/plasma
|
||||
gas_type = GAS_PLASMA
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/bz
|
||||
name = "\improper BZ canister"
|
||||
desc = "BZ. A powerful hallucinogenic nerve agent."
|
||||
icon_state = "purple"
|
||||
gas_type = /datum/gas/bz
|
||||
gas_type = GAS_BZ
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
|
||||
name = "n2o canister"
|
||||
desc = "Nitrous oxide. Known to cause drowsiness."
|
||||
icon_state = "redws"
|
||||
gas_type = /datum/gas/nitrous_oxide
|
||||
gas_type = GAS_NITROUS
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/air
|
||||
name = "air canister"
|
||||
@@ -115,57 +115,57 @@
|
||||
name = "tritium canister"
|
||||
desc = "Tritium. Inhalation might cause irradiation."
|
||||
icon_state = "green"
|
||||
gas_type = /datum/gas/tritium
|
||||
gas_type = GAS_TRITIUM
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/nob
|
||||
name = "hyper-noblium canister"
|
||||
desc = "Hyper-Noblium. More noble than all other gases."
|
||||
icon_state = "freon"
|
||||
gas_type = /datum/gas/hypernoblium
|
||||
gas_type = GAS_HYPERNOB
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/nitryl
|
||||
name = "nitryl canister"
|
||||
desc = "Nitryl. Feels great 'til the acid eats your lungs."
|
||||
icon_state = "brown"
|
||||
gas_type = /datum/gas/nitryl
|
||||
gas_type = GAS_NITRYL
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/stimulum
|
||||
name = "stimulum canister"
|
||||
desc = "Stimulum. High energy gas, high energy people."
|
||||
icon_state = "darkpurple"
|
||||
gas_type = /datum/gas/stimulum
|
||||
gas_type = GAS_STIMULUM
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/pluoxium
|
||||
name = "pluoxium canister"
|
||||
desc = "Pluoxium. Like oxygen, but more bang for your buck."
|
||||
icon_state = "darkblue"
|
||||
gas_type = /datum/gas/pluoxium
|
||||
gas_type = GAS_PLUOXIUM
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/water_vapor
|
||||
name = "water vapor canister"
|
||||
desc = "Water vapor. We get it, you vape."
|
||||
icon_state = "water_vapor"
|
||||
gas_type = /datum/gas/water_vapor
|
||||
gas_type = GAS_H2O
|
||||
filled = 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/miasma
|
||||
name = "miasma canister"
|
||||
desc = "Miasma. Makes you wish your nose were blocked."
|
||||
icon_state = "miasma"
|
||||
gas_type = /datum/gas/miasma
|
||||
gas_type = GAS_MIASMA
|
||||
filled = 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/methane
|
||||
name = "methane canister"
|
||||
desc = "Methane. The simplest of hydrocarbons. Non-toxic but highly flammable."
|
||||
icon_state = "greyblackred"
|
||||
gas_type = /datum/gas/methane
|
||||
gas_type = GAS_METHANE
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/methyl_bromide
|
||||
name = "methyl bromide canister"
|
||||
desc = "Methyl bromide. A potent toxin to most, essential for the Kharmaan to live."
|
||||
icon_state = "purplecyan"
|
||||
gas_type = /datum/gas/methyl_bromide
|
||||
gas_type = GAS_METHYL_BROMIDE
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/get_time_left()
|
||||
if(timing)
|
||||
@@ -198,7 +198,7 @@
|
||||
name = "prototype canister"
|
||||
desc = "A prototype canister for a prototype bike, what could go wrong?"
|
||||
icon_state = "proto"
|
||||
gas_type = /datum/gas/oxygen
|
||||
gas_type = GAS_O2
|
||||
filled = 1
|
||||
release_pressure = ONE_ATMOSPHERE*2
|
||||
|
||||
@@ -217,13 +217,13 @@
|
||||
// air_contents.add_gas(gas_type)
|
||||
if(starter_temp)
|
||||
air_contents.set_temperature(starter_temp)
|
||||
if(!air_contents.return_volume())
|
||||
CRASH("Auxtools is failing somehow! Gas with pointer [air_contents._extools_pointer_gasmixture] is not valid.")
|
||||
air_contents.set_moles(gas_type,(maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
if(starter_temp)
|
||||
air_contents.set_temperature(starter_temp)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/air/create_gas()
|
||||
air_contents.set_moles(/datum/gas/oxygen, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
air_contents.set_moles(/datum/gas/nitrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
air_contents.set_moles(GAS_O2, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
air_contents.set_moles(GAS_N2, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/update_icon_state()
|
||||
if(stat & BROKEN)
|
||||
@@ -287,9 +287,8 @@
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/proc/canister_break()
|
||||
disconnect()
|
||||
var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/T = get_turf(src)
|
||||
T.assume_air(expelled_gas)
|
||||
T.assume_air(air_contents)
|
||||
air_update_turf()
|
||||
|
||||
obj_break()
|
||||
@@ -434,10 +433,10 @@
|
||||
var/list/danger = list()
|
||||
for(var/id in air_contents.get_gases())
|
||||
var/gas = air_contents.get_moles(id)
|
||||
if(!GLOB.meta_gas_dangers[id])
|
||||
if(!GLOB.gas_data.flags[id] & GAS_FLAG_DANGEROUS)
|
||||
continue
|
||||
if(gas > (GLOB.meta_gas_visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
|
||||
danger[GLOB.meta_gas_names[id]] = gas //ex. "plasma" = 20
|
||||
if(gas > (GLOB.gas_data.visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
|
||||
danger[GLOB.gas_data.names[id]] = gas //ex. "plasma" = 20
|
||||
|
||||
if(danger.len)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] opened a canister that contains the following at [ADMIN_VERBOSEJMP(src)]:")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/obj/machinery/portable_atmospherics/New()
|
||||
..()
|
||||
SSair.atmos_machinery += src
|
||||
SSair.atmos_air_machinery += src
|
||||
|
||||
air_contents = new(volume)
|
||||
air_contents.set_temperature(T20C)
|
||||
@@ -24,7 +24,7 @@
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/Destroy()
|
||||
SSair.atmos_machinery -= src
|
||||
SSair.atmos_air_machinery -= src
|
||||
|
||||
disconnect()
|
||||
qdel(air_contents)
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
if("power")
|
||||
on = !on
|
||||
if(on && !holding)
|
||||
var/plasma = air_contents.get_moles(/datum/gas/plasma)
|
||||
var/n2o = air_contents.get_moles(/datum/gas/nitrous_oxide)
|
||||
var/plasma = air_contents.get_moles(GAS_PLASMA)
|
||||
var/n2o = air_contents.get_moles(GAS_NITROUS)
|
||||
if(n2o || plasma)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]")
|
||||
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/use_overlays = TRUE
|
||||
volume = 1000
|
||||
|
||||
var/list/scrubbing = list(/datum/gas/plasma, /datum/gas/carbon_dioxide, /datum/gas/nitrous_oxide, /datum/gas/bz, /datum/gas/nitryl, /datum/gas/tritium, /datum/gas/hypernoblium, /datum/gas/water_vapor)
|
||||
var/list/scrubbing = list(GAS_PLASMA, GAS_CO2, GAS_NITROUS, GAS_BZ, GAS_NITRYL, GAS_TRITIUM, GAS_HYPERNOB, GAS_H2O)
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
@@ -42,14 +42,7 @@
|
||||
scrub(T.return_air())
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
|
||||
var/transfer_moles = min(1, volume_rate / mixture.return_volume()) * mixture.total_moles()
|
||||
|
||||
var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter.
|
||||
if(!filtering)
|
||||
return
|
||||
|
||||
filtering.scrub_into(air_contents,scrubbing)
|
||||
mixture.merge(filtering) // Returned the cleaned gas.
|
||||
mixture.scrub_into(air_contents, volume_rate / mixture.return_volume(), scrubbing)
|
||||
if(!holding)
|
||||
air_update_turf()
|
||||
|
||||
@@ -76,8 +69,8 @@
|
||||
|
||||
data["id_tag"] = -1 //must be defined in order to reuse code between portable and vent scrubbers
|
||||
data["filter_types"] = list()
|
||||
for(var/path in GLOB.meta_gas_ids)
|
||||
data["filter_types"] += list(list("gas_id" = GLOB.meta_gas_ids[path], "gas_name" = GLOB.meta_gas_names[path], "enabled" = (path in scrubbing)))
|
||||
for(var/id in GLOB.gas_data.ids)
|
||||
data["filter_types"] += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.names[id], "enabled" = (id in scrubbing)))
|
||||
|
||||
if(holding)
|
||||
data["holding"] = list()
|
||||
@@ -100,7 +93,7 @@
|
||||
holding = null
|
||||
. = TRUE
|
||||
if("toggle_filter")
|
||||
scrubbing ^= gas_id2path(params["val"])
|
||||
scrubbing ^= params["val"]
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -156,13 +156,13 @@
|
||||
/turf/open/floor/plasteel/dark/snowdin
|
||||
initial_gas_mix = FROZEN_ATMOS
|
||||
planetary_atmos = 1
|
||||
temperature = 180
|
||||
initial_temperature = 180
|
||||
|
||||
/turf/open/lava/plasma
|
||||
name = "liquid plasma"
|
||||
desc = "A flowing stream of chilled liquid plasma. You probably shouldn't get in."
|
||||
icon_state = "liquidplasma"
|
||||
initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"
|
||||
initial_gas_mix = "n2=82;plasma=24;TEMP=120"
|
||||
baseturfs = /turf/open/lava/plasma
|
||||
slowdown = 2
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
reward = 7500
|
||||
wanted_types = list(/obj/item/tank)
|
||||
var/moles_required = 20 // A full tank is 28 moles, but CentCom ignores that fact.
|
||||
var/gas_type = /datum/gas/pluoxium
|
||||
var/gas_type = GAS_PLUOXIUM
|
||||
|
||||
/datum/bounty/item/engineering/gas/applies_to(obj/O)
|
||||
if(!..())
|
||||
@@ -15,12 +15,12 @@
|
||||
//datum/bounty/item/engineering/gas/nitryl_tank
|
||||
// name = "Full Tank of Nitryl"
|
||||
// description = "The non-human staff of Station 88 has been volunteered to test performance enhancing drugs. Ship them a tank full of Nitryl so they can get started."
|
||||
// gas_type = /datum/gas/nitryl
|
||||
// gas_type = GAS_NITRYL
|
||||
|
||||
/datum/bounty/item/engineering/gas/tritium_tank
|
||||
name = "Full Tank of Tritium"
|
||||
description = "Station 49 is looking to kickstart their research program. Ship them a tank full of Tritium."
|
||||
gas_type = /datum/gas/tritium
|
||||
gas_type = GAS_TRITIUM
|
||||
|
||||
/datum/bounty/item/engineering/pacman
|
||||
name = "P.A.C.M.A.N.-type portable generator"
|
||||
|
||||
@@ -84,17 +84,19 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
|
||||
|
||||
/datum/export/New()
|
||||
..()
|
||||
SSprocessing.processing += src
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
init_cost = cost
|
||||
export_types = typecacheof(export_types)
|
||||
exclude_types = typecacheof(exclude_types)
|
||||
|
||||
/datum/export/Destroy()
|
||||
SSprocessing.processing -= src
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
return ..()
|
||||
|
||||
/datum/export/process()
|
||||
..()
|
||||
. = ..()
|
||||
if(!k_elasticity)
|
||||
return PROCESS_KILL
|
||||
cost *= NUM_E**(k_elasticity * (1/30))
|
||||
if(cost > init_cost)
|
||||
cost = init_cost
|
||||
|
||||
@@ -169,13 +169,13 @@
|
||||
/datum/export/large/gas_canister/get_cost(obj/O)
|
||||
var/obj/machinery/portable_atmospherics/canister/C = O
|
||||
var/worth = 10
|
||||
worth += C.air_contents.get_moles(/datum/gas/bz)*3
|
||||
worth += C.air_contents.get_moles(/datum/gas/stimulum)*25
|
||||
worth += C.air_contents.get_moles(/datum/gas/hypernoblium)*20
|
||||
worth += C.air_contents.get_moles(/datum/gas/miasma)*2
|
||||
worth += C.air_contents.get_moles(/datum/gas/tritium)*7
|
||||
worth += C.air_contents.get_moles(/datum/gas/pluoxium)*6
|
||||
worth += C.air_contents.get_moles(/datum/gas/nitryl)*10
|
||||
worth += C.air_contents.get_moles(GAS_BZ)*3
|
||||
worth += C.air_contents.get_moles(GAS_STIMULUM)*25
|
||||
worth += C.air_contents.get_moles(GAS_HYPERNOB)*20
|
||||
worth += C.air_contents.get_moles(GAS_MIASMA)*2
|
||||
worth += C.air_contents.get_moles(GAS_TRITIUM)*7
|
||||
worth += C.air_contents.get_moles(GAS_PLUOXIUM)*6
|
||||
worth += C.air_contents.get_moles(GAS_NITRYL)*10
|
||||
return worth
|
||||
|
||||
|
||||
|
||||
@@ -183,3 +183,7 @@
|
||||
//world.time of when the crew manifest can be accessed
|
||||
var/crew_manifest_delay
|
||||
|
||||
/// Should go in persistent round player data sometime. This tracks what items have already warned the user on pickup that they can block/parry.
|
||||
var/list/block_parry_hinted = list()
|
||||
/// moused over objects, currently capped at 7. this is awful, and should be replaced with a component to track it using signals for parrying at some point.
|
||||
var/list/moused_over_objects = list()
|
||||
|
||||
@@ -236,10 +236,9 @@
|
||||
parry_efficiency_considered_successful = 0.01
|
||||
parry_efficiency_to_counterattack = INFINITY // no auto counter
|
||||
parry_max_attacks = INFINITY
|
||||
parry_failed_cooldown_duration = 2.25 SECONDS
|
||||
parry_failed_stagger_duration = 2.25 SECONDS
|
||||
parry_failed_cooldown_duration = 1.5 SECONDS
|
||||
parry_failed_stagger_duration = 1.5 SECONDS
|
||||
parry_cooldown = 0
|
||||
parry_failed_clickcd_duration = 0
|
||||
|
||||
/obj/item/clothing/gloves/fingerless/pugilist/mauler
|
||||
name = "mauler gauntlets"
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
name = "Cat Surgeon"
|
||||
typepath = /datum/round_event/cat_surgeon
|
||||
max_occurrences = 1
|
||||
weight = 10
|
||||
weight = 8
|
||||
|
||||
/datum/round_event/cat_surgeon/announce(fake)
|
||||
priority_announce("One of our... ahem... 'special' cases has escaped. Our sensors now show their tracker implant on your station. On an unrelated note, has anyone seen our cats?",
|
||||
sender_override = "Nanotrasen Psych Ward")
|
||||
|
||||
/datum/round_event/cat_surgeon/start()
|
||||
var/list/spawn_locs = list()
|
||||
@@ -16,7 +19,7 @@
|
||||
|
||||
var/turf/T = get_turf(pick(spawn_locs))
|
||||
var/mob/living/simple_animal/hostile/cat_butcherer/S = new(T)
|
||||
playsound(S, 'sound/misc/catscream.ogg', 50, 1, -1)
|
||||
playsound(S, 'sound/misc/catscream.ogg', 75, 1, -1)
|
||||
message_admins("A cat surgeon has been spawned at [COORD(T)][ADMIN_JMP(T)]")
|
||||
log_game("A cat surgeon has been spawned at [COORD(T)]")
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
GM.set_moles(/datum/gas/oxygen, max(GM.get_moles(/datum/gas/oxygen) - severity * holder.energy, 0))
|
||||
GM.set_moles(GAS_O2, max(GM.get_moles(GAS_O2) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/nitro_eater
|
||||
name = "nitrogen consuming"
|
||||
@@ -183,7 +183,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
GM.set_moles(/datum/gas/nitrogen, max(GM.get_moles(/datum/gas/nitrogen) - severity * holder.energy, 0))
|
||||
GM.set_moles(GAS_N2, max(GM.get_moles(GAS_N2) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/carbondioxide_eater
|
||||
name = "CO2 consuming"
|
||||
@@ -195,7 +195,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
GM.set_moles(/datum/gas/carbon_dioxide, max(GM.get_moles(/datum/gas/carbon_dioxide) - severity * holder.energy, 0))
|
||||
GM.set_moles(GAS_CO2, max(GM.get_moles(GAS_CO2) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/plasma_eater
|
||||
name = "toxins consuming"
|
||||
@@ -207,7 +207,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
GM.set_moles(/datum/gas/plasma, max(GM.get_moles(/datum/gas/plasma) - severity * holder.energy, 0))
|
||||
GM.set_moles(GAS_PLASMA, max(GM.get_moles(GAS_PLASMA) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/thorns
|
||||
name = "thorny"
|
||||
|
||||
@@ -139,7 +139,6 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars_by_type, typecacheof_assoc_list(list(
|
||||
if(toupdate.len)
|
||||
for(var/turf/T1 in toupdate)
|
||||
CALCULATE_ADJACENT_TURFS(T1)
|
||||
SSair.add_to_active(T1,1)
|
||||
|
||||
|
||||
return copiedobjs
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
var/datum/effect_system/spark_spread/s = new
|
||||
s.set_up(3, 1, T)
|
||||
s.start()
|
||||
T.temperature = 5000
|
||||
T.set_temperature(5000)
|
||||
T.hotspot_expose(50000, 50000, TRUE, TRUE)
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/stank = new
|
||||
stank.adjust_moles(/datum/gas/miasma,(yield + 6)*7*0.02) // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses
|
||||
stank.adjust_moles(GAS_MIASMA,(yield + 6)*0.14) // 0.14 = 7*0.02, this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses
|
||||
stank.set_temperature(T20C) // without this the room would eventually freeze and miasma mining would be easier
|
||||
T.assume_air(stank)
|
||||
T.air_update_turf()
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
endurance = 30
|
||||
maturation = 5
|
||||
yield = 1
|
||||
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/eyes)
|
||||
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
|
||||
mutatelist = list()
|
||||
reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.05, /datum/reagent/consumable/nutriment = 0.15)
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
var/turf/open/O = loc
|
||||
if(O.air)
|
||||
var/datum/gas_mixture/loc_air = O.air
|
||||
if(loc_air.get_moles(/datum/gas/oxygen) > 13)
|
||||
if(loc_air.get_moles(GAS_O2) > 13)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -419,6 +419,15 @@
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need five lengths of cable to make a [G] battery!</span>")
|
||||
|
||||
/datum/plant_gene/trait/eyes
|
||||
name = "Oculary Mimicry"
|
||||
/// Our googly eyes appearance.
|
||||
var/mutable_appearance/googly
|
||||
|
||||
/datum/plant_gene/trait/eyes/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc)
|
||||
googly = mutable_appearance('icons/obj/hydroponics/harvest.dmi', "eyes")
|
||||
googly.appearance_flags = RESET_COLOR
|
||||
G.add_overlay(googly)
|
||||
|
||||
/datum/plant_gene/trait/stinging
|
||||
name = "Hypodermic Prickles"
|
||||
|
||||
@@ -131,11 +131,10 @@
|
||||
var/pressure_delta = target_pressure - target_air.return_pressure()
|
||||
if(pressure_delta > 0.1)
|
||||
var/transfer_moles = (pressure_delta*target_air.return_volume()/(source_air.return_temperature() * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY
|
||||
var/datum/gas_mixture/removed = source_air.remove(transfer_moles)
|
||||
if(istype(snowflake)) //Snowflake check for tanks specifically, because tank ruptures are handled in a very snowflakey way that expects all tank interactions to be handled via the tank's procs
|
||||
snowflake.assume_air(removed)
|
||||
snowflake.assume_air_moles(source_air, transfer_moles)
|
||||
else
|
||||
target_air.merge(removed)
|
||||
source_air.transfer_to(target_air, transfer_moles)
|
||||
|
||||
|
||||
// - volume pump - // **Works**
|
||||
@@ -183,12 +182,10 @@
|
||||
//The second part of the min caps the pressure built by the volume pumps to the max pump pressure
|
||||
var/transfer_ratio = min(transfer_rate,target_air.return_volume()*PUMP_MAX_PRESSURE/source_air.return_pressure())/source_air.return_volume()
|
||||
|
||||
var/datum/gas_mixture/removed = source_air.remove_ratio(transfer_ratio * PUMP_EFFICIENCY)
|
||||
|
||||
if(istype(snowflake))
|
||||
snowflake.assume_air(removed)
|
||||
snowflake.assume_air_ratio(source_air, transfer_ratio * PUMP_EFFICIENCY)
|
||||
else
|
||||
target_air.merge(removed)
|
||||
source_air.transfer_ratio_to(target_air, transfer_ratio * PUMP_EFFICIENCY)
|
||||
|
||||
|
||||
// - gas vent - // **works**
|
||||
@@ -376,7 +373,7 @@
|
||||
|
||||
for(var/filtered_gas in removed.get_gases())
|
||||
//Get the name of the gas and see if it is in the list
|
||||
if(GLOB.meta_gas_names[filtered_gas] in wanted)
|
||||
if(GLOB.gas_data.names[filtered_gas] in wanted)
|
||||
//The gas that is put in all the filtered out gases
|
||||
filtered_out.set_temperature(removed.return_temperature())
|
||||
filtered_out.set_moles(filtered_gas, removed.get_moles(filtered_gas))
|
||||
@@ -468,16 +465,12 @@
|
||||
|
||||
var/snowflakecheck = istype(gas_output, /obj/item/tank)
|
||||
|
||||
var/datum/gas_mixture/mix = source_1_gases.remove(transfer_moles * gas_percentage)
|
||||
if(snowflakecheck)
|
||||
gas_output.assume_air(mix)
|
||||
gas_output.assume_air_moles(source_1_gases, transfer_moles * gas_percentage)
|
||||
gas_output.assume_air_moles(source_2_gases, transfer_moles * (1-gas_percentage))
|
||||
else
|
||||
output_gases.merge(mix)
|
||||
mix = source_2_gases.remove(transfer_moles * (1-gas_percentage))
|
||||
if(snowflakecheck)
|
||||
gas_output.assume_air(mix)
|
||||
else
|
||||
output_gases.merge(mix)
|
||||
source_1_gases.transfer_to(output_gases, transfer_moles * gas_percentage)
|
||||
source_2_gases.transfer_to(output_gases, transfer_moles * (1-gas_percentage))
|
||||
|
||||
|
||||
// - integrated tank - // **works**
|
||||
|
||||
@@ -1163,7 +1163,7 @@
|
||||
var/list/gas_names = list()
|
||||
var/list/gas_amounts = list()
|
||||
for(var/id in air_contents.get_gases())
|
||||
var/name = GLOB.meta_gas_names[id]
|
||||
var/name = GLOB.gas_data.names[id]
|
||||
var/amt = round(air_contents.get_moles(id), 0.001)
|
||||
gas_names.Add(name)
|
||||
gas_amounts.Add(amt)
|
||||
|
||||
@@ -292,10 +292,7 @@
|
||||
if(!source_air || !target_air)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/removed = source_air.remove(gas_per_throw)
|
||||
if(!removed)
|
||||
return
|
||||
target_air.merge(removed)
|
||||
source_air.transfer_to(target_air, gas_per_throw)
|
||||
|
||||
// If the item is in a grabber circuit we'll update the grabber's outputs after we've thrown it.
|
||||
var/obj/item/integrated_circuit/manipulation/grabber/G = A.loc
|
||||
|
||||
@@ -76,3 +76,15 @@
|
||||
else
|
||||
user.mob.dropItemToGround(I)
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/mob/examine_immediate
|
||||
hotkey_keys = list()
|
||||
classic_keys = list()
|
||||
name = "examine_immediate"
|
||||
full_name = "Examine (Immediate)"
|
||||
description = "Immediately examine anything you're hovering your mouse over."
|
||||
|
||||
/datum/keybinding/mob/examine_immediate/down(client/user)
|
||||
var/atom/A = user.mouseObject
|
||||
if(A)
|
||||
A.attempt_examinate(user.mob)
|
||||
|
||||
@@ -152,7 +152,6 @@
|
||||
locate(min(T.x + width + 1, world.maxx), min(T.y + height + 1, world.maxy), T.z))
|
||||
for(var/i in border)
|
||||
var/turf/turf_to_disable = i
|
||||
SSair.remove_from_active(turf_to_disable) //stop processing turfs along the border to prevent runtimes, we return it in initTemplateBounds()
|
||||
turf_to_disable.atmos_adjacent_turfs?.Cut()
|
||||
|
||||
if(annihilate == MAP_TEMPLATE_ANNIHILATE_PRELOAD)
|
||||
|
||||
@@ -196,7 +196,6 @@
|
||||
parry_imperfect_falloff_percent = 20
|
||||
parry_efficiency_to_counterattack = 100 // perfect parry or you're cringe
|
||||
parry_failed_stagger_duration = 1.5 SECONDS // a good time to reconsider your actions...
|
||||
parry_failed_clickcd_duration = 1.5 SECONDS // or your failures
|
||||
|
||||
/obj/item/kinetic_crusher/glaive/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) // if you're dumb enough to go for a parry...
|
||||
var/turf/proj_turf = owner.loc // destabilizer bolt, ignoring cooldown
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
/obj/item/energy_katana,
|
||||
/obj/item/hierophant_club,
|
||||
/obj/item/his_grace,
|
||||
/obj/item/gun/ballistic/minigun,
|
||||
/obj/item/gun/energy/minigun,
|
||||
/obj/item/gun/ballistic/automatic/l6_saw,
|
||||
/obj/item/gun/magic/staff/chaos,
|
||||
/obj/item/gun/magic/staff/spellblade,
|
||||
|
||||
@@ -16,20 +16,20 @@
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
|
||||
|
||||
//Partial pressure of the toxins in our breath
|
||||
var/Toxins_pp = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure
|
||||
var/Toxins_pp = (breath.get_moles(GAS_PLASMA)/breath.total_moles())*breath_pressure
|
||||
|
||||
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
|
||||
adjustPlasma(breath.get_moles(/datum/gas/plasma)*250)
|
||||
adjustPlasma(breath.get_moles(GAS_PLASMA)*250)
|
||||
throw_alert("alien_tox", /obj/screen/alert/alien_tox)
|
||||
|
||||
toxins_used = breath.get_moles(/datum/gas/plasma)
|
||||
toxins_used = breath.get_moles(GAS_PLASMA)
|
||||
|
||||
else
|
||||
clear_alert("alien_tox")
|
||||
|
||||
//Breathe in toxins and out oxygen
|
||||
breath.adjust_moles(/datum/gas/plasma, -toxins_used)
|
||||
breath.adjust_moles(/datum/gas/oxygen, toxins_used)
|
||||
breath.adjust_moles(GAS_PLASMA, -toxins_used)
|
||||
breath.adjust_moles(GAS_O2, toxins_used)
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//The effects include: stun, knockdown, unconscious, sleeping, resting, jitteriness, dizziness, ear damage,
|
||||
// eye damage, eye_blind, eye_blurry, druggy, TRAIT_BLIND trait, and TRAIT_NEARSIGHT trait.
|
||||
|
||||
/mob/living/carbon/alien/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
|
||||
/mob/living/carbon/alien/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor)
|
||||
return //no
|
||||
|
||||
/////////////////////////////////// STUN ////////////////////////////////////
|
||||
|
||||
@@ -358,10 +358,11 @@
|
||||
return
|
||||
I.item_flags |= BEING_REMOVED
|
||||
breakouttime = I.breakouttime
|
||||
var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src))
|
||||
if(!cuff_break)
|
||||
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)</span>")
|
||||
if(do_after(src, breakouttime, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
|
||||
if(do_after_advanced(src, breakouttime, src, NONE, CALLBACK(cuffbreak_checker, /datum/cuffbreak_checker.proc/check_movement), required_mobility_flags = MOBILITY_RESIST))
|
||||
clear_cuffs(I, cuff_break)
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You fail to remove [I]!</span>")
|
||||
@@ -370,15 +371,30 @@
|
||||
breakouttime = 50
|
||||
visible_message("<span class='warning'>[src] is trying to break [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)</span>")
|
||||
if(do_after(src, breakouttime, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
|
||||
if(do_after_advanced(src, breakouttime, src, NONE, CALLBACK(cuffbreak_checker, /datum/cuffbreak_checker.proc/check_movement), required_mobility_flags = MOBILITY_RESIST))
|
||||
clear_cuffs(I, cuff_break)
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You fail to break [I]!</span>")
|
||||
|
||||
else if(cuff_break == INSTANT_CUFFBREAK)
|
||||
clear_cuffs(I, cuff_break)
|
||||
|
||||
QDEL_NULL(cuffbreak_checker)
|
||||
I.item_flags &= ~BEING_REMOVED
|
||||
|
||||
/datum/cuffbreak_checker
|
||||
var/turf/last
|
||||
|
||||
/datum/cuffbreak_checker/New(turf/initial_turf)
|
||||
last = initial_turf
|
||||
|
||||
/datum/cuffbreak_checker/proc/check_movement(atom/user, delay, atom/target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, list/passed_in)
|
||||
if(get_turf(user) != last)
|
||||
last = get_turf(user)
|
||||
passed_in[1] = 0.5
|
||||
else
|
||||
passed_in[1] = 1
|
||||
|
||||
/mob/living/carbon/proc/uncuff()
|
||||
if (handcuffed)
|
||||
var/obj/item/W = handcuffed
|
||||
@@ -459,10 +475,6 @@
|
||||
if(HAS_TRAIT(src, TRAIT_CLUMSY))
|
||||
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
|
||||
|
||||
//CIT CHANGES START HERE
|
||||
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
modifier -= 50
|
||||
|
||||
if(modifier < 100)
|
||||
dropItemToGround(I)
|
||||
//END OF CIT CHANGES
|
||||
@@ -503,7 +515,7 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
|
||||
if((HAS_TRAIT(src, TRAIT_NOHUNGER) || HAS_TRAIT(src, TRAIT_TOXINLOVER)) && !force)
|
||||
if(HAS_TRAIT(src, TRAIT_NOHUNGER) && !force)
|
||||
return TRUE
|
||||
|
||||
if(nutrition < 100 && !blood && !force)
|
||||
|
||||
@@ -841,7 +841,7 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
|
||||
if(blood && dna?.species && (NOBLOOD in dna.species.species_traits) && !HAS_TRAIT(src, TRAIT_TOXINLOVER))
|
||||
if(blood && dna?.species && (NOBLOOD in dna.species.species_traits))
|
||||
if(message)
|
||||
visible_message("<span class='warning'>[src] dry heaves!</span>", \
|
||||
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
|
||||
@@ -1055,10 +1055,10 @@
|
||||
return
|
||||
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment
|
||||
var/scaling = maxHealth / 100
|
||||
var/health_deficiency = ((maxHealth / scaling) - (health / scaling) + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
|
||||
var/health_deficiency = max(((maxHealth / scaling) - (health / scaling)), (getStaminaLoss()*0.75))
|
||||
if(health_deficiency >= 40)
|
||||
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75)
|
||||
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25)
|
||||
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency - 15) / 75)
|
||||
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency - 15) / 25)
|
||||
else
|
||||
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
|
||||
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
|
||||
|
||||
@@ -409,7 +409,7 @@
|
||||
return
|
||||
var/informed = FALSE
|
||||
if(isrobotic(src))
|
||||
apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
|
||||
apply_status_effect(/datum/status_effect/robotic_emp, severity / 20)
|
||||
severity *= 0.5
|
||||
var/do_not_stun = FALSE
|
||||
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
)
|
||||
|
||||
parry_efficiency_considered_successful = 0.01
|
||||
parry_efficiency_to_counterattack = 0.01
|
||||
parry_efficiency_to_counterattack = INFINITY // no counterattacks
|
||||
parry_max_attacks = INFINITY
|
||||
parry_failed_cooldown_duration = 1.5 SECONDS
|
||||
parry_failed_stagger_duration = 1 SECONDS
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT)
|
||||
H.update_disabled_bodyparts(silent = TRUE) //silently update arms to be paralysed
|
||||
@@ -99,7 +98,6 @@
|
||||
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
|
||||
|
||||
@@ -1589,12 +1589,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/punchedbrute = target.getBruteLoss()
|
||||
|
||||
//CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage
|
||||
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
damage *= 1.2
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
damage *= 0.65
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
damage *= 0.8
|
||||
//END OF CITADEL CHANGES
|
||||
|
||||
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
|
||||
@@ -1718,12 +1714,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
else
|
||||
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes disarmspam cause staminaloss, pugilists can do it almost effortlessly
|
||||
if(!user.UseStaminaBuffer(1, warn = TRUE))
|
||||
return
|
||||
else
|
||||
if(!user.UseStaminaBuffer(1, warn = TRUE))
|
||||
return
|
||||
if(!user.UseStaminaBuffer(1, warn = TRUE))
|
||||
return
|
||||
|
||||
if(attacker_style && attacker_style.disarm_act(user,target))
|
||||
return TRUE
|
||||
@@ -1741,12 +1733,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
log_combat(user, target, "disarmed out of grab from")
|
||||
return
|
||||
var/randn = rand(1, 100)
|
||||
if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE
|
||||
randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE
|
||||
randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE
|
||||
randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode
|
||||
if(user.pulling == target)
|
||||
randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess
|
||||
if(HAS_TRAIT(user, TRAIT_PUGILIST))
|
||||
@@ -1951,9 +1939,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(IS_STAMCRIT(user))
|
||||
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")
|
||||
return
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
to_chat(user, "<span class='warning'>You need combat mode to be active to that!</span>")
|
||||
return
|
||||
if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun())
|
||||
to_chat(user, "<span class='warning'>You can't seem to force yourself up right now!</span>")
|
||||
return
|
||||
@@ -1993,6 +1978,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
if(CHECK_MOBILITY(target, MOBILITY_STAND))
|
||||
target.adjustStaminaLoss(5)
|
||||
else
|
||||
target.adjustStaminaLoss(target.getStaminaLoss() > 75? 5 : 75)
|
||||
|
||||
if(target.is_shove_knockdown_blocked())
|
||||
return
|
||||
@@ -2035,7 +2022,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
target.visible_message("<span class='danger'>[user.name] shoves [target.name]!</span>",
|
||||
"<span class='danger'>[user.name] shoves you!</span>", null, COMBAT_MESSAGE_RANGE, null,
|
||||
user, "<span class='danger'>You shove [target.name]!</span>")
|
||||
target.Stagger(SHOVE_STAGGER_DURATION)
|
||||
var/obj/item/target_held_item = target.get_active_held_item()
|
||||
if(!target.has_status_effect(STATUS_EFFECT_OFF_BALANCE))
|
||||
if(target_held_item)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed)
|
||||
if(environment)
|
||||
if(environment.total_moles())
|
||||
if(environment.get_moles(/datum/gas/oxygen) >= 1) //Same threshhold that extinguishes fire
|
||||
if(environment.get_moles(GAS_O2) >= 1) //Same threshhold that extinguishes fire
|
||||
H.adjust_fire_stacks(0.5)
|
||||
if(!H.on_fire && H.fire_stacks > 0)
|
||||
H.visible_message("<span class='danger'>[H]'s body reacts with the atmosphere and bursts into flames!</span>","<span class='userdanger'>Your body reacts with the atmosphere and bursts into flame!</span>")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
|
||||
/mob/living/carbon/human/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor)
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -115,16 +115,18 @@
|
||||
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME)
|
||||
|
||||
else if(isturf(loc)) //Breathe from loc as turf
|
||||
var/breath_moles = 0
|
||||
var/breath_ratio = 0
|
||||
if(environment)
|
||||
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
|
||||
breath_ratio = BREATH_VOLUME/environment.return_volume()
|
||||
|
||||
breath = loc.remove_air(breath_moles)
|
||||
breath = loc.remove_air_ratio(breath_ratio)
|
||||
else //Breathe from loc as obj again
|
||||
if(istype(loc, /obj/))
|
||||
var/obj/loc_as_obj = loc
|
||||
loc_as_obj.handle_internal_lifeform(src,0)
|
||||
|
||||
if(breath)
|
||||
breath.set_volume(BREATH_VOLUME)
|
||||
check_breath(breath)
|
||||
|
||||
if(breath)
|
||||
@@ -163,11 +165,11 @@
|
||||
var/SA_para_min = 1
|
||||
var/SA_sleep_min = 5
|
||||
var/oxygen_used = 0
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
|
||||
|
||||
var/O2_partialpressure = (breath.get_moles(/datum/gas/oxygen)/breath.total_moles())*breath_pressure
|
||||
var/Toxins_partialpressure = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure
|
||||
var/CO2_partialpressure = (breath.get_moles(/datum/gas/carbon_dioxide)/breath.total_moles())*breath_pressure
|
||||
var/moles = breath.total_moles()
|
||||
var/breath_pressure = (moles*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
|
||||
var/O2_partialpressure = ((breath.get_moles(GAS_O2)/moles)*breath_pressure) + (((breath.get_moles(GAS_PLUOXIUM)*8)/moles)*breath_pressure)
|
||||
var/Toxins_partialpressure = (breath.get_moles(GAS_PLASMA)/moles)*breath_pressure
|
||||
var/CO2_partialpressure = (breath.get_moles(GAS_CO2)/moles)*breath_pressure
|
||||
|
||||
|
||||
//OXYGEN
|
||||
@@ -191,7 +193,7 @@
|
||||
var/ratio = 1 - O2_partialpressure/safe_oxy_min
|
||||
adjustOxyLoss(min(5*ratio, 3))
|
||||
failed_last_breath = 1
|
||||
oxygen_used = breath.get_moles(/datum/gas/oxygen)*ratio
|
||||
oxygen_used = breath.get_moles(GAS_O2)*ratio
|
||||
else
|
||||
adjustOxyLoss(3)
|
||||
failed_last_breath = 1
|
||||
@@ -203,12 +205,12 @@
|
||||
o2overloadtime = 0 //reset our counter for this too
|
||||
if(health >= crit_threshold)
|
||||
adjustOxyLoss(-5)
|
||||
oxygen_used = breath.get_moles(/datum/gas/oxygen)
|
||||
oxygen_used = breath.get_moles(GAS_O2)
|
||||
clear_alert("not_enough_oxy")
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "suffocation")
|
||||
|
||||
breath.adjust_moles(/datum/gas/oxygen, -oxygen_used)
|
||||
breath.adjust_moles(/datum/gas/carbon_dioxide, oxygen_used)
|
||||
breath.adjust_moles(GAS_O2, -oxygen_used)
|
||||
breath.adjust_moles(GAS_CO2, oxygen_used)
|
||||
|
||||
//CARBON DIOXIDE
|
||||
if(CO2_partialpressure > safe_co2_max)
|
||||
@@ -227,15 +229,15 @@
|
||||
|
||||
//TOXINS/PLASMA
|
||||
if(Toxins_partialpressure > safe_tox_max)
|
||||
var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_tox_max) * 10
|
||||
var/ratio = (breath.get_moles(GAS_PLASMA)/safe_tox_max) * 10
|
||||
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
|
||||
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
|
||||
else
|
||||
clear_alert("too_much_tox")
|
||||
|
||||
//NITROUS OXIDE
|
||||
if(breath.get_moles(/datum/gas/nitrous_oxide))
|
||||
var/SA_partialpressure = (breath.get_moles(/datum/gas/nitrous_oxide)/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(GAS_NITROUS))
|
||||
var/SA_partialpressure = (breath.get_moles(GAS_NITROUS)/breath.total_moles())*breath_pressure
|
||||
if(SA_partialpressure > SA_para_min)
|
||||
Unconscious(60)
|
||||
if(SA_partialpressure > SA_sleep_min)
|
||||
@@ -248,26 +250,26 @@
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria")
|
||||
|
||||
//BZ (Facepunch port of their Agent B)
|
||||
if(breath.get_moles(/datum/gas/bz))
|
||||
var/bz_partialpressure = (breath.get_moles(/datum/gas/bz)/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(GAS_BZ))
|
||||
var/bz_partialpressure = (breath.get_moles(GAS_BZ)/breath.total_moles())*breath_pressure
|
||||
if(bz_partialpressure > 1)
|
||||
hallucination += 10
|
||||
else if(bz_partialpressure > 0.01)
|
||||
hallucination += 5
|
||||
|
||||
//TRITIUM
|
||||
if(breath.get_moles(/datum/gas/tritium))
|
||||
var/tritium_partialpressure = (breath.get_moles(/datum/gas/tritium)/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(GAS_TRITIUM))
|
||||
var/tritium_partialpressure = (breath.get_moles(GAS_TRITIUM)/breath.total_moles())*breath_pressure
|
||||
radiation += tritium_partialpressure/10
|
||||
|
||||
//NITRYL
|
||||
if(breath.get_moles(/datum/gas/nitryl))
|
||||
var/nitryl_partialpressure = (breath.get_moles(/datum/gas/nitryl)/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(GAS_NITRYL))
|
||||
var/nitryl_partialpressure = (breath.get_moles(GAS_NITRYL)/breath.total_moles())*breath_pressure
|
||||
adjustFireLoss(nitryl_partialpressure/4)
|
||||
|
||||
//MIASMA
|
||||
if(breath.get_moles(/datum/gas/miasma))
|
||||
var/miasma_partialpressure = (breath.get_moles(/datum/gas/miasma)/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(GAS_MIASMA))
|
||||
var/miasma_partialpressure = (breath.get_moles(GAS_MIASMA)/breath.total_moles())*breath_pressure
|
||||
if(miasma_partialpressure > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
|
||||
if(prob(0.05 * miasma_partialpressure))
|
||||
@@ -365,7 +367,7 @@
|
||||
|
||||
var/datum/gas_mixture/stank = new
|
||||
|
||||
stank.set_moles(/datum/gas/miasma,0.1)
|
||||
stank.set_moles(GAS_MIASMA,0.1)
|
||||
|
||||
stank.set_temperature(BODYTEMP_NORMAL)
|
||||
|
||||
@@ -510,9 +512,8 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
|
||||
//this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc..
|
||||
/mob/living/carbon/handle_status_effects()
|
||||
..()
|
||||
var/combat_mode = SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)
|
||||
if(getStaminaLoss() && !HAS_TRAIT(src, TRAIT_NO_STAMINA_REGENERATION))
|
||||
adjustStaminaLoss((!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL) * (combat_mode? 0.25 : 1))
|
||||
adjustStaminaLoss((!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL))
|
||||
|
||||
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1)
|
||||
incomingstammult = max(0.01, incomingstammult)
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
ExtinguishMob()
|
||||
return
|
||||
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
|
||||
if(!G.get_moles(/datum/gas/oxygen, 1))
|
||||
if(!G.get_moles(GAS_O2, 1))
|
||||
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
|
||||
return
|
||||
var/turf/location = get_turf(src)
|
||||
|
||||
@@ -995,7 +995,7 @@
|
||||
loc_temp = obj_temp
|
||||
else if(isspaceturf(get_turf(src)))
|
||||
var/turf/heat_turf = get_turf(src)
|
||||
loc_temp = heat_turf.temperature
|
||||
loc_temp = heat_turf.return_temperature()
|
||||
return loc_temp
|
||||
|
||||
/mob/living/proc/get_standard_pixel_x_offset(lying = 0)
|
||||
|
||||
@@ -48,25 +48,23 @@
|
||||
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN)
|
||||
|
||||
/mob/living/proc/continue_starting_active_block()
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
return DO_AFTER_STOP
|
||||
return (combat_flags & COMBAT_FLAG_ACTIVE_BLOCK_STARTING)? DO_AFTER_CONTINUE : DO_AFTER_STOP
|
||||
|
||||
/mob/living/get_standard_pixel_x_offset()
|
||||
. = ..()
|
||||
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
|
||||
if(dir & EAST)
|
||||
. += 8
|
||||
. += 4
|
||||
if(dir & WEST)
|
||||
. -= 8
|
||||
. -= 4
|
||||
|
||||
/mob/living/get_standard_pixel_y_offset()
|
||||
. = ..()
|
||||
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
|
||||
if(dir & NORTH)
|
||||
. += 8
|
||||
. += 4
|
||||
if(dir & SOUTH)
|
||||
. -= 8
|
||||
. -= 4
|
||||
|
||||
/**
|
||||
* Proc called by keybindings to toggle active blocking.
|
||||
@@ -100,11 +98,6 @@
|
||||
if(!I.can_active_block())
|
||||
to_chat(src, "<span class='warning'>[I] is either not capable of being used to actively block, or is not currently in a state that can! (Try wielding it if it's twohanded, for example.)</span>")
|
||||
return
|
||||
// QOL: Attempt to toggle on combat mode if it isn't already
|
||||
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
to_chat(src, "<span class='warning'>You must be in combat mode to actively block!</span>")
|
||||
return FALSE
|
||||
var/datum/block_parry_data/data = I.get_block_parry_data()
|
||||
var/delay = data.block_start_delay
|
||||
combat_flags |= COMBAT_FLAG_ACTIVE_BLOCK_STARTING
|
||||
@@ -147,7 +140,7 @@
|
||||
/**
|
||||
* Calculates FINAL ATTACK DAMAGE after mitigation
|
||||
*/
|
||||
/obj/item/proc/active_block_calculate_final_damage(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
/obj/item/proc/active_block_calculate_final_damage(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, passive = FALSE)
|
||||
var/datum/block_parry_data/data = get_block_parry_data()
|
||||
var/absorption = data.attack_type_list_scan(data.block_damage_absorption_override, attack_type)
|
||||
var/efficiency = data.attack_type_list_scan(data.block_damage_multiplier_override, attack_type)
|
||||
@@ -156,7 +149,7 @@
|
||||
if(isnull(absorption))
|
||||
absorption = data.block_damage_absorption
|
||||
if(isnull(efficiency))
|
||||
efficiency = data.block_damage_multiplier
|
||||
efficiency = data.block_damage_multiplier * (passive? (1 / data.block_automatic_mitigation_multiplier) : 1)
|
||||
if(isnull(limit))
|
||||
limit = data.block_damage_limit
|
||||
// now we calculate damage to reduce.
|
||||
@@ -172,7 +165,7 @@
|
||||
return final_damage
|
||||
|
||||
/// Amount of stamina from damage blocked. Note that the damage argument is damage_blocked.
|
||||
/obj/item/proc/active_block_stamina_cost(mob/living/owner, atom/object, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
/obj/item/proc/active_block_stamina_cost(mob/living/owner, atom/object, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, passive = FALSE)
|
||||
var/datum/block_parry_data/data = get_block_parry_data()
|
||||
var/efficiency = data.attack_type_list_scan(data.block_stamina_efficiency_override, attack_type)
|
||||
if(isnull(efficiency))
|
||||
@@ -182,7 +175,7 @@
|
||||
multiplier = data.attack_type_list_scan(data.block_resting_stamina_penalty_multiplier_override, attack_type)
|
||||
if(isnull(multiplier))
|
||||
multiplier = data.block_resting_stamina_penalty_multiplier
|
||||
return (damage_blocked / efficiency) * multiplier
|
||||
return (damage_blocked / efficiency) * multiplier * (passive? data.block_automatic_stamina_multiplier : 1)
|
||||
|
||||
/// Apply the stamina damage to our user, notice how damage argument is stamina_amount.
|
||||
/obj/item/proc/active_block_do_stamina_damage(mob/living/owner, atom/object, stamina_amount, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
@@ -214,6 +207,18 @@
|
||||
return
|
||||
|
||||
/obj/item/proc/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
|
||||
return directional_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, override_direction)
|
||||
|
||||
/obj/item/proc/can_passive_block()
|
||||
if(!block_parry_data || !(item_flags & ITEM_CAN_BLOCK))
|
||||
return FALSE
|
||||
var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
|
||||
return data.block_automatic_enabled
|
||||
|
||||
/obj/item/proc/passive_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
|
||||
return directional_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, override_direction, TRUE)
|
||||
|
||||
/obj/item/proc/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction, passive = FALSE)
|
||||
if(!can_active_block())
|
||||
return BLOCK_NONE
|
||||
var/datum/block_parry_data/data = get_block_parry_data()
|
||||
@@ -228,12 +233,12 @@
|
||||
incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src)
|
||||
if(!CHECK_MOBILITY(owner, MOBILITY_STAND) && !(data.block_resting_attack_types_anydir & attack_type) && (!(data.block_resting_attack_types_directional & attack_type) || !can_block_direction(owner.dir, incoming_direction)))
|
||||
return BLOCK_NONE
|
||||
else if(!can_block_direction(owner.dir, incoming_direction))
|
||||
else if(!can_block_direction(owner.dir, incoming_direction, passive))
|
||||
return BLOCK_NONE
|
||||
block_return[BLOCK_RETURN_ACTIVE_BLOCK] = TRUE
|
||||
var/final_damage = active_block_calculate_final_damage(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
var/final_damage = active_block_calculate_final_damage(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, passive)
|
||||
var/damage_blocked = damage - final_damage
|
||||
var/stamina_cost = active_block_stamina_cost(owner, object, damage_blocked, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
var/stamina_cost = active_block_stamina_cost(owner, object, damage_blocked, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, passive)
|
||||
active_block_do_stamina_damage(owner, object, stamina_cost, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
block_return[BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED] = damage - final_damage
|
||||
block_return[BLOCK_RETURN_SET_DAMAGE_TO] = final_damage
|
||||
@@ -261,9 +266,9 @@
|
||||
/**
|
||||
* Gets the block direction bitflags of what we can block.
|
||||
*/
|
||||
/obj/item/proc/blockable_directions()
|
||||
/obj/item/proc/blockable_directions(passive = FALSE)
|
||||
var/datum/block_parry_data/data = get_block_parry_data()
|
||||
return data.can_block_directions
|
||||
return (!isnull(data.block_automatic_directions) && passive)? data.block_automatic_directions : data.can_block_directions
|
||||
|
||||
/**
|
||||
* Checks if we can block from a specific direction from our direction.
|
||||
@@ -272,14 +277,14 @@
|
||||
* * our_dir - our direction.
|
||||
* * their_dir - their direction. Must be a single direction, or NONE for an attack from the same tile. This is incoming direction.
|
||||
*/
|
||||
/obj/item/proc/can_block_direction(our_dir, their_dir)
|
||||
/obj/item/proc/can_block_direction(our_dir, their_dir, passive = FALSE)
|
||||
their_dir = turn(their_dir, 180)
|
||||
if(our_dir != NORTH)
|
||||
var/turn_angle = dir2angle(our_dir)
|
||||
// dir2angle(), ss13 proc is clockwise so dir2angle(EAST) == 90
|
||||
// turn(), byond proc is counterclockwise so turn(NORTH, 90) == WEST
|
||||
their_dir = turn(their_dir, turn_angle)
|
||||
return (DIR2BLOCKDIR(their_dir) & blockable_directions())
|
||||
return (DIR2BLOCKDIR(their_dir) & blockable_directions(passive))
|
||||
|
||||
/**
|
||||
* can_block_direction but for "compound" directions to check all of them and return the number of directions that were blocked.
|
||||
|
||||
@@ -14,18 +14,58 @@
|
||||
/**
|
||||
* Initiates a parrying sequence.
|
||||
*/
|
||||
/mob/living/proc/initiate_parry_sequence()
|
||||
/mob/living/proc/initiate_parry_sequence(silent = FALSE, list/override_method_data)
|
||||
if(parrying)
|
||||
return // already parrying
|
||||
return FALSE // already parrying
|
||||
if(!(mobility_flags & MOBILITY_USE))
|
||||
to_chat(src, "<span class='warning'>You can't move your arms!</span>")
|
||||
return
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You can't move your arms!</span>")
|
||||
return FALSE
|
||||
if(!(combat_flags & COMBAT_FLAG_PARRY_CAPABLE))
|
||||
to_chat(src, "<span class='warning'>You are not something that can parry attacks.</span>")
|
||||
return
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You are not something that can parry attacks.</span>")
|
||||
return FALSE
|
||||
if(!(mobility_flags & MOBILITY_STAND))
|
||||
to_chat(src, "<span class='warning'>You aren't able to parry without solid footing!</span>")
|
||||
return
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You aren't able to parry without solid footing!</span>")
|
||||
return FALSE
|
||||
var/datum/block_parry_data/data
|
||||
var/list/determined = override_method_data || determine_parry_method(FALSE, FALSE)
|
||||
if(!islist(determined))
|
||||
return FALSE
|
||||
var/method = determined[1]
|
||||
data = return_block_parry_datum(determined[2])
|
||||
var/datum/tool = determined[3]
|
||||
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
|
||||
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
|
||||
// can always implement it later, whatever.
|
||||
if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You are not ready to parry (again)!</span>")
|
||||
return FALSE
|
||||
// Point of no return, make sure everything is set.
|
||||
parrying = method
|
||||
if(method == ITEM_PARRY)
|
||||
active_parry_item = tool
|
||||
if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
|
||||
return FALSE
|
||||
parry_start_time = world.time
|
||||
successful_parries = list()
|
||||
successful_parry_counterattacks = list()
|
||||
addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration)
|
||||
if(data.parry_flags & PARRY_LOCK_ATTACKING)
|
||||
ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT)
|
||||
if(data.parry_flags & PARRY_LOCK_SPRINTING)
|
||||
ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT)
|
||||
handle_parry_starting_effects(data)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Massive snowflake proc for getting something to parry with.
|
||||
*
|
||||
* @return list of [method, data, tool], where method is the parry method define, data is the block_parry_data var that must be run through return_block_parry_data, and tool is the concept/object/martial art/etc used.
|
||||
*/
|
||||
/mob/living/proc/determine_parry_method(silent = TRUE, autoparry = FALSE)
|
||||
// Prioritize item, then martial art, then unarmed.
|
||||
// yanderedev else if time
|
||||
var/obj/item/using_item = get_active_held_item()
|
||||
@@ -55,7 +95,8 @@
|
||||
var/list/other_items = list()
|
||||
var/list/override = list()
|
||||
if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items, override) & COMPONENT_PREVENT_PARRY_START)
|
||||
to_chat(src, "<span class='warning'>Something is preventing you from parrying!</span>")
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>Something is preventing you from parrying!</span>")
|
||||
return
|
||||
if(length(override))
|
||||
var/datum/thing = override[1]
|
||||
@@ -72,35 +113,10 @@
|
||||
method = ITEM_PARRY
|
||||
data = using_item.block_parry_data
|
||||
if(!method)
|
||||
to_chat(src, "<span class='warning'>You have nothing to parry with!</span>")
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You have nothing to parry with!</span>")
|
||||
return FALSE
|
||||
//QOL: Try to enable combat mode if it isn't already
|
||||
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
to_chat(src, "<span class='warning'>You must be in combat mode to parry!</span>")
|
||||
return FALSE
|
||||
data = return_block_parry_datum(data)
|
||||
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
|
||||
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
|
||||
// can always implement it later, whatever.
|
||||
if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
|
||||
to_chat(src, "<span class='warning'>You are not ready to parry (again)!</span>")
|
||||
return FALSE
|
||||
// Point of no return, make sure everything is set.
|
||||
parrying = method
|
||||
if(method == ITEM_PARRY)
|
||||
active_parry_item = using_item
|
||||
if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
|
||||
return FALSE
|
||||
parry_start_time = world.time
|
||||
successful_parries = list()
|
||||
addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration)
|
||||
if(data.parry_flags & PARRY_LOCK_ATTACKING)
|
||||
ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT)
|
||||
if(data.parry_flags & PARRY_LOCK_SPRINTING)
|
||||
ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT)
|
||||
handle_parry_starting_effects(data)
|
||||
return TRUE
|
||||
return list(method, data, tool)
|
||||
|
||||
/**
|
||||
* Tries to find a backup parry item.
|
||||
@@ -146,6 +162,7 @@
|
||||
parry_start_time = 0
|
||||
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
|
||||
successful_parries = null
|
||||
successful_parry_counterattacks = null
|
||||
|
||||
/**
|
||||
* Handles starting effects for parrying.
|
||||
@@ -178,17 +195,17 @@
|
||||
/**
|
||||
* Called when an attack is parried using this, whether or not the parry was successful.
|
||||
*/
|
||||
/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
|
||||
/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
|
||||
|
||||
/**
|
||||
* Called when an attack is parried innately, whether or not the parry was successful.
|
||||
*/
|
||||
/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
|
||||
/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
|
||||
|
||||
/**
|
||||
* Called when an attack is parried using this, whether or not the parry was successful.
|
||||
*/
|
||||
/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
|
||||
/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
|
||||
|
||||
/**
|
||||
* Called when an attack is parried and block_parra_data indicates to use a proc to handle counterattack.
|
||||
@@ -205,6 +222,94 @@
|
||||
*/
|
||||
/datum/martial_art/proc/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency, list/effect_text)
|
||||
|
||||
/**
|
||||
* Attempts to automatically parry an attacker.
|
||||
*/
|
||||
/mob/living/proc/attempt_auto_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
|
||||
// determine how we'll parry
|
||||
var/list/determined = determine_parry_method(TRUE, TRUE)
|
||||
if(!islist(determined))
|
||||
return BLOCK_NONE
|
||||
var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
|
||||
if(!data.parry_automatic_enabled || (last_autoparry > (world.time - data.autoparry_cooldown_absolute)))
|
||||
return BLOCK_NONE
|
||||
if(attack_type && !(attack_type & data.parry_attack_types))
|
||||
return BLOCK_NONE
|
||||
// before doing anything, check if the user moused over them properly
|
||||
if(!client)
|
||||
return BLOCK_NONE
|
||||
var/found = attacker == client.mouseObject
|
||||
if(!found)
|
||||
for(var/i in client.moused_over_objects)
|
||||
if(i == object)
|
||||
if((client.moused_over_objects[i] + (data.autoparry_mouse_delay_maximum)) >= world.time)
|
||||
found = TRUE
|
||||
break
|
||||
if(!found)
|
||||
return BLOCK_NONE
|
||||
|
||||
// if that works, try to start parry
|
||||
// first, check cooldowns
|
||||
|
||||
// now, depending on if we're doing a single simulation or a full sequence
|
||||
last_autoparry = world.time
|
||||
if(data.autoparry_sequence_simulation)
|
||||
// for full sequence simulation
|
||||
initiate_parry_sequence(TRUE, determined)
|
||||
if(data.autoparry_sequence_start_time == -1)
|
||||
parry_start_time = world.time - data.parry_time_windup
|
||||
else
|
||||
parry_start_time = world.time - data.autoparry_sequence_start_time
|
||||
// recurse back to original
|
||||
return run_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, FALSE)
|
||||
else
|
||||
// yes, this is mostly a copypaste of run_parry.
|
||||
var/efficiency = data.attack_type_list_scan(data.autoparry_single_efficiency_override, attack_type)
|
||||
if(isnull(efficiency))
|
||||
efficiency = data.autoparry_single_efficiency
|
||||
var/method = determined[1]
|
||||
switch(method)
|
||||
if(ITEM_PARRY)
|
||||
var/obj/item/I = determined[3]
|
||||
. = I.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
|
||||
if(UNARMED_PARRY)
|
||||
. = on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
|
||||
if(MARTIAL_PARRY)
|
||||
. = mind.martial_art.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
|
||||
if(!isnull(return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY])) // one of our procs overrode
|
||||
efficiency = return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY]
|
||||
if(efficiency <= 0) // Do not allow automatically handled/standardized parries that increase damage for now.
|
||||
return
|
||||
. |= BLOCK_SHOULD_PARTIAL_MITIGATE
|
||||
if(efficiency >= data.parry_efficiency_perfect)
|
||||
. |= data.perfect_parry_block_return_flags
|
||||
if(data.perfect_parry_block_return_list)
|
||||
return_list |= data.perfect_parry_block_return_list
|
||||
else if(efficiency >= data.parry_efficiency_considered_successful)
|
||||
. |= data.imperfect_parry_block_return_flags
|
||||
if(data.imperfect_parry_block_return_list)
|
||||
return_list |= data.imperfect_parry_block_return_list
|
||||
else
|
||||
. |= data.failed_parry_block_return_flags
|
||||
if(data.failed_parry_block_return_list)
|
||||
return_list |= data.failed_parry_block_return_list
|
||||
if(isnull(return_list[BLOCK_RETURN_MITIGATION_PERCENT])) // if one of the on_active_parry procs overrode. We don't have to worry about interference since parries are the first thing checked in the [do_run_block()] sequence.
|
||||
return_list[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(efficiency, 0, 100) // do not allow > 100% or < 0% for now.
|
||||
if((return_list[BLOCK_RETURN_MITIGATION_PERCENT] >= 100) || (damage <= 0))
|
||||
. |= BLOCK_SUCCESS
|
||||
var/list/effect_text
|
||||
var/pacifist_counter_check = TRUE
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM))
|
||||
switch(parrying)
|
||||
if(ITEM_PARRY)
|
||||
pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
|
||||
else
|
||||
pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
|
||||
if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] && (!(attacker in successful_parry_counterattacks) && !data.parry_allow_repeated_counterattacks))
|
||||
effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, data)
|
||||
if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
|
||||
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text, data)
|
||||
|
||||
/**
|
||||
* Gets the stage of our parry sequence we're currently in.
|
||||
*/
|
||||
@@ -235,12 +340,20 @@
|
||||
return world.time - parry_start_time
|
||||
|
||||
/// same return values as normal blocking, called with absolute highest priority in the block "chain".
|
||||
/mob/living/proc/run_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
|
||||
/mob/living/proc/run_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), allow_auto = TRUE)
|
||||
var/stage = get_parry_stage()
|
||||
if(attack_type & ATTACK_TYPE_PARRY_COUNTERATTACK)
|
||||
return BLOCK_NONE // don't infinite loop
|
||||
if(stage != PARRY_ACTIVE)
|
||||
return BLOCK_NONE
|
||||
// If they're not currently parrying, attempt auto parry
|
||||
if(stage == NOT_PARRYING)
|
||||
if(!allow_auto || SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
return BLOCK_NONE
|
||||
return attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
|
||||
else
|
||||
return BLOCK_NONE
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
if(attack_type && (!(attack_type & data.parry_attack_types) || (attack_type & ATTACK_TYPE_PARRY_COUNTERATTACK))) // if this attack is from a parry do not parry it lest we infinite loop.
|
||||
if(attack_type && !(attack_type & data.parry_attack_types))
|
||||
return BLOCK_NONE
|
||||
var/efficiency = data.get_parry_efficiency(attack_type, get_parry_time())
|
||||
switch(parrying)
|
||||
@@ -281,7 +394,7 @@
|
||||
pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
|
||||
else
|
||||
pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
|
||||
if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check)
|
||||
if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] && (!(attacker in successful_parry_counterattacks) && !data.parry_allow_repeated_counterattacks))
|
||||
effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
|
||||
if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
|
||||
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text)
|
||||
@@ -289,8 +402,9 @@
|
||||
if(length(successful_parries) >= data.parry_max_attacks)
|
||||
end_parry_sequence()
|
||||
|
||||
/mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text)
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
/mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text, datum/block_parry_data/data)
|
||||
if(!data)
|
||||
data = get_parry_data()
|
||||
var/knockdown_check = FALSE
|
||||
if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER] && parry_efficiency >= data.parry_efficiency_to_counterattack)
|
||||
knockdown_check = TRUE
|
||||
@@ -299,12 +413,14 @@
|
||||
visible_message("<span class='danger'>[src] parries [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""][length(effect_text) && knockdown_check? " and" : ""][knockdown_check? " knocking them to the ground" : ""]!</span>")
|
||||
|
||||
/// Run counterattack if any
|
||||
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency)
|
||||
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, datum/block_parry_data/data)
|
||||
if(!isliving(attacker))
|
||||
return
|
||||
var/mob/living/L = attacker
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
if(!data)
|
||||
data = get_parry_data()
|
||||
var/list/effect_text = list()
|
||||
successful_parry_counterattacks |= attacker
|
||||
// Always proc so items can override behavior easily
|
||||
switch(parrying)
|
||||
if(ITEM_PARRY)
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
var/results
|
||||
if(I == active_block_item)
|
||||
results = I.active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction)
|
||||
else if(I.can_passive_block() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
results = I.passive_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction)
|
||||
else
|
||||
results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list)
|
||||
. |= results
|
||||
|
||||
@@ -75,7 +75,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
var/block_stamina_buffer_ratio = 1
|
||||
|
||||
/// Stamina dealt directly via UseStaminaBuffer() per SECOND of block.
|
||||
var/block_stamina_cost_per_second = 1.5
|
||||
var/block_stamina_cost_per_second = 1
|
||||
/// Prevent stamina buffer regeneration while block?
|
||||
var/block_no_stambuffer_regeneration = TRUE
|
||||
/// Prevent stamina regeneration while block?
|
||||
@@ -93,20 +93,31 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
/// Sounds for blocking
|
||||
var/list/block_sounds = list('sound/block_parry/block_metal1.ogg' = 1, 'sound/block_parry/block_metal1.ogg' = 1)
|
||||
|
||||
// Autoblock
|
||||
// Other than for overrides, this mostly just reads from the above vars
|
||||
/// Can this item automatically block?
|
||||
var/block_automatic_enabled = TRUE
|
||||
/// Directions that you can autoblock in. Null to default to normal directions.
|
||||
var/block_automatic_directions = null
|
||||
/// Effectiveness multiplier for automated block. Only applies to efficiency, absorption and limits stay the same!
|
||||
var/block_automatic_mitigation_multiplier = 0.33
|
||||
/// Stamina cost multiplier for automated block
|
||||
var/block_automatic_stamina_multiplier = 1
|
||||
|
||||
/////////// PARRYING ////////////
|
||||
/// Prioriry for [mob/do_run_block()] while we're being used to parry.
|
||||
/// Priority for [mob/do_run_block()] while we're being used to parry.
|
||||
// None - Parry is always highest priority!
|
||||
/// Parry doesn't work if you aren't able to otherwise attack due to clickdelay
|
||||
var/parry_respect_clickdelay = TRUE
|
||||
var/parry_respect_clickdelay = FALSE
|
||||
/// Parry stamina cost
|
||||
var/parry_stamina_cost = 5
|
||||
/// Attack types we can block
|
||||
var/parry_attack_types = ALL
|
||||
/// Parry flags
|
||||
var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
|
||||
var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK
|
||||
|
||||
/// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage.
|
||||
var/parry_time_windup = 2
|
||||
var/parry_time_windup = 0
|
||||
/// Parry spindown duration in deciseconds. main stage end to this is the spindown stage, afterwards the parry fully ends.
|
||||
var/parry_time_spindown = 3
|
||||
/// Main parry window in deciseconds. This is between [parry_time_windup] and [parry_time_spindown]
|
||||
@@ -139,7 +150,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
/// Efficiency must be at least this to be considered successful
|
||||
var/parry_efficiency_considered_successful = 0.1
|
||||
/// Efficiency must be at least this to run automatic counterattack
|
||||
var/parry_efficiency_to_counterattack = 0.1
|
||||
var/parry_efficiency_to_counterattack = INFINITY
|
||||
/// Maximum attacks to parry successfully or unsuccessfully (but not efficiency < 0) during active period, hitting this immediately ends the sequence.
|
||||
var/parry_max_attacks = INFINITY
|
||||
/// Visual icon state override for parrying
|
||||
@@ -153,7 +164,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
/// Stagger duration post-parry if you fail to parry an attack
|
||||
var/parry_failed_stagger_duration = 3.5 SECONDS
|
||||
/// Clickdelay duration post-parry if you fail to parry an attack
|
||||
var/parry_failed_clickcd_duration = 2 SECONDS
|
||||
var/parry_failed_clickcd_duration = 0 SECONDS
|
||||
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
|
||||
var/parry_failed_cooldown_duration = 0 SECONDS
|
||||
|
||||
@@ -166,6 +177,29 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
var/perfect_parry_block_return_list
|
||||
var/imperfect_parry_block_return_list
|
||||
var/failed_parry_block_return_list
|
||||
/// Allow multiple counterattacks per parry sequence. Bad idea.
|
||||
var/parry_allow_repeated_counterattacks = FALSE
|
||||
|
||||
// Auto parry
|
||||
// Anything not specified like cooldowns/clickdelay respecting is pulled from above.
|
||||
/// Can this data automatically parry? This is off by default because this is something that requires thought to balance.
|
||||
var/parry_automatic_enabled = FALSE
|
||||
/// Hard autoparry cooldown
|
||||
var/autoparry_cooldown_absolute = 7.5 SECONDS
|
||||
/// Autoparry : Simulate a parry sequence starting at a certain tick, or simply simulate a single attack parry?
|
||||
var/autoparry_sequence_simulation = FALSE
|
||||
// Single attack simulation:
|
||||
/// Single attack autoparry - efficiency
|
||||
var/autoparry_single_efficiency = 75
|
||||
/// Single attack autoparry - efficiency overrides by attack type, see above
|
||||
var/list/autoparry_single_efficiency_override
|
||||
// Parry sequence simulation:
|
||||
/// Decisecond of sequence to start on. -1 to start to 0th tick of active parry window.
|
||||
var/autoparry_sequence_start_time = -1
|
||||
// Clickdelay/cooldown settings not included, as well as whether or not to lock attack/sprinting/etc. They will be pulled from the above.
|
||||
|
||||
/// ADVANCED - Autoparry requirement for time since last moused over for a specific object
|
||||
var/autoparry_mouse_delay_maximum = 0.35 SECONDS
|
||||
|
||||
/**
|
||||
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
|
||||
@@ -308,6 +342,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
RENDER_VARIABLE_SIMPLE(parry_cooldown, "Deciseconds it has to be since the last time a parry sequence <b>ended</b> for you before you can parry again.")
|
||||
RENDER_VARIABLE_SIMPLE(parry_failed_stagger_duration, "Deciseconds you are staggered for at the of the parry sequence if you do not successfully parry anything.")
|
||||
RENDER_VARIABLE_SIMPLE(parry_failed_clickcd_duration, "Deciseconds you are put on attack cooldown at the end of the parry sequence if you do not successfully parry anything.")
|
||||
dat += ""
|
||||
dat += "</div></table>"
|
||||
return dat.Join("")
|
||||
#undef RENDER_VARIABLE_SIMPLE
|
||||
|
||||
@@ -50,8 +50,12 @@
|
||||
var/obj/effect/abstract/parry/parry_visual_effect
|
||||
/// world.time of last parry end
|
||||
var/parry_end_time_last = 0
|
||||
/// Last autoparry
|
||||
var/last_autoparry = 0
|
||||
/// Successful parries within the current parry cycle. It's a list of efficiency percentages.
|
||||
var/list/successful_parries
|
||||
/// Current parry counterattacks. Makes sure we can only counterattack someone once per parry.
|
||||
var/list/successful_parry_counterattacks
|
||||
|
||||
var/confused = 0 //Makes the mob move in random directions.
|
||||
|
||||
|
||||
@@ -267,16 +267,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
eavesdrop_range = EAVESDROP_EXTRA_RANGE
|
||||
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
|
||||
var/list/the_dead = list()
|
||||
var/list/yellareas //CIT CHANGE - adds the ability for yelling to penetrate walls and echo throughout areas
|
||||
if(!eavesdrop_range && say_test(message) == "2") //CIT CHANGE - ditto
|
||||
yellareas = get_areas_in_range(message_range*0.5, source) //CIT CHANGE - ditto
|
||||
|
||||
for(var/_M in GLOB.player_list)
|
||||
var/mob/M = _M
|
||||
if(M.stat != DEAD) //not dead, not important
|
||||
if(yellareas) //CIT CHANGE - see above. makes yelling penetrate walls
|
||||
var/area/A = get_area(M) //CIT CHANGE - ditto
|
||||
if(istype(A) && A.ambientsounds != SPACE && (A in yellareas)) //CIT CHANGE - ditto
|
||||
listening |= M //CIT CHANGE - ditto
|
||||
continue
|
||||
if(!M.client || !client) //client is so that ghosts don't have to listen to mice
|
||||
continue
|
||||
@@ -303,6 +297,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
|
||||
|
||||
if(!eavesdrop_range && say_test(message) == "2") // Yell hook
|
||||
process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
|
||||
|
||||
//speech bubble
|
||||
var/list/speech_bubble_recipients = list()
|
||||
for(var/mob/M in listening)
|
||||
@@ -312,6 +309,30 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
|
||||
|
||||
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
|
||||
if(last_yell > (world.time - 10))
|
||||
to_chat(src, "<span class='warning'>Your voice doesn't project as far as you try to yell in such quick succession.") // yeah no, no spamming an expensive floodfill.
|
||||
return
|
||||
last_yell = world.time
|
||||
var/list/overhearing = list()
|
||||
var/list/overhearing_text = list()
|
||||
overhearing = yelling_wavefill(src, yell_power)
|
||||
if(!overhearing.len)
|
||||
overhearing_text = "none"
|
||||
else
|
||||
for(var/mob/M as anything in overhearing)
|
||||
overhearing_text += key_name(M)
|
||||
overhearing_text = english_list(overhearing_text)
|
||||
log_say("YELL: [ismob(src)? key_name(src) : src] yelled [message] with overhearing mobs [overhearing_text]")
|
||||
// overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
|
||||
overhearing -= already_heard
|
||||
if(!overhearing.len)
|
||||
return
|
||||
// to_chat(world, "DEBUG: overhearing [english_list(overhearing)]")
|
||||
for(var/_AM in overhearing)
|
||||
var/atom/movable/AM = _AM
|
||||
AM.Hear(rendered, speaker, message_language, message, null, spans, message_mode, source)
|
||||
|
||||
/mob/proc/binarycheck()
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/mob/living/silicon/examine(mob/user) //Displays a silicon's laws to ghosts
|
||||
. = ..()
|
||||
if(laws && isobserver(user))
|
||||
. += "<b>[src] has the following laws:</b>"
|
||||
for(var/law in laws.get_law_list(include_zeroth = TRUE))
|
||||
|
||||
@@ -575,7 +575,7 @@
|
||||
for(var/id in environment.get_gases())
|
||||
var/gas_level = environment.get_moles(id)/total_moles
|
||||
if(gas_level > 0.01)
|
||||
dat += "[GLOB.meta_gas_names[id]]: [round(gas_level*100)]%<br>"
|
||||
dat += "[GLOB.gas_data.names[id]]: [round(gas_level*100)]%<br>"
|
||||
dat += "Temperature: [round(environment.return_temperature()-T0C)]°C<br>"
|
||||
dat += "<a href='byond://?src=[REF(src)];software=atmosensor;sub=0'>Refresh Reading</a> <br>"
|
||||
dat += "<br>"
|
||||
|
||||
@@ -753,6 +753,12 @@
|
||||
else
|
||||
return null
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/remove_air_ratio(ratio)
|
||||
if(loc)
|
||||
return loc.remove_air_ratio(ratio)
|
||||
else
|
||||
return null
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/do_resist()
|
||||
. = ..()
|
||||
if(load)
|
||||
|
||||
@@ -50,12 +50,12 @@
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/T = src.loc
|
||||
if(T.air)
|
||||
var/co2 = T.air.get_moles(/datum/gas/carbon_dioxide)
|
||||
var/co2 = T.air.get_moles(GAS_CO2)
|
||||
if(co2 > 0)
|
||||
if(prob(25))
|
||||
var/amt = min(co2, 9)
|
||||
T.air.adjust_moles(/datum/gas/carbon_dioxide, -amt)
|
||||
T.atmos_spawn_air("o2=[amt]")
|
||||
T.air.adjust_moles(GAS_CO2, -amt)
|
||||
T.atmos_spawn_air("o2=[amt];TEMP=293.15")
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/AttackingTarget()
|
||||
. = ..()
|
||||
|
||||
@@ -264,10 +264,10 @@
|
||||
var/turf/open/ST = src.loc
|
||||
if(ST.air)
|
||||
|
||||
var/tox = ST.air.get_moles(/datum/gas/plasma)
|
||||
var/oxy = ST.air.get_moles(/datum/gas/oxygen)
|
||||
var/n2 = ST.air.get_moles(/datum/gas/nitrogen)
|
||||
var/co2 = ST.air.get_moles(/datum/gas/carbon_dioxide)
|
||||
var/tox = ST.air.get_moles(GAS_PLASMA)
|
||||
var/oxy = ST.air.get_moles(GAS_O2)
|
||||
var/n2 = ST.air.get_moles(GAS_N2)
|
||||
var/co2 = ST.air.get_moles(GAS_CO2)
|
||||
|
||||
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
|
||||
. = FALSE
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
Tempstun = 0
|
||||
|
||||
if(stat != DEAD)
|
||||
var/bz_percentage = environment.total_moles() ? (environment.get_moles(/datum/gas/bz) / environment.total_moles()) : 0
|
||||
var/bz_percentage = environment.total_moles() ? (environment.get_moles(GAS_BZ) / environment.total_moles()) : 0
|
||||
var/stasis = (bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) || force_stasis
|
||||
|
||||
if(stat == CONSCIOUS && stasis)
|
||||
|
||||
@@ -35,11 +35,10 @@
|
||||
return
|
||||
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/out_of_combat_timer, out_of_combat_timer)
|
||||
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/base_regeneration, base_regeneration)
|
||||
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/combat_regeneration, combat_regeneration)
|
||||
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/percent_regeneration_out_of_combat, percent_regeneration_out_of_combat)
|
||||
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/post_action_penalty_delay, post_action_penalty_delay)
|
||||
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/post_action_penalty_factor, post_action_penalty_factor)
|
||||
var/base_regen = (SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))? base_regeneration : combat_regeneration
|
||||
var/base_regen = base_regeneration
|
||||
var/time_since_last_action = world.time - stamina_buffer_last_use
|
||||
var/action_penalty = ((time_since_last_action) < (post_action_penalty_delay * 10))? post_action_penalty_factor : 1
|
||||
var/out_of_combat_bonus = (time_since_last_action < (out_of_combat_timer * 10))? 0 : ((buffer_max * percent_regeneration_out_of_combat * 0.01))
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
// ignore_castun = same logic as Paralyze() in general
|
||||
// override_duration = If this is set, does Paralyze() for this duration.
|
||||
// override_stam = If this is set, does this amount of stamina damage.
|
||||
/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
|
||||
// knocktofloor - whether to knock them to the ground
|
||||
/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor = TRUE)
|
||||
if(!iscarbon(src))
|
||||
return Paralyze(amount, updating, ignore_canknockdown)
|
||||
if(!ignore_canknockdown && !(status_flags & CANKNOCKDOWN))
|
||||
@@ -13,7 +14,8 @@
|
||||
buckled.unbuckle_mob(src)
|
||||
var/drop_items = amount > 80 //80 is cutoff for old item dropping behavior
|
||||
var/stamdmg = isnull(override_stamdmg)? (amount * 0.25) : override_stamdmg
|
||||
KnockToFloor(drop_items, TRUE, updating)
|
||||
if(knocktofloor)
|
||||
KnockToFloor(drop_items, TRUE, updating)
|
||||
adjustStaminaLoss(stamdmg)
|
||||
if(!isnull(override_hardstun))
|
||||
Paralyze(override_hardstun)
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
t += "<span class='danger'>Temperature: [environment.return_temperature()] \n</span>"
|
||||
for(var/id in environment.get_gases())
|
||||
if(environment.get_moles(id))
|
||||
t+="<span class='notice'>[GLOB.meta_gas_names[id]]: [environment.get_moles(id)] \n</span>"
|
||||
t+="<span class='notice'>[GLOB.gas_data.names[id]]: [environment.get_moles(id)] \n</span>"
|
||||
|
||||
to_chat(usr, t)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
for(var/id in env_gases)
|
||||
var/gas_level = environment.get_moles(id)/total_moles
|
||||
if(gas_level > 0)
|
||||
airlist += list(list("name" = "[GLOB.meta_gas_names[id]]", "percentage" = round(gas_level*100, 0.01)))
|
||||
airlist += list(list("name" = "[GLOB.gas_data.names[id]]", "percentage" = round(gas_level*100, 0.01)))
|
||||
data["AirData"] = airlist
|
||||
else
|
||||
data["AirPressure"] = 0
|
||||
|
||||
@@ -139,13 +139,13 @@
|
||||
var/amount = air.get_moles(gasid)
|
||||
if(amount)
|
||||
gasdata.Add(list(list(
|
||||
"name"= GLOB.meta_gas_names[gasid],
|
||||
"name"= GLOB.gas_data.names[gasid],
|
||||
"amount" = round(100*amount/air.total_moles(),0.01))))
|
||||
|
||||
else
|
||||
for(var/gasid in air.get_gases())
|
||||
gasdata.Add(list(list(
|
||||
"name"= GLOB.meta_gas_names[gasid],
|
||||
"name"= GLOB.gas_data.names[gasid],
|
||||
"amount" = 0)))
|
||||
|
||||
data["gases"] = gasdata
|
||||
|
||||
@@ -45,3 +45,9 @@
|
||||
/datum/movespeed_modifier/status_effect/mkultra
|
||||
multiplicative_slowdown = -2
|
||||
blacklisted_movetypes= FLYING|FLOATING
|
||||
|
||||
/datum/movespeed_modifier/status_effect/stagger
|
||||
variable = TRUE
|
||||
|
||||
/datum/movespeed_modifier/status_effect/off_balance
|
||||
variable = TRUE
|
||||
|
||||
@@ -118,7 +118,7 @@ Contents:
|
||||
ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes = H.shoes
|
||||
ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes.slowdown--
|
||||
n_shoes.slowdown -= 0.5
|
||||
n_gloves = H.gloves
|
||||
ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
return TRUE
|
||||
@@ -139,7 +139,7 @@ Contents:
|
||||
REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
if(n_shoes)
|
||||
REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes.slowdown++
|
||||
n_shoes.slowdown += 0.5
|
||||
if(n_gloves)
|
||||
n_gloves.icon_state = "s-ninja"
|
||||
n_gloves.item_state = "s-ninja"
|
||||
|
||||
@@ -1389,13 +1389,7 @@
|
||||
charging = APC_NOT_CHARGING
|
||||
chargecount = 0
|
||||
longtermpower = max(-10,longtermpower - 2)
|
||||
if(cell.charge >= cur_used)
|
||||
cell.use(GLOB.CELLRATE * cur_used)
|
||||
else
|
||||
// This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
|
||||
equipment = autoset(equipment, 0)
|
||||
lighting = autoset(lighting, 0)
|
||||
environ = autoset(environ, 0)
|
||||
cell.use(min(GLOB.CELLRATE * cur_used, cell.charge))
|
||||
|
||||
// set channels based on remaining charge
|
||||
|
||||
|
||||
@@ -47,29 +47,29 @@
|
||||
if(!loaded_tank)
|
||||
return
|
||||
if(!bitcoinmining)
|
||||
if(loaded_tank.air_contents.get_moles(/datum/gas/plasma) < 0.0001)
|
||||
if(loaded_tank.air_contents.get_moles(GAS_PLASMA) < 0.0001)
|
||||
investigate_log("<font color='red'>out of fuel</font>.", INVESTIGATE_SINGULO)
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
Radio.talk_into(src, "Insufficient plasma in [get_area(src)] [src], ejecting \the [loaded_tank].", FREQ_ENGINEERING)
|
||||
eject()
|
||||
else
|
||||
var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.get_moles(/datum/gas/plasma))
|
||||
loaded_tank.air_contents.adjust_moles(/datum/gas/plasma, -gasdrained)
|
||||
loaded_tank.air_contents.adjust_moles(/datum/gas/tritium, gasdrained)
|
||||
var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.get_moles(GAS_PLASMA))
|
||||
loaded_tank.air_contents.adjust_moles(GAS_PLASMA, -gasdrained)
|
||||
loaded_tank.air_contents.adjust_moles(GAS_TRITIUM, gasdrained)
|
||||
|
||||
var/power_produced = RAD_COLLECTOR_OUTPUT
|
||||
add_avail(power_produced)
|
||||
stored_power-=power_produced
|
||||
else if(is_station_level(z) && SSresearch.science_tech)
|
||||
if(!loaded_tank.air_contents.get_moles(/datum/gas/tritium) || !loaded_tank.air_contents.get_moles(/datum/gas/oxygen))
|
||||
if(!loaded_tank.air_contents.get_moles(GAS_TRITIUM) || !loaded_tank.air_contents.get_moles(GAS_O2))
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
Radio.talk_into(src, "Insufficient oxygen and tritium in [get_area(src)] [src] to produce research points, ejecting \the [loaded_tank].", FREQ_ENGINEERING)
|
||||
eject()
|
||||
else
|
||||
var/gasdrained = bitcoinproduction_drain*drainratio
|
||||
loaded_tank.air_contents.adjust_moles(/datum/gas/tritium, -gasdrained)
|
||||
loaded_tank.air_contents.adjust_moles(/datum/gas/oxygen, -gasdrained)
|
||||
loaded_tank.air_contents.adjust_moles(/datum/gas/carbon_dioxide, gasdrained*2)
|
||||
loaded_tank.air_contents.adjust_moles(GAS_TRITIUM, -gasdrained)
|
||||
loaded_tank.air_contents.adjust_moles(GAS_O2, -gasdrained)
|
||||
loaded_tank.air_contents.adjust_moles(GAS_CO2, gasdrained*2)
|
||||
var/bitcoins_mined = stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG)
|
||||
if(D)
|
||||
@@ -84,7 +84,7 @@
|
||||
toggle_power()
|
||||
user.visible_message("[user.name] turns the [src.name] [active? "on":"off"].", \
|
||||
"<span class='notice'>You turn the [src.name] [active? "on":"off"].</span>")
|
||||
var/fuel = loaded_tank.air_contents.get_moles(/datum/gas/plasma)
|
||||
var/fuel = loaded_tank.air_contents.get_moles(GAS_PLASMA)
|
||||
investigate_log("turned [active?"<font color='green'>on</font>":"<font color='red'>off</font>"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"<font color='red'>It is empty</font>"].", INVESTIGATE_SINGULO)
|
||||
return
|
||||
else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user