Merge remote-tracking branch 'Upstream/master' into TGUI-3.0
This commit is contained in:
@@ -909,10 +909,9 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
|
||||
assoc = SDQL_expression(object, expressions_list[expression_list])
|
||||
if(assoc != null)
|
||||
// Need to insert the key like this to prevent duplicate keys fucking up.
|
||||
var/list/dummy = list()
|
||||
dummy[result] = assoc
|
||||
result = dummy
|
||||
val += result
|
||||
val[result] = assoc
|
||||
else
|
||||
val += list(result)
|
||||
else
|
||||
val = world.SDQL_var(object, expression, i, object, superuser, src)
|
||||
i = expression.len
|
||||
|
||||
@@ -573,7 +573,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.gases[/datum/gas/plasma] = 70
|
||||
Plasma.air_contents.set_moles(/datum/gas/plasma,70)
|
||||
Rad.drainratio = 0
|
||||
Rad.loaded_tank = Plasma
|
||||
Plasma.forceMove(Rad)
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/proc/show_air_status_to(turf/target, mob/user)
|
||||
var/datum/gas_mixture/env = target.return_air()
|
||||
var/list/env_gases = env.gases
|
||||
var/burning = FALSE
|
||||
if(isopenturf(target))
|
||||
var/turf/open/T = target
|
||||
if(T.active_hotspot)
|
||||
burning = TRUE
|
||||
|
||||
var/list/lines = list("<span class='adminnotice'>[AREACOORD(target)]: [env.temperature] K ([env.temperature - T0C] C), [env.return_pressure()] kPa[(burning)?(", <font color='red'>burning</font>"):(null)]</span>")
|
||||
for(var/id in env_gases)
|
||||
var/moles = env_gases[id]
|
||||
var/list/lines = list("<span class='adminnotice'>[AREACOORD(target)]: [env.return_temperature()] K ([env.return_temperature() - T0C] C), [env.return_pressure()] kPa[(burning)?(", <font color='red'>burning</font>"):(null)]</span>")
|
||||
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"
|
||||
to_chat(usr, lines.Join("\n"))
|
||||
|
||||
@@ -113,8 +113,7 @@
|
||||
for(var/i in 1 to healseverity)
|
||||
new /obj/effect/temp_visual/heal(targetturf, "#1E8CE1")
|
||||
if(totaldamage)
|
||||
L.adjustBruteLoss(-brutedamage)
|
||||
L.adjustFireLoss(-burndamage)
|
||||
L.heal_overall_damage(brutedamage, burndamage, only_organic = FALSE) //Maybe a machine god shouldn't murder augmented followers instead of healing them
|
||||
L.adjustOxyLoss(-oxydamage)
|
||||
L.adjustToxLoss(totaldamage * 0.5, TRUE, TRUE)
|
||||
clockwork_say(ranged_ability_user, text2ratvar("[has_holy_water ? "Heal tainted" : "Mend wounded"] flesh!"))
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
mind.add_antag_datum(/datum/antagonist/revenant)
|
||||
|
||||
//Life, Stat, Hud Updates, and Say
|
||||
/mob/living/simple_animal/revenant/BiologicalLife(seconds, times_fired)
|
||||
/mob/living/simple_animal/revenant/Life(seconds, times_fired)
|
||||
. = ..()
|
||||
if(stasis)
|
||||
return
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
return
|
||||
if(I.use_tool(src, user, 0, volume=40))
|
||||
status = TRUE
|
||||
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.return_temperature()-T0C]"
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] welded a single tank bomb. Temp: [bombtank.air_contents.return_temperature()-T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
|
||||
add_fingerprint(user)
|
||||
return TRUE
|
||||
@@ -145,8 +145,7 @@
|
||||
return
|
||||
|
||||
/obj/item/tank/proc/ignite() //This happens when a bomb is told to explode
|
||||
var/fuel_moles = air_contents.gases[/datum/gas/plasma] + air_contents.gases[/datum/gas/oxygen]/6
|
||||
GAS_GARBAGE_COLLECT(air_contents.gases)
|
||||
var/fuel_moles = air_contents.get_moles(/datum/gas/plasma) + air_contents.get_moles(/datum/gas/oxygen)/6
|
||||
var/datum/gas_mixture/bomb_mixture = air_contents.copy()
|
||||
var/strength = 1
|
||||
|
||||
@@ -156,7 +155,7 @@
|
||||
qdel(master)
|
||||
qdel(src)
|
||||
|
||||
if(bomb_mixture.temperature > (T0C + 400))
|
||||
if(bomb_mixture.return_temperature() > (T0C + 400))
|
||||
strength = (fuel_moles/15)
|
||||
|
||||
if(strength >=1)
|
||||
@@ -169,7 +168,7 @@
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(bomb_mixture.temperature > (T0C + 250))
|
||||
else if(bomb_mixture.return_temperature() > (T0C + 250))
|
||||
strength = (fuel_moles/20)
|
||||
|
||||
if(strength >=1)
|
||||
@@ -180,7 +179,7 @@
|
||||
ground_zero.assume_air(bomb_mixture)
|
||||
ground_zero.hotspot_expose(1000, 125)
|
||||
|
||||
else if(bomb_mixture.temperature > (T0C + 100))
|
||||
else if(bomb_mixture.return_temperature() > (T0C + 100))
|
||||
strength = (fuel_moles/25)
|
||||
|
||||
if (strength >=1)
|
||||
|
||||
@@ -172,6 +172,7 @@
|
||||
|
||||
/datum/asset/spritesheet/goonchat/register()
|
||||
InsertAll("emoji", 'icons/emoji.dmi')
|
||||
InsertAll("emoji", 'icons/emoji_32.dmi')
|
||||
|
||||
// pre-loading all lanugage icons also helps to avoid meta
|
||||
InsertAll("language", 'icons/misc/language.dmi')
|
||||
|
||||
@@ -9,46 +9,31 @@
|
||||
return
|
||||
|
||||
|
||||
/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh = FALSE, holo = FALSE)
|
||||
var/datum/gas_mixture/air_contents = return_air()
|
||||
if(!air_contents)
|
||||
return 0
|
||||
/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
if(!air)
|
||||
return
|
||||
|
||||
var/oxy = air_contents.gases[/datum/gas/oxygen]
|
||||
var/tox = air_contents.gases[/datum/gas/plasma]
|
||||
var/trit = air_contents.gases[/datum/gas/tritium]
|
||||
var/oxy = air.get_moles(/datum/gas/oxygen)
|
||||
if (oxy < 0.5)
|
||||
return
|
||||
var/tox = air.get_moles(/datum/gas/plasma)
|
||||
var/trit = air.get_moles(/datum/gas/tritium)
|
||||
if(active_hotspot)
|
||||
if(soh)
|
||||
if((tox > 0.5 || trit > 0.5) && oxy > 0.5)
|
||||
if(active_hotspot.temperature < exposed_temperature*50)
|
||||
active_hotspot.temperature = exposed_temperature*50
|
||||
if(tox > 0.5 || trit > 0.5)
|
||||
if(active_hotspot.temperature < exposed_temperature)
|
||||
active_hotspot.temperature = exposed_temperature
|
||||
if(active_hotspot.volume < exposed_volume)
|
||||
active_hotspot.volume = exposed_volume
|
||||
return 1
|
||||
|
||||
var/igniting = 0
|
||||
return
|
||||
|
||||
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (tox > 0.5 || trit > 0.5))
|
||||
igniting = 1
|
||||
|
||||
if(igniting)
|
||||
if(oxy < 0.5)
|
||||
return 0
|
||||
|
||||
active_hotspot = new /obj/effect/hotspot(src, holo)
|
||||
active_hotspot.temperature = exposed_temperature*50
|
||||
active_hotspot.volume = exposed_volume*25
|
||||
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)
|
||||
else
|
||||
var/datum/gas_mixture/heating = air_contents.remove_ratio(exposed_volume/air_contents.volume)
|
||||
heating.temperature = exposed_temperature
|
||||
heating.react()
|
||||
assume_air(heating)
|
||||
air_update_turf()
|
||||
return igniting
|
||||
|
||||
//This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile
|
||||
/obj/effect/hotspot
|
||||
@@ -67,11 +52,13 @@
|
||||
var/bypassing = FALSE
|
||||
var/visual_update_tick = 0
|
||||
|
||||
/obj/effect/hotspot/Initialize(mapload, holo = FALSE)
|
||||
/obj/effect/hotspot/Initialize(mapload, starting_volume, starting_temperature)
|
||||
. = ..()
|
||||
if(holo)
|
||||
flags_1 |= HOLOGRAM_1
|
||||
SSair.hotspots += src
|
||||
if(!isnull(starting_volume))
|
||||
volume = starting_volume
|
||||
if(!isnull(starting_temperature))
|
||||
temperature = starting_temperature
|
||||
perform_exposure()
|
||||
setDir(pick(GLOB.cardinals))
|
||||
air_update_turf()
|
||||
@@ -83,22 +70,19 @@
|
||||
|
||||
location.active_hotspot = src
|
||||
|
||||
if(volume > CELL_VOLUME*0.95)
|
||||
bypassing = TRUE
|
||||
else
|
||||
bypassing = FALSE
|
||||
bypassing = !just_spawned && (volume > CELL_VOLUME*0.95)
|
||||
|
||||
if(bypassing)
|
||||
if(!just_spawned)
|
||||
volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE
|
||||
temperature = location.air.temperature
|
||||
volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE
|
||||
temperature = location.air.return_temperature()
|
||||
else
|
||||
var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.volume)
|
||||
affected.temperature = temperature
|
||||
affected.react(src)
|
||||
temperature = affected.temperature
|
||||
volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE
|
||||
location.assume_air(affected)
|
||||
var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.return_volume())
|
||||
if(affected) //in case volume is 0
|
||||
affected.set_temperature(temperature)
|
||||
affected.react(src)
|
||||
temperature = affected.return_temperature()
|
||||
volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE
|
||||
location.assume_air(affected)
|
||||
|
||||
for(var/A in location)
|
||||
var/atom/AT = A
|
||||
@@ -164,7 +148,7 @@
|
||||
color = list(LERP(0.3, 1, 1-greyscale_fire) * heat_r,0.3 * heat_g * greyscale_fire,0.3 * heat_b * greyscale_fire, 0.59 * heat_r * greyscale_fire,LERP(0.59, 1, 1-greyscale_fire) * heat_g,0.59 * heat_b * greyscale_fire, 0.11 * heat_r * greyscale_fire,0.11 * heat_g * greyscale_fire,LERP(0.11, 1, 1-greyscale_fire) * heat_b, 0,0,0)
|
||||
alpha = heat_a
|
||||
|
||||
#define INSUFFICIENT(path) (location.air.gases[path] < 0.5)
|
||||
#define INSUFFICIENT(path) (location.air.get_moles(path) < 0.5)
|
||||
/obj/effect/hotspot/process()
|
||||
if(just_spawned)
|
||||
just_spawned = FALSE
|
||||
@@ -175,8 +159,7 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(location.excited_group)
|
||||
location.excited_group.reset_cooldowns()
|
||||
location.eg_reset_cooldowns()
|
||||
|
||||
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
|
||||
qdel(src)
|
||||
@@ -186,7 +169,8 @@
|
||||
return
|
||||
|
||||
//Not enough to burn
|
||||
if((location.air.gases[/datum/gas/plasma] < 0.5 && location.air.gases[/datum/gas/tritium] < 0.5) || location.air.gases[/datum/gas/oxygen] < 0.5)
|
||||
// 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))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
@@ -194,16 +178,15 @@
|
||||
|
||||
if(bypassing)
|
||||
icon_state = "3"
|
||||
if(!(flags_1 & HOLOGRAM_1))
|
||||
location.burn_tile()
|
||||
location.burn_tile()
|
||||
|
||||
//Possible spread due to radiated heat
|
||||
if(location.air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD)
|
||||
var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE
|
||||
if(location.air.return_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD)
|
||||
var/radiated_temperature = location.air.return_temperature()*FIRE_SPREAD_RADIOSITY_SCALE
|
||||
for(var/t in location.atmos_adjacent_turfs)
|
||||
var/turf/open/T = t
|
||||
if(!T.active_hotspot)
|
||||
T.hotspot_expose(radiated_temperature, CELL_VOLUME/4, flags_1 & HOLOGRAM_1)
|
||||
T.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
|
||||
|
||||
else
|
||||
if(volume > CELL_VOLUME*0.4)
|
||||
@@ -227,14 +210,13 @@
|
||||
var/turf/open/T = loc
|
||||
if(istype(T) && T.active_hotspot == src)
|
||||
T.active_hotspot = null
|
||||
if(!(flags_1 & HOLOGRAM_1))
|
||||
DestroyTurf()
|
||||
DestroyTurf()
|
||||
return ..()
|
||||
|
||||
/obj/effect/hotspot/proc/DestroyTurf()
|
||||
if(isturf(loc))
|
||||
var/turf/T = loc
|
||||
if(T.to_be_destroyed)
|
||||
if(T.to_be_destroyed && !T.changing_turf)
|
||||
var/chance_of_deletion
|
||||
if (T.heat_capacity) //beware of division by zero
|
||||
chance_of_deletion = T.max_fire_temperature_sustained / T.heat_capacity * 8 //there is no problem with prob(23456), min() was redundant --rastaf0
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
/turf/open/CanAtmosPass(turf/T, vertical = FALSE)
|
||||
var/dir = vertical? get_dir_multiz(src, T) : get_dir(src, T)
|
||||
var/opp = dir_inverse_multiz(dir)
|
||||
var/opp = REVERSE_DIR(dir)
|
||||
var/R = FALSE
|
||||
if(vertical && !(zAirOut(dir, T) && T.zAirIn(dir, src)))
|
||||
R = TRUE
|
||||
@@ -44,25 +44,32 @@
|
||||
return FALSE
|
||||
|
||||
/turf/proc/ImmediateCalculateAdjacentTurfs()
|
||||
var/canpass = CANATMOSPASS(src, src)
|
||||
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))
|
||||
continue
|
||||
if(!(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] = TRUE
|
||||
T.atmos_adjacent_turfs[src] = TRUE
|
||||
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)
|
||||
UNSETEMPTY(atmos_adjacent_turfs)
|
||||
src.atmos_adjacent_turfs = atmos_adjacent_turfs
|
||||
__update_extools_adjacent_turfs()
|
||||
|
||||
/turf/proc/__update_extools_adjacent_turfs()
|
||||
|
||||
|
||||
//returns a list of adjacent turfs that can share air with this one.
|
||||
//alldir includes adjacent diagonal tiles that can share
|
||||
@@ -111,9 +118,9 @@
|
||||
SSair.add_to_active(src,command)
|
||||
|
||||
/atom/movable/proc/move_update_air(turf/T)
|
||||
if(isturf(T))
|
||||
T.air_update_turf(1)
|
||||
air_update_turf(1)
|
||||
if(isturf(T))
|
||||
T.air_update_turf(1)
|
||||
air_update_turf(1)
|
||||
|
||||
/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires
|
||||
var/turf/open/T = get_turf(src)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
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
|
||||
@@ -23,21 +24,21 @@
|
||||
//used for spacewind
|
||||
var/pressure_difference = 0
|
||||
var/pressure_direction = 0
|
||||
var/turf/pressure_specific_target
|
||||
|
||||
var/datum/excited_group/excited_group
|
||||
var/excited = FALSE
|
||||
var/datum/gas_mixture/turf/air
|
||||
|
||||
var/obj/effect/hotspot/active_hotspot
|
||||
var/atmos_cooldown = 0
|
||||
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.copy_from_turf(src)
|
||||
update_air_ref()
|
||||
. = ..()
|
||||
|
||||
/turf/open/Destroy()
|
||||
@@ -48,6 +49,8 @@
|
||||
SSair.add_to_active(T)
|
||||
return ..()
|
||||
|
||||
/turf/proc/update_air_ref()
|
||||
|
||||
/////////////////GAS MIXTURE PROCS///////////////////
|
||||
|
||||
/turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
|
||||
@@ -89,15 +92,37 @@
|
||||
temperature_archived = temperature
|
||||
|
||||
/turf/open/archive()
|
||||
ARCHIVE(air)
|
||||
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()
|
||||
/turf/open/proc/set_excited()
|
||||
|
||||
/////////////////////////GAS OVERLAYS//////////////////////////////
|
||||
|
||||
|
||||
/turf/open/proc/update_visuals()
|
||||
var/list/new_overlay_types = tile_graphic()
|
||||
|
||||
var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance
|
||||
var/list/new_overlay_types = list()
|
||||
var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays()
|
||||
|
||||
if(!air) // 2019-05-14: was not able to get this path to fire in testing. Consider removing/looking at callers -Naksu
|
||||
if (atmos_overlay_types)
|
||||
for(var/overlay in atmos_overlay_types)
|
||||
vis_contents -= overlay
|
||||
src.atmos_overlay_types = null
|
||||
return
|
||||
|
||||
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])
|
||||
new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(air.get_moles(id) / MOLES_GAS_VISIBLE_STEP, 1))]
|
||||
|
||||
if (atmos_overlay_types)
|
||||
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
|
||||
@@ -112,19 +137,18 @@
|
||||
UNSETEMPTY(new_overlay_types)
|
||||
src.atmos_overlay_types = new_overlay_types
|
||||
|
||||
/turf/open/proc/tile_graphic()
|
||||
var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays()
|
||||
if(!air)
|
||||
return
|
||||
. = new /list
|
||||
var/list/gases = air.gases
|
||||
for(var/id in gases)
|
||||
if (nonoverlaying_gases[id])
|
||||
continue
|
||||
var/gas = gases[id]
|
||||
var/gas_overlay = GLOB.meta_gas_overlays[id]
|
||||
if(gas_overlay && gas > GLOB.meta_gas_visibility[id])
|
||||
. += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas / MOLES_GAS_VISIBLE_STEP, 1))]
|
||||
/turf/open/proc/set_visuals(list/new_overlay_types)
|
||||
if (atmos_overlay_types)
|
||||
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
|
||||
vis_contents -= overlay
|
||||
|
||||
if (length(new_overlay_types))
|
||||
if (atmos_overlay_types)
|
||||
vis_contents += new_overlay_types - atmos_overlay_types //don't add overlays that already exist
|
||||
else
|
||||
vis_contents += new_overlay_types
|
||||
UNSETEMPTY(new_overlay_types)
|
||||
src.atmos_overlay_types = new_overlay_types
|
||||
|
||||
/proc/typecache_of_gases_with_no_overlays()
|
||||
. = list()
|
||||
@@ -135,8 +159,8 @@
|
||||
|
||||
/////////////////////////////SIMULATION///////////////////////////////////
|
||||
|
||||
#define LAST_SHARE_CHECK \
|
||||
var/last_share = our_air.last_share;\
|
||||
/*#define LAST_SHARE_CHECK \
|
||||
var/last_share = our_air.get_last_share();\
|
||||
if(last_share > MINIMUM_AIR_TO_SUSPEND){\
|
||||
our_excited_group.reset_cooldowns();\
|
||||
cached_atmos_cooldown = 0;\
|
||||
@@ -144,127 +168,59 @@
|
||||
our_excited_group.dismantle_cooldown = 0;\
|
||||
cached_atmos_cooldown = 0;\
|
||||
}
|
||||
|
||||
*/
|
||||
/turf/proc/process_cell(fire_count)
|
||||
SSair.remove_from_active(src)
|
||||
|
||||
/turf/open/process_cell(fire_count)
|
||||
if(archived_cycle < fire_count) //archive self if not already done
|
||||
archive()
|
||||
|
||||
current_cycle = fire_count
|
||||
|
||||
//cache for sanic speed
|
||||
var/list/adjacent_turfs = atmos_adjacent_turfs
|
||||
var/datum/excited_group/our_excited_group = excited_group
|
||||
var/adjacent_turfs_length = LAZYLEN(adjacent_turfs)
|
||||
var/cached_atmos_cooldown = atmos_cooldown + 1
|
||||
|
||||
var/planet_atmos = planetary_atmos
|
||||
if (planet_atmos)
|
||||
adjacent_turfs_length++
|
||||
|
||||
var/datum/gas_mixture/our_air = air
|
||||
|
||||
for(var/t in adjacent_turfs)
|
||||
var/turf/open/enemy_tile = t
|
||||
|
||||
if(fire_count <= enemy_tile.current_cycle)
|
||||
/turf/open/proc/equalize_pressure_in_zone(cyclenum)
|
||||
/turf/open/proc/consider_firelocks(turf/T2)
|
||||
var/reconsider_adj = FALSE
|
||||
for(var/obj/machinery/door/firedoor/FD in T2)
|
||||
if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, src) != FD.dir)
|
||||
continue
|
||||
enemy_tile.archive()
|
||||
FD.emergency_pressure_stop()
|
||||
reconsider_adj = TRUE
|
||||
for(var/obj/machinery/door/firedoor/FD in src)
|
||||
if((FD.flags_1 & ON_BORDER_1) && get_dir(src, T2) != FD.dir)
|
||||
continue
|
||||
FD.emergency_pressure_stop()
|
||||
reconsider_adj = TRUE
|
||||
if(reconsider_adj)
|
||||
T2.ImmediateCalculateAdjacentTurfs() // We want those firelocks closed yesterday.
|
||||
|
||||
/******************* GROUP HANDLING START *****************************************************************/
|
||||
/turf/proc/handle_decompression_floor_rip()
|
||||
/turf/open/floor/handle_decompression_floor_rip(sum)
|
||||
if(sum > 20 && prob(clamp(sum / 10, 0, 30)))
|
||||
remove_tile()
|
||||
|
||||
var/should_share_air = FALSE
|
||||
var/datum/gas_mixture/enemy_air = enemy_tile.air
|
||||
|
||||
//cache for sanic speed
|
||||
var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group
|
||||
|
||||
if(our_excited_group && enemy_excited_group)
|
||||
if(our_excited_group != enemy_excited_group)
|
||||
//combine groups (this also handles updating the excited_group var of all involved turfs)
|
||||
our_excited_group.merge_groups(enemy_excited_group)
|
||||
our_excited_group = excited_group //update our cache
|
||||
should_share_air = TRUE
|
||||
|
||||
else if(our_air.compare(enemy_air))
|
||||
if(!enemy_tile.excited)
|
||||
SSair.add_to_active(enemy_tile)
|
||||
var/datum/excited_group/EG = our_excited_group || enemy_excited_group || new
|
||||
if(!our_excited_group)
|
||||
EG.add_turf(src)
|
||||
if(!enemy_excited_group)
|
||||
EG.add_turf(enemy_tile)
|
||||
our_excited_group = excited_group
|
||||
should_share_air = TRUE
|
||||
|
||||
//air sharing
|
||||
if(should_share_air)
|
||||
var/difference = our_air.share(enemy_air, adjacent_turfs_length)
|
||||
if(difference)
|
||||
if(difference > 0)
|
||||
consider_pressure_difference(enemy_tile, difference)
|
||||
else
|
||||
enemy_tile.consider_pressure_difference(src, -difference)
|
||||
LAST_SHARE_CHECK
|
||||
|
||||
|
||||
/******************* GROUP HANDLING FINISH *********************************************************************/
|
||||
|
||||
if (planet_atmos) //share our air with the "atmosphere" "above" the turf
|
||||
var/datum/gas_mixture/G = new
|
||||
G.copy_from_turf(src)
|
||||
ARCHIVE(G)
|
||||
if(our_air.compare(G))
|
||||
if(!our_excited_group)
|
||||
var/datum/excited_group/EG = new
|
||||
EG.add_turf(src)
|
||||
our_excited_group = excited_group
|
||||
our_air.share(G, adjacent_turfs_length)
|
||||
LAST_SHARE_CHECK
|
||||
|
||||
SSair.add_to_react_queue(src)
|
||||
|
||||
if((!our_excited_group && !(our_air.temperature > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION && consider_superconductivity(starting = TRUE))) \
|
||||
|| (cached_atmos_cooldown > (EXCITED_GROUP_DISMANTLE_CYCLES * 2)))
|
||||
SSair.remove_from_active(src)
|
||||
|
||||
atmos_cooldown = cached_atmos_cooldown
|
||||
|
||||
/turf/open/space/process_cell(fire_count) //dumb hack to prevent space pollution
|
||||
. = ..()
|
||||
var/datum/gas_mixture/immutable/I = space_gas
|
||||
I.after_process_cell()
|
||||
|
||||
/turf/proc/process_cell_reaction()
|
||||
SSair.remove_from_react_queue(src)
|
||||
|
||||
/turf/open/process_cell_reaction()
|
||||
air.react(src)
|
||||
update_visuals()
|
||||
SSair.remove_from_react_queue(src)
|
||||
return
|
||||
/turf/open/process_cell(fire_count)
|
||||
|
||||
//////////////////////////SPACEWIND/////////////////////////////
|
||||
|
||||
/turf/open/proc/consider_pressure_difference(turf/T, difference)
|
||||
SSair.high_pressure_delta |= src
|
||||
SSair.high_pressure_delta[src] = TRUE
|
||||
if(difference > pressure_difference)
|
||||
pressure_direction = get_dir(src, T)
|
||||
pressure_difference = difference
|
||||
|
||||
/turf/open/proc/high_pressure_movements()
|
||||
var/atom/movable/M
|
||||
var/multiplier = 1
|
||||
if(locate(/obj/structure/rack) in src)
|
||||
multiplier *= 0.1
|
||||
else if(locate(/obj/structure/table) in src)
|
||||
multiplier *= 0.2
|
||||
for(var/thing in src)
|
||||
M = thing
|
||||
if (!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
|
||||
M.experience_pressure_difference(pressure_difference, pressure_direction)
|
||||
M.experience_pressure_difference(pressure_difference * multiplier, pressure_direction, 0, pressure_specific_target)
|
||||
if(pressure_difference > 100)
|
||||
new /obj/effect/temp_visual/dir_setting/space_wind(src, pressure_direction, clamp(round(sqrt(pressure_difference) * 2), 10, 255))
|
||||
|
||||
/atom/movable/var/pressure_resistance = 10
|
||||
/atom/movable/var/last_high_pressure_movement_air_cycle = 0
|
||||
|
||||
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
|
||||
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target)
|
||||
var/const/PROBABILITY_OFFSET = 25
|
||||
var/const/PROBABILITY_BASE_PRECENT = 75
|
||||
var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5)
|
||||
@@ -275,93 +231,8 @@
|
||||
move_prob += pressure_resistance_prob_delta
|
||||
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)
|
||||
last_high_pressure_movement_air_cycle = SSair.times_fired
|
||||
|
||||
///////////////////////////EXCITED GROUPS/////////////////////////////
|
||||
|
||||
/datum/excited_group
|
||||
var/list/turf_list = list()
|
||||
var/breakdown_cooldown = 0
|
||||
var/dismantle_cooldown = 0
|
||||
|
||||
/datum/excited_group/New()
|
||||
SSair.excited_groups += src
|
||||
|
||||
/datum/excited_group/proc/add_turf(turf/open/T)
|
||||
turf_list += T
|
||||
T.excited_group = src
|
||||
reset_cooldowns()
|
||||
|
||||
/datum/excited_group/proc/merge_groups(datum/excited_group/E)
|
||||
if(turf_list.len > E.turf_list.len)
|
||||
SSair.excited_groups -= E
|
||||
for(var/t in E.turf_list)
|
||||
var/turf/open/T = t
|
||||
T.excited_group = src
|
||||
turf_list += T
|
||||
reset_cooldowns()
|
||||
else
|
||||
SSair.excited_groups -= src
|
||||
for(var/t in turf_list)
|
||||
var/turf/open/T = t
|
||||
T.excited_group = E
|
||||
E.turf_list += T
|
||||
E.reset_cooldowns()
|
||||
|
||||
/datum/excited_group/proc/reset_cooldowns()
|
||||
breakdown_cooldown = 0
|
||||
dismantle_cooldown = 0
|
||||
|
||||
//argument is so world start can clear out any turf differences quickly.
|
||||
/datum/excited_group/proc/self_breakdown(space_is_all_consuming = FALSE)
|
||||
var/datum/gas_mixture/A = new
|
||||
|
||||
//make local for sanic speed
|
||||
var/list/A_gases = A.gases
|
||||
var/list/turf_list = src.turf_list
|
||||
var/turflen = turf_list.len
|
||||
var/space_in_group = FALSE
|
||||
|
||||
for(var/t in turf_list)
|
||||
var/turf/open/T = t
|
||||
if (space_is_all_consuming && !space_in_group && istype(T.air, /datum/gas_mixture/immutable/space))
|
||||
space_in_group = TRUE
|
||||
qdel(A)
|
||||
A = new /datum/gas_mixture/immutable/space()
|
||||
A_gases = A.gases //update the cache
|
||||
break
|
||||
A.merge(T.air)
|
||||
|
||||
for(var/id in A_gases)
|
||||
A_gases[id] /= turflen
|
||||
|
||||
for(var/t in turf_list)
|
||||
var/turf/open/T = t
|
||||
T.air.copy_from(A)
|
||||
T.atmos_cooldown = 0
|
||||
T.update_visuals()
|
||||
|
||||
breakdown_cooldown = 0
|
||||
|
||||
/datum/excited_group/proc/dismantle()
|
||||
for(var/t in turf_list)
|
||||
var/turf/open/T = t
|
||||
T.excited = FALSE
|
||||
T.excited_group = null
|
||||
SSair.active_turfs -= T
|
||||
garbage_collect()
|
||||
|
||||
/datum/excited_group/proc/garbage_collect()
|
||||
for(var/t in turf_list)
|
||||
var/turf/open/T = t
|
||||
T.excited_group = null
|
||||
turf_list.Cut()
|
||||
SSair.excited_groups -= src
|
||||
|
||||
////////////////////////SUPERCONDUCTIVITY/////////////////////////////
|
||||
/atom/movable/proc/blocksTemperature()
|
||||
return FALSE
|
||||
|
||||
/turf/proc/conductivity_directions()
|
||||
if(archived_cycle < SSair.times_fired)
|
||||
archive()
|
||||
@@ -376,9 +247,6 @@
|
||||
. |= direction
|
||||
|
||||
/turf/proc/neighbor_conduct_with_src(turf/open/other)
|
||||
for (var/atom/movable/G in src)
|
||||
if (G.blocksTemperature())
|
||||
return
|
||||
if(!other.blocks_air) //Open but neighbor is solid
|
||||
other.temperature_share_open_to_solid(src)
|
||||
else //Both tiles are solid
|
||||
@@ -389,9 +257,7 @@
|
||||
if(blocks_air)
|
||||
..()
|
||||
return
|
||||
for (var/atom/movable/G in src)
|
||||
if (G.blocksTemperature())
|
||||
return
|
||||
|
||||
if(!other.blocks_air) //Both tiles are open
|
||||
var/turf/open/T = other
|
||||
T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
|
||||
@@ -410,8 +276,10 @@
|
||||
|
||||
if(!neighbor.thermal_conductivity)
|
||||
continue
|
||||
|
||||
if(neighbor.archived_cycle < SSair.times_fired)
|
||||
neighbor.archive()
|
||||
|
||||
neighbor.neighbor_conduct_with_src(src)
|
||||
|
||||
neighbor.consider_superconductivity()
|
||||
@@ -430,17 +298,18 @@
|
||||
//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.temperature))
|
||||
..((blocks_air ? temperature : air.return_temperature()))
|
||||
|
||||
/turf/proc/consider_superconductivity()
|
||||
if(!thermal_conductivity)
|
||||
return FALSE
|
||||
|
||||
SSair.active_super_conductivity |= src
|
||||
SSair.active_super_conductivity[src] = TRUE
|
||||
|
||||
return TRUE
|
||||
|
||||
/turf/open/consider_superconductivity(starting)
|
||||
if(air.temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
|
||||
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
|
||||
|
||||
@@ -16,90 +16,80 @@ 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
|
||||
var/list/gases = list()
|
||||
var/list/gas_archive = list()
|
||||
var/temperature = 0 //kelvins
|
||||
var/tmp/temperature_archived = 0
|
||||
var/volume = CELL_VOLUME //liters
|
||||
var/last_share = 0
|
||||
var/list/reaction_results = list()
|
||||
var/initial_volume = CELL_VOLUME //liters
|
||||
var/list/reaction_results
|
||||
var/list/analyzer_results //used for analyzer feedback - not initialized until its used
|
||||
var/gc_share = FALSE // Whether to call garbage_collect() on the sharer during shares, used for immutable mixtures
|
||||
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.
|
||||
|
||||
/datum/gas_mixture/New(volume)
|
||||
if (!isnull(volume))
|
||||
src.volume = volume
|
||||
initial_volume = volume
|
||||
ATMOS_EXTOOLS_CHECK
|
||||
__gasmixture_register()
|
||||
reaction_results = new
|
||||
|
||||
//PV = nRT
|
||||
/datum/gas_mixture/vv_edit_var(var_name, var_value)
|
||||
if(var_name == "_extools_pointer_gasmixture")
|
||||
return FALSE // please no. segfaults bad.
|
||||
return ..()
|
||||
/*
|
||||
/datum/gas_mixture/Del()
|
||||
__gasmixture_unregister()
|
||||
. = ..()*/
|
||||
|
||||
/datum/gas_mixture/proc/heat_capacity()
|
||||
/datum/gas_mixture/proc/__gasmixture_unregister()
|
||||
/datum/gas_mixture/proc/__gasmixture_register()
|
||||
|
||||
/datum/gas_mixture/proc/archived_heat_capacity()
|
||||
/proc/gas_types()
|
||||
var/list/L = subtypesof(/datum/gas)
|
||||
for(var/gt in L)
|
||||
var/datum/gas/G = gt
|
||||
L[gt] = initial(G.specific_heat)
|
||||
return L
|
||||
|
||||
/datum/gas_mixture/heat_capacity() //joules per kelvin
|
||||
var/list/cached_gases = gases
|
||||
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
|
||||
. = 0
|
||||
for(var/id in cached_gases)
|
||||
. += cached_gases[id] * cached_gasheats[id]
|
||||
|
||||
/datum/gas_mixture/archived_heat_capacity()
|
||||
// lots of copypasta but heat_capacity is the single proc called the most in a regular round, bar none, so performance loss adds up
|
||||
var/list/cached_gases = gas_archive
|
||||
var/list/cached_gasheats = GLOB.meta_gas_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
|
||||
for(var/id in cached_gases)
|
||||
. += cached_gases[id] * cached_gasheats[id]
|
||||
if(!.)
|
||||
. += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space
|
||||
|
||||
/datum/gas_mixture/turf/archived_heat_capacity() // Same as above except vacuums return HEAT_CAPACITY_VACUUM
|
||||
var/list/cached_gases = gas_archive
|
||||
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
|
||||
for(var/id in cached_gases)
|
||||
. += cached_gases[id] * cached_gasheats[id]
|
||||
if(!.)
|
||||
. += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space
|
||||
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
|
||||
|
||||
/datum/gas_mixture/proc/total_moles()
|
||||
var/cached_gases = gases
|
||||
TOTAL_MOLES(cached_gases, .)
|
||||
|
||||
/datum/gas_mixture/proc/return_pressure() //kilopascals
|
||||
if(volume > 0) // to prevent division by zero
|
||||
var/cached_gases = gases
|
||||
TOTAL_MOLES(cached_gases, .)
|
||||
. *= R_IDEAL_GAS_EQUATION * temperature / volume
|
||||
return
|
||||
return 0
|
||||
|
||||
/datum/gas_mixture/proc/return_temperature() //kelvins
|
||||
return temperature
|
||||
|
||||
/datum/gas_mixture/proc/set_min_heat_capacity(n)
|
||||
/datum/gas_mixture/proc/set_temperature(new_temp)
|
||||
/datum/gas_mixture/proc/set_volume(new_volume)
|
||||
/datum/gas_mixture/proc/get_moles(gas_type)
|
||||
/datum/gas_mixture/proc/set_moles(gas_type, moles)
|
||||
/datum/gas_mixture/proc/scrub_into(datum/gas_mixture/target, list/gases)
|
||||
/datum/gas_mixture/proc/mark_immutable()
|
||||
/datum/gas_mixture/proc/get_gases()
|
||||
/datum/gas_mixture/proc/multiply(factor)
|
||||
/datum/gas_mixture/proc/get_last_share()
|
||||
/datum/gas_mixture/proc/clear()
|
||||
|
||||
/datum/gas_mixture/proc/adjust_moles(gas_type, amt = 0)
|
||||
set_moles(gas_type, get_moles(gas_type) + amt)
|
||||
|
||||
/datum/gas_mixture/proc/return_volume() //liters
|
||||
return max(0, volume)
|
||||
|
||||
/datum/gas_mixture/proc/thermal_energy() //joules
|
||||
return THERMAL_ENERGY(src) //see code/__DEFINES/atmospherics.dm; use the define in performance critical areas
|
||||
|
||||
/datum/gas_mixture/proc/archive()
|
||||
//Update archived versions of variables
|
||||
//Returns: 1 in all cases
|
||||
|
||||
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
|
||||
//Merges all air from giver into self. Deletes giver.
|
||||
//Merges all air from giver into self. giver is untouched.
|
||||
//Returns: 1 if we are mutable, 0 otherwise
|
||||
|
||||
/datum/gas_mixture/proc/remove(amount)
|
||||
//Proportionally removes amount of gas from the gas_mixture
|
||||
//Removes amount of gas from the gas_mixture
|
||||
//Returns: gas_mixture with the gases removed
|
||||
|
||||
/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/remove_ratio(ratio)
|
||||
//Proportionally removes amount of gas from the gas_mixture
|
||||
//Returns: gas_mixture with the gases removed
|
||||
@@ -136,245 +126,63 @@ 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/archive()
|
||||
temperature_archived = temperature
|
||||
gas_archive = gases.Copy()
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/merge(datum/gas_mixture/giver)
|
||||
if(!giver)
|
||||
return 0
|
||||
|
||||
//heat transfer
|
||||
if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = heat_capacity()
|
||||
var/giver_heat_capacity = giver.heat_capacity()
|
||||
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
|
||||
if(combined_heat_capacity)
|
||||
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
|
||||
|
||||
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
|
||||
var/list/giver_gases = giver.gases
|
||||
//gas transfer
|
||||
for(var/giver_id in giver_gases)
|
||||
cached_gases[giver_id] += giver_gases[giver_id]
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/proc/__remove()
|
||||
/datum/gas_mixture/remove(amount)
|
||||
var/sum
|
||||
var/list/cached_gases = gases
|
||||
TOTAL_MOLES(cached_gases, sum)
|
||||
amount = min(amount, sum) //Can not take more air than tile has!
|
||||
if(amount <= 0)
|
||||
return null
|
||||
var/datum/gas_mixture/removed = new type
|
||||
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
|
||||
|
||||
removed.temperature = temperature
|
||||
for(var/id in cached_gases)
|
||||
removed_gases[id] = QUANTIZE((cached_gases[id] / sum) * amount)
|
||||
cached_gases[id] -= removed_gases[id]
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
__remove(removed, amount)
|
||||
|
||||
return removed
|
||||
|
||||
/datum/gas_mixture/proc/__remove_ratio()
|
||||
/datum/gas_mixture/remove_ratio(ratio)
|
||||
if(ratio <= 0)
|
||||
return null
|
||||
ratio = min(ratio, 1)
|
||||
|
||||
var/list/cached_gases = gases
|
||||
var/datum/gas_mixture/removed = new type
|
||||
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
|
||||
|
||||
removed.temperature = temperature
|
||||
for(var/id in cached_gases)
|
||||
removed_gases[id] = QUANTIZE(cached_gases[id] * ratio)
|
||||
cached_gases[id] -= removed_gases[id]
|
||||
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
__remove_ratio(removed, ratio)
|
||||
|
||||
return removed
|
||||
|
||||
/datum/gas_mixture/copy()
|
||||
var/list/cached_gases = gases
|
||||
var/datum/gas_mixture/copy = new type
|
||||
var/list/copy_gases = copy.gases
|
||||
|
||||
copy.temperature = temperature
|
||||
for(var/id in cached_gases)
|
||||
copy_gases[id] = cached_gases[id]
|
||||
copy.copy_from(src)
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
/datum/gas_mixture/copy_from(datum/gas_mixture/sample)
|
||||
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
|
||||
var/list/sample_gases = sample.gases
|
||||
|
||||
temperature = sample.temperature
|
||||
for(var/id in sample_gases)
|
||||
cached_gases[id] = sample_gases[id]
|
||||
|
||||
//remove all gases not in the sample
|
||||
cached_gases &= sample_gases
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/copy_from_turf(turf/model)
|
||||
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))
|
||||
temperature = model.temperature
|
||||
set_temperature(model.temperature)
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/parse_gas_string(gas_string)
|
||||
var/list/gases = src.gases
|
||||
var/list/gas = params2list(gas_string)
|
||||
if(gas["TEMP"])
|
||||
temperature = text2num(gas["TEMP"])
|
||||
set_temperature(text2num(gas["TEMP"]))
|
||||
gas -= "TEMP"
|
||||
gases.Cut()
|
||||
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
|
||||
gases[path] = text2num(gas[id])
|
||||
set_moles(path, text2num(gas[id]))
|
||||
archive()
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
|
||||
var/list/cached_gases = gases
|
||||
var/list/sharer_gases = sharer.gases
|
||||
|
||||
var/temperature_delta = temperature_archived - sharer.temperature_archived
|
||||
var/abs_temperature_delta = abs(temperature_delta)
|
||||
|
||||
var/old_self_heat_capacity = 0
|
||||
var/old_sharer_heat_capacity = 0
|
||||
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
old_self_heat_capacity = heat_capacity()
|
||||
old_sharer_heat_capacity = sharer.heat_capacity()
|
||||
|
||||
var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
|
||||
var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
|
||||
|
||||
var/moved_moles = 0
|
||||
var/abs_moved_moles = 0
|
||||
|
||||
//we're gonna define these vars outside of this for loop because as it turns out, var declaration is pricy
|
||||
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
|
||||
//GAS TRANSFER
|
||||
for(var/id in cached_gases | sharer_gases) // transfer gases
|
||||
|
||||
delta = QUANTIZE(gas_archive[id] - sharer.gas_archive[id])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
|
||||
|
||||
if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
gas_heat_capacity = delta * cached_gasheats[id]
|
||||
if(delta > 0)
|
||||
heat_capacity_self_to_sharer += gas_heat_capacity
|
||||
else
|
||||
heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative.
|
||||
|
||||
cached_gases[id] -= delta
|
||||
sharer_gases[id] += delta
|
||||
moved_moles += delta
|
||||
abs_moved_moles += abs(delta)
|
||||
|
||||
last_share = abs_moved_moles
|
||||
|
||||
//THERMAL ENERGY TRANSFER
|
||||
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
|
||||
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
|
||||
|
||||
//transfer of thermal energy (via changed heat capacity) between self and sharer
|
||||
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
|
||||
|
||||
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
|
||||
//thermal energy of the system (self and sharer) is unchanged
|
||||
|
||||
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
|
||||
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity
|
||||
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
|
||||
|
||||
if (initial(sharer.gc_share))
|
||||
GAS_GARBAGE_COLLECT(sharer.gases)
|
||||
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
var/our_moles
|
||||
TOTAL_MOLES(cached_gases,our_moles)
|
||||
var/their_moles
|
||||
TOTAL_MOLES(sharer_gases,their_moles)
|
||||
return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume
|
||||
|
||||
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
|
||||
//transfer of thermal energy (via conduction) between self and sharer
|
||||
if(sharer)
|
||||
sharer_temperature = sharer.temperature_archived
|
||||
var/temperature_delta = temperature_archived - sharer_temperature
|
||||
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = archived_heat_capacity()
|
||||
sharer_heat_capacity = sharer_heat_capacity || sharer.archived_heat_capacity()
|
||||
|
||||
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
|
||||
var/heat = conduction_coefficient*temperature_delta* \
|
||||
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
|
||||
|
||||
temperature = max(temperature - heat/self_heat_capacity, TCMB)
|
||||
sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB)
|
||||
if(sharer)
|
||||
sharer.temperature = sharer_temperature
|
||||
return sharer_temperature
|
||||
//thermal energy of the system (self and sharer) is unchanged
|
||||
|
||||
/datum/gas_mixture/compare(datum/gas_mixture/sample)
|
||||
var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
|
||||
var/list/cached_gases = gases
|
||||
|
||||
for(var/id in cached_gases | sample_gases) // compare gases from either mixture
|
||||
var/gas_moles = cached_gases[id]
|
||||
var/sample_moles = sample_gases[id]
|
||||
var/delta = abs(gas_moles - sample_moles)
|
||||
if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \
|
||||
delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)
|
||||
return id
|
||||
|
||||
var/our_moles
|
||||
TOTAL_MOLES(cached_gases, our_moles)
|
||||
if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
var/temp = temperature
|
||||
var/sample_temp = sample.temperature
|
||||
|
||||
var/temperature_delta = abs(temp - sample_temp)
|
||||
if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
|
||||
return "temp"
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
/datum/gas_mixture/react(datum/holder)
|
||||
. = NO_REACTION
|
||||
var/list/cached_gases = gases
|
||||
if(!length(cached_gases))
|
||||
if(!total_moles())
|
||||
return
|
||||
var/list/reactions = list()
|
||||
for(var/datum/gas_reaction/G in SSair.gas_reactions)
|
||||
if(cached_gases[G.major_gas])
|
||||
if(get_moles(G.major_gas))
|
||||
reactions += G
|
||||
if(!length(reactions))
|
||||
return
|
||||
reaction_results = new
|
||||
var/temp = temperature
|
||||
var/ener = THERMAL_ENERGY(src)
|
||||
var/temp = return_temperature()
|
||||
var/ener = thermal_energy()
|
||||
|
||||
reaction_loop:
|
||||
for(var/r in reactions)
|
||||
@@ -388,14 +196,13 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
for(var/id in min_reqs)
|
||||
if (id == "TEMP" || id == "ENER")
|
||||
continue
|
||||
if(cached_gases[id] < min_reqs[id])
|
||||
if(get_moles(id) < min_reqs[id])
|
||||
continue reaction_loop
|
||||
//at this point, all minimum requirements for the reaction are satisfied.
|
||||
|
||||
/* currently no reactions have maximum requirements, so we can leave the checks commented out for a slight performance boost
|
||||
PLEASE DO NOT REMOVE THIS CODE. the commenting is here only for a performance increase.
|
||||
enabling these checks should be as easy as possible and the fact that they are disabled should be as clear as possible
|
||||
|
||||
var/list/max_reqs = reaction.max_requirements
|
||||
if((max_reqs["TEMP"] && temp > max_reqs["TEMP"]) \
|
||||
|| (max_reqs["ENER"] && ener > max_reqs["ENER"]))
|
||||
@@ -410,8 +217,6 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
. |= reaction.react(src, holder)
|
||||
if (. & STOP_REACTIONS)
|
||||
break
|
||||
if(.)
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
|
||||
//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
|
||||
@@ -420,16 +225,50 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
//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 * temperature) / BREATH_VOLUME
|
||||
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 * temperature)
|
||||
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * return_temperature())
|
||||
|
||||
//Mathematical proofs:
|
||||
/*
|
||||
get_breath_partial_pressure(gas_pp) --> gas_pp/total_moles()*breath_pp = pp
|
||||
get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
|
||||
|
||||
10/20*5 = 2.5
|
||||
10 = 2.5/5*20
|
||||
*/
|
||||
|
||||
/datum/gas_mixture/turf
|
||||
|
||||
/*
|
||||
/mob/verb/profile_atmos()
|
||||
/world{loop_checks = 0;}
|
||||
var/datum/gas_mixture/A = new
|
||||
var/datum/gas_mixture/B = new
|
||||
A.parse_gas_string("o2=200;n2=800;TEMP=50")
|
||||
B.parse_gas_string("co2=500;plasma=500;TEMP=5000")
|
||||
var/pa
|
||||
var/pb
|
||||
pa = world.tick_usage
|
||||
for(var/I in 1 to 100000)
|
||||
B.transfer_to(A, 1)
|
||||
A.transfer_to(B, 1)
|
||||
pb = world.tick_usage
|
||||
var/total_time = (pb-pa) * world.tick_lag
|
||||
to_chat(src, "Total time (gas transfer): [total_time]ms")
|
||||
to_chat(src, "Operations per second: [100000 / (total_time/1000)]")
|
||||
pa = world.tick_usage
|
||||
for(var/I in 1 to 100000)
|
||||
B.total_moles();
|
||||
pb = world.tick_usage
|
||||
total_time = (pb-pa) * world.tick_lag
|
||||
to_chat(src, "Total time (total_moles): [total_time]ms")
|
||||
to_chat(src, "Operations per second: [100000 / (total_time/1000)]")
|
||||
pa = world.tick_usage
|
||||
for(var/I in 1 to 100000)
|
||||
new /datum/gas_mixture
|
||||
pb = world.tick_usage
|
||||
total_time = (pb-pa) * world.tick_lag
|
||||
to_chat(src, "Total time (new gas mixture): [total_time]ms")
|
||||
to_chat(src, "Operations per second: [100000 / (total_time/1000)]")
|
||||
*/
|
||||
|
||||
@@ -2,73 +2,29 @@
|
||||
//it can be changed, but any changes will ultimately be undone before they can have any effect
|
||||
|
||||
/datum/gas_mixture/immutable
|
||||
var/initial_temperature
|
||||
gc_share = TRUE
|
||||
var/initial_temperature = 0
|
||||
|
||||
/datum/gas_mixture/immutable/New()
|
||||
..()
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
set_temperature(initial_temperature)
|
||||
populate()
|
||||
mark_immutable()
|
||||
|
||||
/datum/gas_mixture/immutable/merge()
|
||||
return 0 //we're immutable.
|
||||
/datum/gas_mixture/immutable/proc/populate()
|
||||
return
|
||||
|
||||
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
|
||||
/datum/gas_mixture/immutable/react()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/copy()
|
||||
return new type //we're immutable, so we can just return a new instance.
|
||||
|
||||
/datum/gas_mixture/immutable/copy_from()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/copy_from_turf()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/parse_gas_string()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
|
||||
. = ..()
|
||||
temperature = initial_temperature
|
||||
|
||||
/datum/gas_mixture/immutable/proc/after_process_cell()
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
|
||||
//used by space tiles
|
||||
/datum/gas_mixture/immutable/space
|
||||
initial_temperature = TCMB
|
||||
|
||||
/datum/gas_mixture/immutable/space/heat_capacity()
|
||||
return HEAT_CAPACITY_VACUUM
|
||||
|
||||
/datum/gas_mixture/immutable/space/remove()
|
||||
return copy() //we're always empty, so we can just return a copy.
|
||||
|
||||
/datum/gas_mixture/immutable/space/remove_ratio()
|
||||
return copy() //we're always empty, so we can just return a copy.
|
||||
|
||||
/datum/gas_mixture/immutable/space/populate()
|
||||
set_min_heat_capacity(HEAT_CAPACITY_VACUUM)
|
||||
|
||||
//used by cloners
|
||||
/datum/gas_mixture/immutable/cloner
|
||||
initial_temperature = T20C
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/New()
|
||||
/datum/gas_mixture/immutable/cloner/populate()
|
||||
..()
|
||||
gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/heat_capacity()
|
||||
return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20
|
||||
set_moles(/datum/gas/nitrogen, MOLES_O2STANDARD + MOLES_N2STANDARD)
|
||||
|
||||
@@ -63,11 +63,11 @@
|
||||
/datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder)
|
||||
var/turf/open/location = isturf(holder) ? holder : null
|
||||
. = NO_REACTION
|
||||
if (air.temperature <= WATER_VAPOR_FREEZE)
|
||||
if (air.return_temperature() <= WATER_VAPOR_FREEZE)
|
||||
if(location && location.freon_gas_act())
|
||||
. = REACTING
|
||||
else if(location && location.water_vapor_gas_act())
|
||||
air.gases[/datum/gas/water_vapor] -= MOLES_GAS_VISIBLE
|
||||
air.adjust_moles(/datum/gas/water_vapor,-MOLES_GAS_VISIBLE)
|
||||
. = REACTING
|
||||
|
||||
//tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic
|
||||
@@ -86,38 +86,37 @@
|
||||
/datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder)
|
||||
var/energy_released = 0
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
|
||||
var/temperature = air.temperature
|
||||
var/temperature = air.return_temperature()
|
||||
var/list/cached_results = air.reaction_results
|
||||
cached_results["fire"] = 0
|
||||
var/turf/open/location = isturf(holder) ? holder : null
|
||||
|
||||
var/burned_fuel = 0
|
||||
if(cached_gases[/datum/gas/oxygen] < cached_gases[/datum/gas/tritium])
|
||||
burned_fuel = cached_gases[/datum/gas/oxygen]/TRITIUM_BURN_OXY_FACTOR
|
||||
cached_gases[/datum/gas/tritium] -= burned_fuel
|
||||
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)
|
||||
else
|
||||
burned_fuel = cached_gases[/datum/gas/tritium]*TRITIUM_BURN_TRIT_FACTOR
|
||||
cached_gases[/datum/gas/tritium] -= cached_gases[/datum/gas/tritium]/TRITIUM_BURN_TRIT_FACTOR
|
||||
cached_gases[/datum/gas/oxygen] -= cached_gases[/datum/gas/tritium]
|
||||
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))
|
||||
|
||||
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)
|
||||
|
||||
cached_gases[/datum/gas/water_vapor] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
|
||||
air.adjust_moles(/datum/gas/water_vapor, burned_fuel/TRITIUM_BURN_OXY_FACTOR)
|
||||
|
||||
cached_results["fire"] += burned_fuel
|
||||
|
||||
if(energy_released > 0)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
|
||||
air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity)
|
||||
|
||||
//let the floor know a fire is happening
|
||||
if(istype(location))
|
||||
temperature = air.temperature
|
||||
temperature = air.return_temperature()
|
||||
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
|
||||
location.hotspot_expose(temperature, CELL_VOLUME)
|
||||
for(var/I in location)
|
||||
@@ -143,8 +142,7 @@
|
||||
/datum/gas_reaction/plasmafire/react(datum/gas_mixture/air, datum/holder)
|
||||
var/energy_released = 0
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
|
||||
var/temperature = air.temperature
|
||||
var/temperature = air.return_temperature()
|
||||
var/list/cached_results = air.reaction_results
|
||||
cached_results["fire"] = 0
|
||||
var/turf/open/location = isturf(holder) ? holder : null
|
||||
@@ -163,21 +161,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(cached_gases[/datum/gas/oxygen] / cached_gases[/datum/gas/plasma] > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
|
||||
if(air.get_moles(/datum/gas/oxygen) / air.get_moles(/datum/gas/plasma) > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
|
||||
super_saturation = TRUE
|
||||
if(cached_gases[/datum/gas/oxygen] > cached_gases[/datum/gas/plasma]*PLASMA_OXYGEN_FULLBURN)
|
||||
plasma_burn_rate = (cached_gases[/datum/gas/plasma]*temperature_scale)/PLASMA_BURN_RATE_DELTA
|
||||
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
|
||||
else
|
||||
plasma_burn_rate = (temperature_scale*(cached_gases[/datum/gas/oxygen]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
|
||||
plasma_burn_rate = (temperature_scale*(air.get_moles(/datum/gas/oxygen)/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
|
||||
|
||||
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
|
||||
plasma_burn_rate = min(plasma_burn_rate,cached_gases[/datum/gas/plasma],cached_gases[/datum/gas/oxygen]/oxygen_burn_rate) //Ensures matter is conserved properly
|
||||
cached_gases[/datum/gas/plasma] = QUANTIZE(cached_gases[/datum/gas/plasma] - plasma_burn_rate)
|
||||
cached_gases[/datum/gas/oxygen] = QUANTIZE(cached_gases[/datum/gas/oxygen] - (plasma_burn_rate * oxygen_burn_rate))
|
||||
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)))
|
||||
if (super_saturation)
|
||||
cached_gases[/datum/gas/tritium] += plasma_burn_rate
|
||||
air.adjust_moles(/datum/gas/tritium, plasma_burn_rate)
|
||||
else
|
||||
cached_gases[/datum/gas/carbon_dioxide] += plasma_burn_rate
|
||||
air.adjust_moles(/datum/gas/carbon_dioxide, plasma_burn_rate)
|
||||
|
||||
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
|
||||
|
||||
@@ -186,11 +184,11 @@
|
||||
if(energy_released > 0)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
|
||||
air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity)
|
||||
|
||||
//let the floor know a fire is happening
|
||||
if(istype(location))
|
||||
temperature = air.temperature
|
||||
temperature = air.return_temperature()
|
||||
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
|
||||
location.hotspot_expose(temperature, CELL_VOLUME)
|
||||
for(var/I in location)
|
||||
@@ -218,7 +216,6 @@
|
||||
/datum/gas/carbon_dioxide = FUSION_MOLE_THRESHOLD)
|
||||
|
||||
/datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder)
|
||||
var/list/cached_gases = air.gases
|
||||
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
|
||||
@@ -230,14 +227,14 @@
|
||||
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 = cached_gases[/datum/gas/plasma]
|
||||
var/initial_carbon = cached_gases[/datum/gas/carbon_dioxide]
|
||||
var/scale_factor = (air.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.volume-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus
|
||||
var/initial_plasma = air.get_moles(/datum/gas/plasma)
|
||||
var/initial_carbon = air.get_moles(/datum/gas/carbon_dioxide)
|
||||
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
|
||||
for (var/gas_id in cached_gases)
|
||||
gas_power += (gas_fusion_powers[gas_id]*cached_gases[gas_id])
|
||||
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
|
||||
cached_scan_results[id] = instability//used for analyzer feedback
|
||||
|
||||
@@ -249,9 +246,9 @@
|
||||
carbon = MODULUS(carbon - plasma, toroidal_size)
|
||||
|
||||
|
||||
cached_gases[/datum/gas/plasma] = plasma*scale_factor + FUSION_MOLE_THRESHOLD //Scales the gases back up
|
||||
cached_gases[/datum/gas/carbon_dioxide] = carbon*scale_factor + FUSION_MOLE_THRESHOLD
|
||||
var/delta_plasma = initial_plasma - cached_gases[/datum/gas/plasma]
|
||||
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)
|
||||
|
||||
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)
|
||||
@@ -260,17 +257,17 @@
|
||||
reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5
|
||||
|
||||
if(air.thermal_energy() + reaction_energy < 0) //No using energy that doesn't exist.
|
||||
cached_gases[/datum/gas/plasma] = initial_plasma
|
||||
cached_gases[/datum/gas/carbon_dioxide] = initial_carbon
|
||||
air.set_moles(/datum/gas/plasma,initial_plasma)
|
||||
air.set_moles(/datum/gas/carbon_dioxide, initial_carbon)
|
||||
return NO_REACTION
|
||||
cached_gases[/datum/gas/tritium] -= FUSION_TRITIUM_MOLES_USED
|
||||
air.adjust_moles(/datum/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)
|
||||
cached_gases[/datum/gas/oxygen] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)
|
||||
cached_gases[/datum/gas/nitrous_oxide] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)
|
||||
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))
|
||||
else
|
||||
cached_gases[/datum/gas/bz] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)
|
||||
cached_gases[/datum/gas/nitryl] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)
|
||||
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))
|
||||
|
||||
if(reaction_energy)
|
||||
if(location)
|
||||
@@ -282,7 +279,7 @@
|
||||
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = clamp(((air.temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY)
|
||||
air.set_temperature(clamp(((air.return_temperature()*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY))
|
||||
return REACTING
|
||||
|
||||
/datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst.
|
||||
@@ -299,22 +296,21 @@
|
||||
)
|
||||
|
||||
/datum/gas_reaction/nitrylformation/react(datum/gas_mixture/air)
|
||||
var/list/cached_gases = air.gases
|
||||
var/temperature = air.temperature
|
||||
var/temperature = air.return_temperature()
|
||||
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),cached_gases[/datum/gas/oxygen],cached_gases[/datum/gas/nitrogen])
|
||||
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),air.get_moles(/datum/gas/oxygen),air.get_moles(/datum/gas/nitrogen))
|
||||
var/energy_used = heat_efficency*NITRYL_FORMATION_ENERGY
|
||||
if ((cached_gases[/datum/gas/oxygen] - heat_efficency < 0 )|| (cached_gases[/datum/gas/nitrogen] - heat_efficency < 0)) //Shouldn't produce gas from nothing.
|
||||
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.
|
||||
return NO_REACTION
|
||||
cached_gases[/datum/gas/oxygen] -= heat_efficency
|
||||
cached_gases[/datum/gas/nitrogen] -= heat_efficency
|
||||
cached_gases[/datum/gas/nitryl] += heat_efficency*2
|
||||
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)
|
||||
|
||||
if(energy_used > 0)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB)
|
||||
air.set_temperature(max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB))
|
||||
return REACTING
|
||||
|
||||
/datum/gas_reaction/bzformation //Formation of BZ by combining plasma and tritium at low pressures. Exothermic.
|
||||
@@ -330,27 +326,26 @@
|
||||
|
||||
|
||||
/datum/gas_reaction/bzformation/react(datum/gas_mixture/air)
|
||||
var/list/cached_gases = air.gases
|
||||
var/temperature = air.temperature
|
||||
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(cached_gases[/datum/gas/plasma]/cached_gases[/datum/gas/nitrous_oxide],1))),cached_gases[/datum/gas/nitrous_oxide],cached_gases[/datum/gas/plasma]/2)
|
||||
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/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
|
||||
if ((cached_gases[/datum/gas/nitrous_oxide] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma] - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing.
|
||||
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.
|
||||
return NO_REACTION
|
||||
cached_gases[/datum/gas/bz] += reaction_efficency
|
||||
if(reaction_efficency == cached_gases[/datum/gas/nitrous_oxide])
|
||||
cached_gases[/datum/gas/bz] -= min(pressure,1)
|
||||
cached_gases[/datum/gas/oxygen] += min(pressure,1)
|
||||
cached_gases[/datum/gas/nitrous_oxide] -= reaction_efficency
|
||||
cached_gases[/datum/gas/plasma] -= 2*reaction_efficency
|
||||
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)
|
||||
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((reaction_efficency**2)*BZ_RESEARCH_SCALE),BZ_RESEARCH_MAX_AMOUNT)
|
||||
|
||||
if(energy_released > 0)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB)
|
||||
air.set_temperature(max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB))
|
||||
return REACTING
|
||||
|
||||
/datum/gas_reaction/stimformation //Stimulum formation follows a strange pattern of how effective it will be at a given temperature, having some multiple peaks and some large dropoffs. Exo and endo thermic.
|
||||
@@ -367,24 +362,22 @@
|
||||
"TEMP" = STIMULUM_HEAT_SCALE/2)
|
||||
|
||||
/datum/gas_reaction/stimformation/react(datum/gas_mixture/air)
|
||||
var/list/cached_gases = air.gases
|
||||
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/heat_scale = min(air.temperature/STIMULUM_HEAT_SCALE,cached_gases[/datum/gas/tritium],cached_gases[/datum/gas/plasma],cached_gases[/datum/gas/nitryl])
|
||||
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/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 ((cached_gases[/datum/gas/tritium] - heat_scale < 0 )|| (cached_gases[/datum/gas/plasma] - heat_scale < 0) || (cached_gases[/datum/gas/nitryl] - heat_scale < 0)) //Shouldn't produce gas from nothing.
|
||||
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.
|
||||
return NO_REACTION
|
||||
cached_gases[/datum/gas/stimulum]+= heat_scale/10
|
||||
cached_gases[/datum/gas/tritium] -= heat_scale
|
||||
cached_gases[/datum/gas/plasma] -= heat_scale
|
||||
cached_gases[/datum/gas/nitryl] -= heat_scale
|
||||
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)
|
||||
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, STIMULUM_RESEARCH_AMOUNT*max(stim_energy_change,0))
|
||||
if(stim_energy_change)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = max(((air.temperature*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB)
|
||||
air.set_temperature(max(((air.return_temperature()*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB))
|
||||
return REACTING
|
||||
|
||||
/datum/gas_reaction/nobliumformation //Hyper-Noblium formation is extrememly endothermic, but requires high temperatures to start. Due to its high mass, hyper-nobelium uses large amounts of nitrogen and tritium. BZ can be used as a catalyst to make it less endothermic.
|
||||
@@ -399,22 +392,21 @@
|
||||
"TEMP" = 5000000)
|
||||
|
||||
/datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air)
|
||||
var/list/cached_gases = air.gases
|
||||
var/old_heat_capacity = air.heat_capacity()
|
||||
var/nob_formed = min((cached_gases[/datum/gas/nitrogen]+cached_gases[/datum/gas/tritium])/100,cached_gases[/datum/gas/tritium]/10,cached_gases[/datum/gas/nitrogen]/20)
|
||||
var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(cached_gases[/datum/gas/bz],1)))
|
||||
if ((cached_gases[/datum/gas/tritium] - 10*nob_formed < 0) || (cached_gases[/datum/gas/nitrogen] - 20*nob_formed < 0))
|
||||
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))
|
||||
return NO_REACTION
|
||||
cached_gases[/datum/gas/tritium] -= 10*nob_formed
|
||||
cached_gases[/datum/gas/nitrogen] -= 20*nob_formed
|
||||
cached_gases[/datum/gas/hypernoblium]+= nob_formed
|
||||
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)
|
||||
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, nob_formed*NOBLIUM_RESEARCH_AMOUNT)
|
||||
|
||||
if (nob_formed)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
air.temperature = max(((air.temperature*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB)
|
||||
air.set_temperature(max(((air.return_temperature()*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB))
|
||||
|
||||
|
||||
/datum/gas_reaction/miaster //dry heat sterilization: clears out pathogens in the air
|
||||
@@ -429,16 +421,15 @@
|
||||
)
|
||||
|
||||
/datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder)
|
||||
var/list/cached_gases = air.gases
|
||||
// As the name says it, it needs to be dry
|
||||
if(cached_gases[/datum/gas/water_vapor] && cached_gases[/datum/gas/water_vapor]/air.total_moles() > 0.1)
|
||||
if(air.get_moles(/datum/gas/water_vapor) && air.get_moles(/datum/gas/water_vapor)/air.total_moles() > 0.1)
|
||||
return
|
||||
|
||||
//Replace miasma with oxygen
|
||||
var/cleaned_air = min(cached_gases[/datum/gas/miasma], 20 + (air.temperature - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20)
|
||||
cached_gases[/datum/gas/miasma] -= cleaned_air
|
||||
cached_gases[/datum/gas/oxygen] += cleaned_air
|
||||
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)
|
||||
|
||||
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
|
||||
air.temperature += cleaned_air * 0.002
|
||||
air.set_temperature(air.return_temperature() + cleaned_air * 0.002)
|
||||
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
#ifdef EXTOOLS_BROKE
|
||||
|
||||
/datum/gas_mixture
|
||||
var/list/gases = list()
|
||||
var/temperature = 0 //kelvins
|
||||
var/tmp/temperature_archived = 0
|
||||
var/volume = CELL_VOLUME //liters
|
||||
var/last_share = 0
|
||||
|
||||
/datum/gas_mixture/heat_capacity() //joules per kelvin
|
||||
var/list/cached_gases = gases
|
||||
var/list/cached_gasheats = GLOB.meta_gas_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
|
||||
for(var/id in cached_gases)
|
||||
. += cached_gases[id] * cached_gasheats[id]
|
||||
if(!.)
|
||||
. += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space
|
||||
|
||||
//prefer this to gas_mixture/total_moles in performance critical areas
|
||||
#define TOTAL_MOLES(cached_gases, out_var)\
|
||||
out_var = 0;\
|
||||
for(var/total_moles_id in cached_gases){\
|
||||
out_var += cached_gases[total_moles_id];\
|
||||
}
|
||||
|
||||
#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity())
|
||||
|
||||
/datum/gas_mixture/total_moles()
|
||||
var/cached_gases = gases
|
||||
TOTAL_MOLES(cached_gases, .)
|
||||
|
||||
/datum/gas_mixture/return_pressure() //kilopascals
|
||||
if(volume > 0) // to prevent division by zero
|
||||
var/cached_gases = gases
|
||||
TOTAL_MOLES(cached_gases, .)
|
||||
. *= R_IDEAL_GAS_EQUATION * temperature / volume
|
||||
return
|
||||
return 0
|
||||
|
||||
/datum/gas_mixture/return_temperature() //kelvins
|
||||
return temperature
|
||||
|
||||
/datum/gas_mixture/set_min_heat_capacity(n)
|
||||
return
|
||||
/datum/gas_mixture/set_temperature(new_temp)
|
||||
temperature = new_temp
|
||||
/datum/gas_mixture/set_volume(new_volume)
|
||||
volume = new_volume
|
||||
/datum/gas_mixture/get_moles(gas_type)
|
||||
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)
|
||||
if(isnull(target))
|
||||
return FALSE
|
||||
|
||||
var/list/removed_gases = target.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)
|
||||
/datum/gas_mixture/mark_immutable()
|
||||
return
|
||||
/datum/gas_mixture/get_gases()
|
||||
return gases
|
||||
/datum/gas_mixture/multiply(factor)
|
||||
for(var/id in gases)
|
||||
gases[id] *= factor
|
||||
/datum/gas_mixture/get_last_share()
|
||||
return last_share
|
||||
/datum/gas_mixture/clear()
|
||||
gases.Cut()
|
||||
|
||||
/datum/gas_mixture/return_volume()
|
||||
return volume // wow!
|
||||
|
||||
/datum/gas_mixture/thermal_energy()
|
||||
return THERMAL_ENERGY(src)
|
||||
|
||||
/datum/gas_mixture/archive()
|
||||
temperature_archived = temperature
|
||||
gas_archive = gases.Copy()
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/merge(datum/gas_mixture/giver)
|
||||
if(!giver)
|
||||
return 0
|
||||
|
||||
//heat transfer
|
||||
if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = heat_capacity()
|
||||
var/giver_heat_capacity = giver.heat_capacity()
|
||||
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
|
||||
if(combined_heat_capacity)
|
||||
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
|
||||
|
||||
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
|
||||
var/list/giver_gases = giver.gases
|
||||
//gas transfer
|
||||
for(var/giver_id in giver_gases)
|
||||
cached_gases[giver_id] += giver_gases[giver_id]
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/remove(amount)
|
||||
var/sum
|
||||
var/list/cached_gases = gases
|
||||
TOTAL_MOLES(cached_gases, sum)
|
||||
amount = min(amount, sum) //Can not take more air than tile has!
|
||||
if(amount <= 0)
|
||||
return null
|
||||
var/datum/gas_mixture/removed = new type
|
||||
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
|
||||
|
||||
removed.temperature = temperature
|
||||
for(var/id in cached_gases)
|
||||
removed_gases[id] = QUANTIZE((cached_gases[id] / sum) * amount)
|
||||
cached_gases[id] -= removed_gases[id]
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
|
||||
return removed
|
||||
|
||||
/datum/gas_mixture/remove_ratio(ratio)
|
||||
if(ratio <= 0)
|
||||
return null
|
||||
ratio = min(ratio, 1)
|
||||
|
||||
var/list/cached_gases = gases
|
||||
var/datum/gas_mixture/removed = new type
|
||||
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
|
||||
|
||||
removed.temperature = temperature
|
||||
for(var/id in cached_gases)
|
||||
removed_gases[id] = QUANTIZE(cached_gases[id] * ratio)
|
||||
cached_gases[id] -= removed_gases[id]
|
||||
|
||||
GAS_GARBAGE_COLLECT(gases)
|
||||
|
||||
return removed
|
||||
|
||||
/datum/gas_mixture/copy()
|
||||
var/list/cached_gases = gases
|
||||
var/datum/gas_mixture/copy = new type
|
||||
var/list/copy_gases = copy.gases
|
||||
|
||||
copy.temperature = temperature
|
||||
for(var/id in cached_gases)
|
||||
copy_gases[id] = cached_gases[id]
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
/datum/gas_mixture/copy_from(datum/gas_mixture/sample)
|
||||
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
|
||||
var/list/sample_gases = sample.gases
|
||||
|
||||
temperature = sample.temperature
|
||||
for(var/id in sample_gases)
|
||||
cached_gases[id] = sample_gases[id]
|
||||
|
||||
//remove all gases not in the sample
|
||||
cached_gases &= sample_gases
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/copy_from_turf(turf/model)
|
||||
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))
|
||||
temperature = model.temperature
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
|
||||
var/list/cached_gases = gases
|
||||
var/list/sharer_gases = sharer.gases
|
||||
|
||||
var/temperature_delta = temperature_archived - sharer.temperature_archived
|
||||
var/abs_temperature_delta = abs(temperature_delta)
|
||||
|
||||
var/old_self_heat_capacity = 0
|
||||
var/old_sharer_heat_capacity = 0
|
||||
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
old_self_heat_capacity = heat_capacity()
|
||||
old_sharer_heat_capacity = sharer.heat_capacity()
|
||||
|
||||
var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
|
||||
var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
|
||||
|
||||
var/moved_moles = 0
|
||||
var/abs_moved_moles = 0
|
||||
|
||||
//we're gonna define these vars outside of this for loop because as it turns out, var declaration is pricy
|
||||
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
|
||||
//GAS TRANSFER
|
||||
for(var/id in cached_gases | sharer_gases) // transfer gases
|
||||
|
||||
delta = QUANTIZE(gas_archive[id] - sharer.gas_archive[id])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
|
||||
|
||||
if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
gas_heat_capacity = delta * cached_gasheats[id]
|
||||
if(delta > 0)
|
||||
heat_capacity_self_to_sharer += gas_heat_capacity
|
||||
else
|
||||
heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative.
|
||||
|
||||
cached_gases[id] -= delta
|
||||
sharer_gases[id] += delta
|
||||
moved_moles += delta
|
||||
abs_moved_moles += abs(delta)
|
||||
|
||||
last_share = abs_moved_moles
|
||||
|
||||
//THERMAL ENERGY TRANSFER
|
||||
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
|
||||
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
|
||||
|
||||
//transfer of thermal energy (via changed heat capacity) between self and sharer
|
||||
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
|
||||
|
||||
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
|
||||
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
|
||||
//thermal energy of the system (self and sharer) is unchanged
|
||||
|
||||
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
|
||||
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity
|
||||
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
|
||||
|
||||
if (initial(sharer.gc_share))
|
||||
GAS_GARBAGE_COLLECT(sharer.gases)
|
||||
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
var/our_moles
|
||||
TOTAL_MOLES(cached_gases,our_moles)
|
||||
var/their_moles
|
||||
TOTAL_MOLES(sharer_gases,their_moles)
|
||||
return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume
|
||||
|
||||
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
|
||||
//transfer of thermal energy (via conduction) between self and sharer
|
||||
if(sharer)
|
||||
sharer_temperature = sharer.temperature_archived
|
||||
var/temperature_delta = temperature_archived - sharer_temperature
|
||||
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = archived_heat_capacity()
|
||||
sharer_heat_capacity = sharer_heat_capacity || sharer.archived_heat_capacity()
|
||||
|
||||
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
|
||||
var/heat = conduction_coefficient*temperature_delta* \
|
||||
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
|
||||
|
||||
temperature = max(temperature - heat/self_heat_capacity, TCMB)
|
||||
sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB)
|
||||
if(sharer)
|
||||
sharer.temperature = sharer_temperature
|
||||
return sharer_temperature
|
||||
//thermal energy of the system (self and sharer) is unchanged
|
||||
|
||||
/datum/gas_mixture/compare(datum/gas_mixture/sample)
|
||||
var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
|
||||
var/list/cached_gases = gases
|
||||
|
||||
for(var/id in cached_gases | sample_gases) // compare gases from either mixture
|
||||
var/gas_moles = cached_gases[id]
|
||||
var/sample_moles = sample_gases[id]
|
||||
var/delta = abs(gas_moles - sample_moles)
|
||||
if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \
|
||||
delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)
|
||||
return id
|
||||
|
||||
var/our_moles
|
||||
TOTAL_MOLES(cached_gases, our_moles)
|
||||
if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
var/temp = temperature
|
||||
var/sample_temp = sample.temperature
|
||||
|
||||
var/temperature_delta = abs(temp - sample_temp)
|
||||
if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
|
||||
return "temp"
|
||||
|
||||
return ""
|
||||
|
||||
/datum/gas_mixture/transfer_to(datum/gas_mixture/target, amount)
|
||||
return merge(target.remove(amount))
|
||||
|
||||
#endif
|
||||
@@ -269,7 +269,7 @@
|
||||
"unit" = "kPa",
|
||||
"danger_level" = cur_tlv.get_danger_level(pressure)
|
||||
))
|
||||
var/temperature = environment.temperature
|
||||
var/temperature = environment.return_temperature()
|
||||
cur_tlv = TLV["temperature"]
|
||||
data["environment_data"] += list(list(
|
||||
"name" = "Temperature",
|
||||
@@ -278,16 +278,16 @@
|
||||
"danger_level" = cur_tlv.get_danger_level(temperature)
|
||||
))
|
||||
var/total_moles = environment.total_moles()
|
||||
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
|
||||
for(var/gas_id in environment.gases)
|
||||
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.return_temperature() / environment.return_volume()
|
||||
for(var/gas_id in environment.get_gases())
|
||||
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
|
||||
continue
|
||||
cur_tlv = TLV[gas_id]
|
||||
data["environment_data"] += list(list(
|
||||
"name" = GLOB.meta_gas_names[gas_id],
|
||||
"value" = environment.gases[gas_id] / total_moles * 100,
|
||||
"value" = environment.get_moles(gas_id) / total_moles * 100,
|
||||
"unit" = "%",
|
||||
"danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure)
|
||||
"danger_level" = cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure)
|
||||
))
|
||||
|
||||
if(!locked || hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE))
|
||||
@@ -684,24 +684,21 @@
|
||||
var/datum/tlv/cur_tlv
|
||||
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
var/list/env_gases = environment.gases
|
||||
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
|
||||
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.return_temperature() / environment.return_volume()
|
||||
|
||||
cur_tlv = TLV["pressure"]
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
|
||||
|
||||
cur_tlv = TLV["temperature"]
|
||||
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
|
||||
var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.return_temperature())
|
||||
|
||||
var/gas_dangerlevel = 0
|
||||
for(var/gas_id in env_gases)
|
||||
for(var/gas_id in environment.get_gases())
|
||||
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
|
||||
continue
|
||||
cur_tlv = TLV[gas_id]
|
||||
gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(env_gases[gas_id] * partial_pressure))
|
||||
|
||||
GAS_GARBAGE_COLLECT(environment.gases)
|
||||
gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure))
|
||||
|
||||
var/old_danger_level = danger_level
|
||||
danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel)
|
||||
|
||||
@@ -52,10 +52,10 @@
|
||||
return null
|
||||
|
||||
//Calculate necessary moles to transfer using PV = nRT
|
||||
if(air2.temperature>0)
|
||||
if(air2.return_temperature()>0)
|
||||
var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2
|
||||
|
||||
var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
|
||||
var/transfer_moles = pressure_delta*air1.return_volume()/(air2.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
last_pressure_delta = pressure_delta
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
|
||||
|
||||
if(pressure_delta > 0)
|
||||
if(air1.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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
|
||||
@@ -81,20 +81,17 @@
|
||||
parent1.update = 1
|
||||
|
||||
else //external -> output
|
||||
var/pressure_delta = 10000
|
||||
if(environment.return_pressure() > 0)
|
||||
var/our_multiplier = air2.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
var/moles_delta = 10000 * our_multiplier
|
||||
if(pressure_checks&EXT_BOUND)
|
||||
moles_delta = min(moles_delta, (environment_pressure - output_pressure_max) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION))
|
||||
if(pressure_checks&INPUT_MIN)
|
||||
moles_delta = min(moles_delta, (input_pressure_min - air2.return_pressure()) * our_multiplier)
|
||||
|
||||
if(pressure_checks&EXT_BOUND)
|
||||
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
|
||||
if(pressure_checks&INPUT_MIN)
|
||||
pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
|
||||
|
||||
if(pressure_delta > 0)
|
||||
if(environment.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
|
||||
//removed can be null if there is no air in the location
|
||||
if(!removed)
|
||||
if(moles_delta > 0)
|
||||
var/datum/gas_mixture/removed = loc.remove_air(moles_delta)
|
||||
if (isnull(removed)) // in space
|
||||
return
|
||||
|
||||
air2.merge(removed)
|
||||
@@ -182,8 +179,8 @@
|
||||
..()
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
var/datum/gas_mixture/air2 = airs[2]
|
||||
air1.volume = 1000
|
||||
air2.volume = 1000
|
||||
air1.set_volume(1000)
|
||||
air2.set_volume(1000)
|
||||
|
||||
// Mapping
|
||||
|
||||
|
||||
@@ -68,11 +68,11 @@ Passive gate is similar to the regular pump except:
|
||||
return
|
||||
|
||||
//Calculate necessary moles to transfer using PV = nRT
|
||||
if((air1.total_moles() > 0) && (air1.temperature>0))
|
||||
if((air1.total_moles() > 0) && (air1.return_temperature()>0))
|
||||
var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2)
|
||||
//Can not have a pressure delta that would cause output_pressure > input_pressure
|
||||
|
||||
var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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)
|
||||
@@ -187,4 +187,4 @@ Passive gate is similar to the regular pump except:
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/layer3
|
||||
piping_layer = 3
|
||||
icon_state = "passgate_map-3"
|
||||
icon_state = "passgate_map-3"
|
||||
|
||||
@@ -77,9 +77,9 @@
|
||||
return
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
if((air1.total_moles() > 0) && (air1.temperature>0))
|
||||
if((air1.total_moles() > 0) && (air1.return_temperature()>0))
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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)
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000))
|
||||
return
|
||||
|
||||
var/transfer_ratio = transfer_rate/air1.volume
|
||||
var/transfer_ratio = transfer_rate/air1.return_volume()
|
||||
|
||||
var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
|
||||
if("set_transfer_rate" in signal.data)
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
transfer_rate = clamp(text2num(signal.data["set_transfer_rate"]),0,air1.volume)
|
||||
transfer_rate = clamp(text2num(signal.data["set_transfer_rate"]),0,air1.return_volume())
|
||||
|
||||
if(on != old_on)
|
||||
investigate_log("was turned [on ? "on" : "off"] by a remote signal", INVESTIGATE_ATMOS)
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
..()
|
||||
|
||||
for(var/i in 1 to device_type)
|
||||
var/datum/gas_mixture/A = new
|
||||
A.volume = 200
|
||||
var/datum/gas_mixture/A = new(200)
|
||||
airs[i] = A
|
||||
|
||||
// Iconnery
|
||||
@@ -117,7 +116,7 @@
|
||||
var/times_lost = 0
|
||||
for(var/i in 1 to device_type)
|
||||
var/datum/gas_mixture/air = airs[i]
|
||||
lost += pressures*environment.volume/(air.temperature * R_IDEAL_GAS_EQUATION)
|
||||
lost += pressures*environment.return_volume()/(air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
times_lost++
|
||||
var/shared_loss = lost/times_lost
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/transfer_ratio = transfer_rate/air1.volume
|
||||
var/transfer_ratio = transfer_rate/air1.return_volume()
|
||||
|
||||
//Actually transfer the gas
|
||||
|
||||
@@ -111,14 +111,13 @@
|
||||
else
|
||||
filtering = FALSE
|
||||
|
||||
if(filtering && removed.gases[filter_type])
|
||||
if(filtering && removed.get_moles(filter_type))
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
|
||||
filtered_out.temperature = removed.temperature
|
||||
filtered_out.gases[filter_type] = removed.gases[filter_type]
|
||||
filtered_out.set_temperature(removed.return_temperature())
|
||||
filtered_out.set_moles(filter_type, removed.get_moles(filter_type))
|
||||
|
||||
removed.gases[filter_type] = 0
|
||||
GAS_GARBAGE_COLLECT(removed.gases)
|
||||
removed.set_moles(filter_type, 0)
|
||||
|
||||
var/datum/gas_mixture/target = (air2.return_pressure() < 9000 ? air2 : air1)
|
||||
target.merge(filtered_out)
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/New()
|
||||
..()
|
||||
var/datum/gas_mixture/air3 = airs[3]
|
||||
air3.volume = 300
|
||||
air3.set_volume(300)
|
||||
airs[3] = air3
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/process_atmos()
|
||||
@@ -81,26 +81,26 @@
|
||||
return
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
var/general_transfer = (target_pressure - output_starting_pressure) * air3.volume / R_IDEAL_GAS_EQUATION
|
||||
var/general_transfer = (target_pressure - output_starting_pressure) * air3.return_volume() / R_IDEAL_GAS_EQUATION
|
||||
|
||||
var/transfer_moles1 = air1.temperature ? node1_concentration * general_transfer / air1.temperature : 0
|
||||
var/transfer_moles2 = air2.temperature ? node2_concentration * general_transfer / air2.temperature : 0
|
||||
var/transfer_moles1 = air1.return_temperature() ? node1_concentration * general_transfer / air1.return_temperature() : 0
|
||||
var/transfer_moles2 = air2.return_temperature() ? node2_concentration * general_transfer / air2.return_temperature() : 0
|
||||
|
||||
var/air1_moles = air1.total_moles()
|
||||
var/air2_moles = air2.total_moles()
|
||||
|
||||
if(!node2_concentration)
|
||||
if(air1.temperature <= 0)
|
||||
if(air1.return_temperature() <= 0)
|
||||
return
|
||||
transfer_moles1 = min(transfer_moles1, air1_moles)
|
||||
transfer_moles2 = 0
|
||||
else if(!node1_concentration)
|
||||
if(air2.temperature <= 0)
|
||||
if(air2.return_temperature() <= 0)
|
||||
return
|
||||
transfer_moles2 = min(transfer_moles2, air2_moles)
|
||||
transfer_moles1 = 0
|
||||
else
|
||||
if(air1.temperature <= 0 || air2.temperature <= 0)
|
||||
if(air1.return_temperature() <= 0 || air2.return_temperature() <= 0)
|
||||
return
|
||||
if((transfer_moles2 <= 0) || (transfer_moles1 <= 0))
|
||||
return
|
||||
@@ -248,4 +248,4 @@
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped/inverse
|
||||
node1_concentration = O2STANDARD
|
||||
node2_concentration = N2STANDARD
|
||||
node2_concentration = N2STANDARD
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
|
||||
if(air1.gases.len)
|
||||
if(air1.total_moles())
|
||||
if(mob_occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
|
||||
// temperature factor goes from 1 to about 2.5
|
||||
var/amount = max(1, (4 * log(T0C - mob_occupant.bodytemperature)) - 20) * knockout_factor * base_knockout
|
||||
@@ -196,8 +196,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.gases[/datum/gas/oxygen] -= max(0,air1.gases[/datum/gas/oxygen] - 2 / efficiency) //Let's use gas for this
|
||||
GAS_GARBAGE_COLLECT(air1.gases)
|
||||
air1.adjust_moles(/datum/gas/oxygen, -max(0,air1.get_moles(/datum/gas/oxygen) - 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
|
||||
|
||||
@@ -211,7 +210,7 @@
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
|
||||
if(!nodes[1] || !airs[1] || !air1.gases.len || air1.gases[/datum/gas/oxygen] < 5) // Turn off if the machine won't work.
|
||||
if(!nodes[1] || !airs[1] || air1.get_moles(/datum/gas/oxygen) < 5) // Turn off if the machine won't work.
|
||||
on = FALSE
|
||||
update_icon()
|
||||
return
|
||||
@@ -219,22 +218,21 @@
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/cold_protection = 0
|
||||
var/temperature_delta = air1.temperature - mob_occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant.
|
||||
var/temperature_delta = air1.return_temperature() - mob_occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant.
|
||||
|
||||
if(ishuman(occupant))
|
||||
var/mob/living/carbon/human/H = occupant
|
||||
cold_protection = H.get_thermal_protection(air1.temperature, TRUE)
|
||||
cold_protection = H.get_thermal_protection(air1.return_temperature(), TRUE)
|
||||
|
||||
if(abs(temperature_delta) > 1)
|
||||
var/air_heat_capacity = air1.heat_capacity()
|
||||
|
||||
var/heat = ((1 - cold_protection) * 0.1 + conduction_coefficient) * temperature_delta * (air_heat_capacity * heat_capacity / (air_heat_capacity + heat_capacity))
|
||||
|
||||
air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB)
|
||||
air1.set_temperature(max(air1.return_temperature() - heat / air_heat_capacity, TCMB))
|
||||
mob_occupant.adjust_bodytemperature(heat / heat_capacity, TCMB)
|
||||
|
||||
air1.gases[/datum/gas/oxygen] = max(0,air1.gases[/datum/gas/oxygen] - 0.5 / efficiency) // Magically consume gas? Why not, we run on cryo magic.
|
||||
GAS_GARBAGE_COLLECT(air1.gases)
|
||||
air1.set_temperature(max(air1.return_temperature() - 0.5 / efficiency)) // Magically consume gas? Why not, we run on cryo magic.
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
|
||||
..()
|
||||
@@ -369,7 +367,7 @@
|
||||
data["occupant"]["temperaturestatus"] = "bad"
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
data["cellTemperature"] = round(air1.temperature, 1)
|
||||
data["cellTemperature"] = round(air1.return_temperature(), 1)
|
||||
|
||||
data["isBeakerLoaded"] = beaker ? TRUE : FALSE
|
||||
var/beakerContents = list()
|
||||
@@ -439,7 +437,7 @@
|
||||
var/datum/gas_mixture/G = airs[1]
|
||||
|
||||
if(G.total_moles() > 10)
|
||||
return G.temperature
|
||||
return G.return_temperature()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/default_change_direction_wrench(mob/user, obj/item/wrench/W)
|
||||
|
||||
@@ -59,18 +59,18 @@
|
||||
var/other_air_heat_capacity = partner_air_contents.heat_capacity()
|
||||
var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity
|
||||
|
||||
var/old_temperature = air_contents.temperature
|
||||
var/other_old_temperature = partner_air_contents.temperature
|
||||
var/old_temperature = air_contents.return_temperature()
|
||||
var/other_old_temperature = partner_air_contents.return_temperature()
|
||||
|
||||
if(combined_heat_capacity > 0)
|
||||
var/combined_energy = partner_air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature
|
||||
var/combined_energy = partner_air_contents.return_temperature()*other_air_heat_capacity + air_heat_capacity*air_contents.return_temperature()
|
||||
|
||||
var/new_temperature = combined_energy/combined_heat_capacity
|
||||
air_contents.temperature = new_temperature
|
||||
partner_air_contents.temperature = new_temperature
|
||||
air_contents.set_temperature(new_temperature)
|
||||
partner_air_contents.set_temperature(new_temperature)
|
||||
|
||||
if(abs(old_temperature-air_contents.temperature) > 1)
|
||||
if(abs(old_temperature-air_contents.return_temperature()) > 1)
|
||||
update_parents()
|
||||
|
||||
if(abs(other_old_temperature-partner_air_contents.temperature) > 1)
|
||||
if(abs(other_old_temperature-partner_air_contents.return_temperature()) > 1)
|
||||
partner.update_parents()
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
|
||||
if(air_contents.temperature > 0)
|
||||
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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)
|
||||
|
||||
@@ -86,8 +86,8 @@
|
||||
|
||||
injecting = 1
|
||||
|
||||
if(air_contents.temperature > 0)
|
||||
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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)
|
||||
update_parents()
|
||||
@@ -138,7 +138,7 @@
|
||||
if("set_volume_rate" in signal.data)
|
||||
var/number = text2num(signal.data["set_volume_rate"])
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
volume_rate = clamp(number, 0, air_contents.volume)
|
||||
volume_rate = clamp(number, 0, air_contents.return_volume())
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
@@ -256,4 +256,4 @@
|
||||
id = ATMOS_GAS_MONITOR_INPUT_INCINERATOR
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/toxins_mixing_input
|
||||
name = "toxins mixing input injector"
|
||||
id = ATMOS_GAS_MONITOR_INPUT_TOXINS_LAB
|
||||
id = ATMOS_GAS_MONITOR_INPUT_TOXINS_LAB
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
|
||||
if(pressure_delta > 0.5)
|
||||
if(external_pressure < internal_pressure)
|
||||
var/air_temperature = (external.temperature > 0) ? external.temperature : internal.temperature
|
||||
var/transfer_moles = (pressure_delta * external.volume) / (air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
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.temperature > 0) ? internal.temperature : external.temperature
|
||||
var/transfer_moles = (pressure_delta * internal.volume) / (air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
transfer_moles = min(transfer_moles, external.total_moles() * internal.volume / external.volume)
|
||||
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
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
|
||||
air_contents.volume = 0
|
||||
air_contents.set_volume(0)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/portables_connector/Destroy()
|
||||
if(connected_device)
|
||||
@@ -64,4 +64,4 @@
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer3
|
||||
piping_layer = 3
|
||||
icon_state = "connector_map-3"
|
||||
icon_state = "connector_map-3"
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
else if(!opened && our_pressure >= open_pressure)
|
||||
opened = TRUE
|
||||
update_icon_nopipes()
|
||||
if(opened && air_contents.temperature > 0)
|
||||
if(opened && air_contents.return_temperature() > 0)
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
var/pressure_delta = our_pressure - environment.return_pressure()
|
||||
var/transfer_moles = pressure_delta*200/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define AIR_CONTENTS ((25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature))
|
||||
#define AIR_CONTENTS ((25*ONE_ATMOSPHERE)*(air_contents.return_volume())/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature()))
|
||||
/obj/machinery/atmospherics/components/unary/tank
|
||||
icon = 'icons/obj/atmospherics/pipes/pressure_tank.dmi'
|
||||
icon_state = "generic"
|
||||
@@ -15,10 +15,10 @@
|
||||
/obj/machinery/atmospherics/components/unary/tank/New()
|
||||
..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
air_contents.volume = volume
|
||||
air_contents.temperature = T20C
|
||||
air_contents.set_volume(volume)
|
||||
air_contents.set_temperature(T20C)
|
||||
if(gas_type)
|
||||
air_contents.gases[gas_type] = AIR_CONTENTS
|
||||
air_contents.set_moles(AIR_CONTENTS)
|
||||
name = "[name] ([GLOB.meta_gas_names[gas_type]])"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/air
|
||||
@@ -28,8 +28,8 @@
|
||||
/obj/machinery/atmospherics/components/unary/tank/air/New()
|
||||
..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
air_contents.gases[/datum/gas/oxygen] = AIR_CONTENTS * 0.2
|
||||
air_contents.gases[/datum/gas/nitrogen] = AIR_CONTENTS * 0.8
|
||||
air_contents.set_moles(/datum/gas/oxygen, AIR_CONTENTS * 0.2)
|
||||
air_contents.set_moles(/datum/gas/nitrogen, AIR_CONTENTS * 0.8)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide
|
||||
gas_type = /datum/gas/carbon_dioxide
|
||||
|
||||
@@ -74,13 +74,13 @@
|
||||
|
||||
var/air_heat_capacity = air_contents.heat_capacity()
|
||||
var/combined_heat_capacity = heat_capacity + air_heat_capacity
|
||||
var/old_temperature = air_contents.temperature
|
||||
var/old_temperature = air_contents.return_temperature()
|
||||
|
||||
if(combined_heat_capacity > 0)
|
||||
var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.temperature
|
||||
air_contents.temperature = combined_energy/combined_heat_capacity
|
||||
var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.return_temperature()
|
||||
air_contents.set_temperature(combined_energy/combined_heat_capacity)
|
||||
|
||||
var/temperature_delta= abs(old_temperature - air_contents.temperature)
|
||||
var/temperature_delta= abs(old_temperature - air_contents.return_temperature())
|
||||
if(temperature_delta > 1)
|
||||
active_power_usage = (heat_capacity * temperature_delta) / 10 + idle_power_usage
|
||||
update_parents()
|
||||
@@ -142,7 +142,7 @@
|
||||
data["initial"] = initial(target_temperature)
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
data["temperature"] = air1.temperature
|
||||
data["temperature"] = air1.return_temperature()
|
||||
data["pressure"] = air1.return_pressure()
|
||||
return data
|
||||
|
||||
|
||||
@@ -104,8 +104,8 @@
|
||||
pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound))
|
||||
|
||||
if(pressure_delta > 0)
|
||||
if(air_contents.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
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)
|
||||
|
||||
@@ -113,21 +113,21 @@
|
||||
air_update_turf()
|
||||
|
||||
else // external -> internal
|
||||
var/pressure_delta = 10000
|
||||
if(pressure_checks&EXT_BOUND)
|
||||
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
|
||||
if(pressure_checks&INT_BOUND)
|
||||
pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure()))
|
||||
if(environment.return_pressure() > 0)
|
||||
var/our_multiplier = air_contents.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
var/moles_delta = 10000 * our_multiplier
|
||||
if(pressure_checks&EXT_BOUND)
|
||||
moles_delta = min(moles_delta, (environment_pressure - external_pressure_bound) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION))
|
||||
if(pressure_checks&INT_BOUND)
|
||||
moles_delta = min(moles_delta, (internal_pressure_bound - air_contents.return_pressure()) * our_multiplier)
|
||||
|
||||
if(pressure_delta > 0 && environment.temperature > 0)
|
||||
var/transfer_moles = pressure_delta * air_contents.volume / (environment.temperature * R_IDEAL_GAS_EQUATION)
|
||||
if(moles_delta > 0)
|
||||
var/datum/gas_mixture/removed = loc.remove_air(moles_delta)
|
||||
if (isnull(removed)) // in space
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
|
||||
if (isnull(removed)) // in space
|
||||
return
|
||||
|
||||
air_contents.merge(removed)
|
||||
air_update_turf()
|
||||
air_contents.merge(removed)
|
||||
air_update_turf()
|
||||
update_parents()
|
||||
|
||||
//Radio remote control
|
||||
@@ -295,7 +295,7 @@
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/high_volume/New()
|
||||
..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
air_contents.volume = 1000
|
||||
air_contents.set_volume(1000)
|
||||
|
||||
// mapping
|
||||
|
||||
|
||||
@@ -149,43 +149,29 @@
|
||||
return FALSE
|
||||
var/datum/gas_mixture/environment = tile.return_air()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
var/list/env_gases = environment.gases
|
||||
|
||||
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE)
|
||||
return FALSE
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
if(length(env_gases & filter_types))
|
||||
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
|
||||
var/transfer_moles = min(1, volume_rate/environment.return_volume())*environment.total_moles()
|
||||
|
||||
//Take a gas sample
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
//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
|
||||
//Nothing left to remove from the tile
|
||||
if(isnull(removed))
|
||||
return FALSE
|
||||
|
||||
var/list/removed_gases = removed.gases
|
||||
removed.scrub_into(air_contents, filter_types)
|
||||
|
||||
//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
|
||||
|
||||
GAS_GARBAGE_COLLECT(removed.gases)
|
||||
|
||||
//Remix the resulting gases
|
||||
air_contents.merge(filtered_out)
|
||||
tile.assume_air(removed)
|
||||
tile.air_update_turf()
|
||||
//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.volume)
|
||||
var/transfer_moles = environment.total_moles()*(volume_rate/environment.return_volume())
|
||||
|
||||
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
/datum/pipeline/Destroy()
|
||||
SSair.networks -= src
|
||||
if(air && air.volume)
|
||||
if(air && air.return_volume())
|
||||
temporarily_store_air()
|
||||
for(var/obj/machinery/atmospherics/pipe/P in members)
|
||||
P.parent = null
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
possible_expansions -= borderline
|
||||
|
||||
air.volume = volume
|
||||
air.set_volume(volume)
|
||||
|
||||
/datum/pipeline/proc/addMachineryMember(obj/machinery/atmospherics/components/C)
|
||||
other_atmosmch |= C
|
||||
@@ -99,7 +99,7 @@
|
||||
merge(E)
|
||||
if(!members.Find(P))
|
||||
members += P
|
||||
air.volume += P.volume
|
||||
air.set_volume(air.return_volume() + P.volume)
|
||||
else
|
||||
A.setPipenet(src, N)
|
||||
addMachineryMember(A)
|
||||
@@ -107,7 +107,7 @@
|
||||
/datum/pipeline/proc/merge(datum/pipeline/E)
|
||||
if(E == src)
|
||||
return
|
||||
air.volume += E.air.volume
|
||||
air.set_volume(air.return_volume() + E.air.return_volume())
|
||||
members.Add(E.members)
|
||||
for(var/obj/machinery/atmospherics/pipe/S in E.members)
|
||||
S.parent = src
|
||||
@@ -139,18 +139,16 @@
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/member in members)
|
||||
member.air_temporary = new
|
||||
member.air_temporary.volume = member.volume
|
||||
member.air_temporary.set_volume(member.volume)
|
||||
member.air_temporary.copy_from(air)
|
||||
var/member_gases = member.air_temporary.gases
|
||||
|
||||
for(var/id in member_gases)
|
||||
member_gases[id] *= member.volume/air.volume
|
||||
member.air_temporary.multiply(member.volume/air.return_volume())
|
||||
|
||||
member.air_temporary.temperature = air.temperature
|
||||
member.air_temporary.set_temperature(air.return_temperature())
|
||||
|
||||
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
|
||||
var/total_heat_capacity = air.heat_capacity()
|
||||
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
|
||||
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.return_volume())
|
||||
var/target_temperature
|
||||
var/target_heat_capacity
|
||||
|
||||
@@ -163,19 +161,19 @@
|
||||
if(modeled_location.blocks_air)
|
||||
|
||||
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
|
||||
var/delta_temperature = air.temperature - target_temperature
|
||||
var/delta_temperature = air.return_temperature() - target_temperature
|
||||
|
||||
var/heat = thermal_conductivity*delta_temperature* \
|
||||
(partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity))
|
||||
|
||||
air.temperature -= heat/total_heat_capacity
|
||||
air.set_temperature(air.return_temperature() - heat/total_heat_capacity)
|
||||
modeled_location.TakeTemperature(heat/target_heat_capacity)
|
||||
|
||||
else
|
||||
var/delta_temperature = 0
|
||||
var/sharer_heat_capacity = 0
|
||||
|
||||
delta_temperature = (air.temperature - target_temperature)
|
||||
delta_temperature = (air.return_temperature() - target_temperature)
|
||||
sharer_heat_capacity = target_heat_capacity
|
||||
|
||||
var/self_temperature_delta = 0
|
||||
@@ -190,18 +188,18 @@
|
||||
else
|
||||
return 1
|
||||
|
||||
air.temperature += self_temperature_delta
|
||||
air.set_temperature(air.return_temperature() + self_temperature_delta)
|
||||
modeled_location.TakeTemperature(sharer_temperature_delta)
|
||||
|
||||
|
||||
else
|
||||
if((target.heat_capacity>0) && (partial_heat_capacity>0))
|
||||
var/delta_temperature = air.temperature - target.temperature
|
||||
var/delta_temperature = air.return_temperature() - target.return_temperature()
|
||||
|
||||
var/heat = thermal_conductivity*delta_temperature* \
|
||||
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
|
||||
|
||||
air.temperature -= heat/total_heat_capacity
|
||||
air.set_temperature(air.return_temperature() - heat/total_heat_capacity)
|
||||
update = TRUE
|
||||
|
||||
/datum/pipeline/proc/return_air()
|
||||
@@ -242,20 +240,18 @@
|
||||
|
||||
for(var/i in GL)
|
||||
var/datum/gas_mixture/G = i
|
||||
total_gas_mixture.volume += G.volume
|
||||
total_gas_mixture.set_volume(total_gas_mixture.return_volume() + G.return_volume())
|
||||
|
||||
total_gas_mixture.merge(G)
|
||||
|
||||
total_thermal_energy += THERMAL_ENERGY(G)
|
||||
total_thermal_energy += G.thermal_energy()
|
||||
total_heat_capacity += G.heat_capacity()
|
||||
|
||||
total_gas_mixture.temperature = total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0
|
||||
total_gas_mixture.set_temperature(total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0)
|
||||
|
||||
if(total_gas_mixture.volume > 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)
|
||||
var/list/G_gases = G.gases
|
||||
for(var/id in G_gases)
|
||||
G_gases[id] *= G.volume/total_gas_mixture.volume
|
||||
G.multiply(G.return_volume()/total_gas_mixture.return_volume())
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
if (target)
|
||||
var/datum/gas_mixture/environment = target.return_air()
|
||||
if(environment)
|
||||
. = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)] K ([round(environment.temperature-T0C,0.01)]°C)."
|
||||
. = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.return_temperature(),0.01)] K ([round(environment.return_temperature()-T0C,0.01)]°C)."
|
||||
else
|
||||
. = "The sensor error light is blinking."
|
||||
else
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
if(!isopenturf(O))
|
||||
return FALSE
|
||||
var/datum/gas_mixture/merger = new
|
||||
merger.gases[spawn_id] = (spawn_mol)
|
||||
merger.temperature = spawn_temp
|
||||
merger.set_moles(spawn_id, spawn_mol)
|
||||
merger.set_temperature(spawn_temp)
|
||||
O.assume_air(merger)
|
||||
O.air_update_turf(TRUE)
|
||||
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
if(islava(T))
|
||||
environment_temperature = 5000
|
||||
else if(T.blocks_air)
|
||||
environment_temperature = T.temperature
|
||||
environment_temperature = T.return_temperature()
|
||||
else
|
||||
var/turf/open/OT = T
|
||||
environment_temperature = OT.GetTemperature()
|
||||
else
|
||||
environment_temperature = T.temperature
|
||||
environment_temperature = T.return_temperature()
|
||||
|
||||
if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
|
||||
if(abs(environment_temperature-pipe_air.return_temperature()) > minimum_temperature_difference)
|
||||
parent.temperature_interact(T, volume, thermal_conductivity)
|
||||
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
var/hc = pipe_air.heat_capacity()
|
||||
var/mob/living/heat_source = buckled_mobs[1]
|
||||
//Best guess-estimate of the total bodytemperature of all the mobs, since they share the same environment it's ~ok~ to guess like this
|
||||
var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0))
|
||||
var/avg_temp = (pipe_air.return_temperature() * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0))
|
||||
for(var/m in buckled_mobs)
|
||||
var/mob/living/L = m
|
||||
L.bodytemperature = avg_temp
|
||||
pipe_air.temperature = avg_temp
|
||||
pipe_air.set_temperature(avg_temp)
|
||||
|
||||
/obj/machinery/atmospherics/pipe/heat_exchanging/process()
|
||||
if(!parent)
|
||||
@@ -57,9 +57,9 @@
|
||||
var/datum/gas_mixture/pipe_air = return_air()
|
||||
|
||||
//Heat causes pipe to glow
|
||||
if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //glow starts at 500K
|
||||
if(abs(pipe_air.temperature - icon_temperature) > 10)
|
||||
icon_temperature = pipe_air.temperature
|
||||
if(pipe_air.return_temperature() && (icon_temperature > 500 || pipe_air.return_temperature() > 500)) //glow starts at 500K
|
||||
if(abs(pipe_air.return_temperature() - icon_temperature) > 10)
|
||||
icon_temperature = pipe_air.return_temperature()
|
||||
|
||||
var/h_r = heat2colour_r(icon_temperature)
|
||||
var/h_g = heat2colour_g(icon_temperature)
|
||||
@@ -76,7 +76,7 @@
|
||||
//burn any mobs buckled based on temperature
|
||||
if(has_buckled_mobs())
|
||||
var/heat_limit = 1000
|
||||
if(pipe_air.temperature > heat_limit + 1)
|
||||
if(pipe_air.return_temperature() > heat_limit + 1)
|
||||
for(var/m in buckled_mobs)
|
||||
var/mob/living/buckled_mob = m
|
||||
buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BODY_ZONE_CHEST)
|
||||
buckled_mob.apply_damage(4 * log(pipe_air.return_temperature() - heat_limit), BURN, BODY_ZONE_CHEST)
|
||||
|
||||
@@ -205,14 +205,14 @@
|
||||
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
|
||||
if(gas_type)
|
||||
if(starter_temp)
|
||||
air_contents.temperature = starter_temp
|
||||
air_contents.gases[gas_type] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
air_contents.set_temperature(starter_temp)
|
||||
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.temperature = starter_temp
|
||||
air_contents.set_temperature(starter_temp)
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/air/create_gas()
|
||||
air_contents.gases[/datum/gas/oxygen] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
air_contents.gases[/datum/gas/nitrogen] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
|
||||
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()))
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/update_icon_state()
|
||||
if(stat & BROKEN)
|
||||
@@ -401,8 +401,8 @@ obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/ite
|
||||
logmsg = "Valve was <b>opened</b> by [key_name(usr)], starting a transfer into \the [holding || "air"].<br>"
|
||||
if(!holding)
|
||||
var/list/danger = list()
|
||||
for(var/id in air_contents.gases)
|
||||
var/gas = air_contents.gases[id]
|
||||
for(var/id in air_contents.get_gases())
|
||||
var/gas = air_contents.get_moles(id)
|
||||
if(!GLOB.meta_gas_dangers[id])
|
||||
continue
|
||||
if(gas > (GLOB.meta_gas_visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
..()
|
||||
SSair.atmos_machinery += src
|
||||
|
||||
air_contents = new
|
||||
air_contents.volume = volume
|
||||
air_contents.temperature = T20C
|
||||
air_contents = new(volume)
|
||||
air_contents.set_temperature(T20C)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
if("power")
|
||||
on = !on
|
||||
if(on && !holding)
|
||||
var/plasma = air_contents.gases[/datum/gas/plasma]
|
||||
var/n2o = air_contents.gases[/datum/gas/nitrous_oxide]
|
||||
var/plasma = air_contents.get_moles(/datum/gas/plasma)
|
||||
var/n2o = air_contents.get_moles(/datum/gas/nitrous_oxide)
|
||||
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)]")
|
||||
|
||||
@@ -42,20 +42,13 @@
|
||||
scrub(T.return_air())
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
|
||||
var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles()
|
||||
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.
|
||||
var/datum/gas_mixture/filtered = new
|
||||
if(!filtering)
|
||||
return
|
||||
|
||||
filtered.temperature = filtering.temperature
|
||||
for(var/gas in filtering.gases & scrubbing)
|
||||
filtered.gases[gas] = filtering.gases[gas] // Shuffle the "bad" gasses to the filtered mixture.
|
||||
filtering.gases[gas] = 0
|
||||
GAS_GARBAGE_COLLECT(filtering.gases)
|
||||
|
||||
air_contents.merge(filtered) // Store filtered out gasses.
|
||||
filtering.scrub_into(air_contents,scrubbing)
|
||||
mixture.merge(filtering) // Returned the cleaned gas.
|
||||
if(!holding)
|
||||
air_update_turf()
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
if(!..())
|
||||
return FALSE
|
||||
var/obj/item/tank/T = O
|
||||
if(!T.air_contents.gases[gas_type])
|
||||
return FALSE
|
||||
return T.air_contents.gases[gas_type] >= moles_required
|
||||
return T.air_contents.get_moles(gas_type) >= moles_required
|
||||
|
||||
//datum/bounty/item/engineering/gas/nitryl_tank
|
||||
// name = "Full Tank of Nitryl"
|
||||
|
||||
@@ -169,15 +169,13 @@
|
||||
/datum/export/large/gas_canister/get_cost(obj/O)
|
||||
var/obj/machinery/portable_atmospherics/canister/C = O
|
||||
var/worth = 10
|
||||
var/gases = C.air_contents.gases
|
||||
|
||||
worth += gases[/datum/gas/bz]*3
|
||||
worth += gases[/datum/gas/stimulum]*25
|
||||
worth += gases[/datum/gas/hypernoblium]*1000
|
||||
worth += gases[/datum/gas/miasma]*2
|
||||
worth += gases[/datum/gas/tritium]*7
|
||||
worth += gases[/datum/gas/pluoxium]*6
|
||||
worth += gases[/datum/gas/nitryl]*30
|
||||
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)*1000
|
||||
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)*30
|
||||
return worth
|
||||
|
||||
|
||||
|
||||
@@ -155,3 +155,10 @@
|
||||
cost = 30
|
||||
message = "of paperframes"
|
||||
export_types = list(/obj/item/stack/sheet/paperframes)
|
||||
|
||||
/datum/export/stack/telecrystal
|
||||
unit_name = "raw"
|
||||
cost = 1000
|
||||
message = "telecrystals"
|
||||
export_types = list(/obj/item/stack/telecrystal)
|
||||
|
||||
|
||||
@@ -301,3 +301,36 @@
|
||||
/obj/item/clothing/head/wizard/fake)
|
||||
crate_name = "wizard costume crate"
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
|
||||
/datum/supply_pack/costumes_toys/wedding
|
||||
name = "Wedding Crate"
|
||||
desc = "Tie the knot IN SPACE! Hold your own extravagant wedding with this crate of suits and bridal gowns. Complete with champagne, cake, and the luxurious cost you would expect for an event to remember."
|
||||
cost = 10000 // weddings are absurdly expensive and so is this crate
|
||||
contains = list(/obj/item/clothing/under/suit/black_really, //we don't actually need suits since you can vend them but the crate should feel "complete"
|
||||
/obj/item/clothing/under/suit/black_really,
|
||||
/obj/item/clothing/under/suit/charcoal,
|
||||
/obj/item/clothing/under/suit/charcoal,
|
||||
/obj/item/clothing/under/suit/navy,
|
||||
/obj/item/clothing/under/suit/navy,
|
||||
/obj/item/clothing/under/suit/burgundy,
|
||||
/obj/item/clothing/under/suit/burgundy, // A pair of each "fancy suit" color for variety
|
||||
/obj/item/clothing/under/suit/white,
|
||||
/obj/item/clothing/under/suit/white, // white is a weird color for a groom but some people are weird
|
||||
/obj/item/clothing/under/suit/polychromic,
|
||||
/obj/item/clothing/under/suit/polychromic, // in case you can't be satisfied with the most fitting choices, of course.
|
||||
/obj/item/clothing/under/dress/wedding,
|
||||
/obj/item/clothing/under/dress/wedding, // this is what you actually bought the crate for. You can't get these anywhere else.
|
||||
/obj/item/clothing/under/dress/wedding/orange,
|
||||
/obj/item/clothing/under/dress/wedding/orange,
|
||||
/obj/item/clothing/under/dress/wedding/purple,
|
||||
/obj/item/clothing/under/dress/wedding/purple,
|
||||
/obj/item/clothing/under/dress/wedding/blue,
|
||||
/obj/item/clothing/under/dress/wedding/blue,
|
||||
/obj/item/clothing/under/dress/wedding/red,
|
||||
/obj/item/clothing/under/dress/wedding/red, // two of each
|
||||
/obj/item/reagent_containers/food/drinks/bottle/champagne, //appropriate booze for a wedding
|
||||
/obj/item/reagent_containers/food/snacks/store/cake/vanilla_cake, // we don't have a full wedding cake but this will do
|
||||
/obj/item/storage/fancy/ringbox/silver,
|
||||
/obj/item/storage/fancy/ringbox/silver) //diamond rings cost the same price as this crate via cargo so we're not giving you two for free. Wedding rings are traditionally less valuable anyway.
|
||||
crate_name = "wedding crate"
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@
|
||||
|
||||
/// Messages currently seen by this client
|
||||
var/list/seen_messages
|
||||
///A lazy list of atoms we've examined in the last EXAMINE_MORE_TIME (default 1.5) seconds, so that we will call [atom/proc/examine_more()] instead of [atom/proc/examine()] on them when examining
|
||||
var/list/recent_examines
|
||||
///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns
|
||||
var/cryo_warned = -5 MINUTES
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
. = text
|
||||
if(!CONFIG_GET(flag/emojis))
|
||||
return
|
||||
var/static/list/emojis = icon_states(icon('icons/emoji.dmi'))
|
||||
var/list/emojis = icon_states(icon('icons/emoji.dmi'))
|
||||
emojis |= icon_states(icon('icons/emoji_32.dmi'))
|
||||
var/parsed = ""
|
||||
var/pos = 1
|
||||
var/search = 0
|
||||
@@ -18,7 +19,7 @@
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
|
||||
var/tag = sheet.icon_tag("emoji-[emoji]")
|
||||
if(tag)
|
||||
parsed += tag
|
||||
parsed += "<i style='width:16px !important;height:16px !important;'>[tag]</i>" //evil way of enforcing 16x16
|
||||
pos = search + length(text[pos])
|
||||
else
|
||||
parsed += copytext(text, pos, search)
|
||||
@@ -34,7 +35,8 @@
|
||||
. = text
|
||||
if(!CONFIG_GET(flag/emojis))
|
||||
return
|
||||
var/static/list/emojis = icon_states(icon('icons/emoji.dmi'))
|
||||
var/list/emojis = icon_states(icon('icons/emoji.dmi'))
|
||||
emojis |= icon_states(icon('icons/emoji_32.dmi'))
|
||||
var/final = "" //only tags are added to this
|
||||
var/pos = 1
|
||||
var/search = 0
|
||||
|
||||
@@ -171,10 +171,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases[/datum/gas/oxygen])
|
||||
return
|
||||
GM.gases[/datum/gas/oxygen] = max(GM.gases[/datum/gas/oxygen] - severity * holder.energy, 0)
|
||||
GAS_GARBAGE_COLLECT(GM.gases)
|
||||
GM.set_moles(/datum/gas/oxygen, max(GM.get_moles(/datum/gas/oxygen) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/nitro_eater
|
||||
name = "nitrogen consuming"
|
||||
@@ -186,10 +183,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases[/datum/gas/nitrogen])
|
||||
return
|
||||
GM.gases[/datum/gas/nitrogen] = max(GM.gases[/datum/gas/nitrogen] - severity * holder.energy, 0)
|
||||
GAS_GARBAGE_COLLECT(GM.gases)
|
||||
GM.set_moles(/datum/gas/nitrogen, max(GM.get_moles(/datum/gas/nitrogen) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/carbondioxide_eater
|
||||
name = "CO2 consuming"
|
||||
@@ -201,10 +195,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases[/datum/gas/carbon_dioxide])
|
||||
return
|
||||
GM.gases[/datum/gas/carbon_dioxide] = max(GM.gases[/datum/gas/carbon_dioxide] - severity * holder.energy, 0)
|
||||
GAS_GARBAGE_COLLECT(GM.gases)
|
||||
GM.set_moles(/datum/gas/carbon_dioxide, max(GM.get_moles(/datum/gas/carbon_dioxide) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/plasma_eater
|
||||
name = "toxins consuming"
|
||||
@@ -216,10 +207,7 @@
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases[/datum/gas/plasma])
|
||||
return
|
||||
GM.gases[/datum/gas/plasma] = max(GM.gases[/datum/gas/plasma] - severity * holder.energy, 0)
|
||||
GAS_GARBAGE_COLLECT(GM.gases)
|
||||
GM.set_moles(/datum/gas/plasma, max(GM.get_moles(/datum/gas/plasma) - severity * holder.energy, 0))
|
||||
|
||||
/datum/spacevine_mutation/thorns
|
||||
name = "thorny"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Wisdom cow"
|
||||
typepath = /datum/round_event/wisdomcow
|
||||
max_occurrences = 1
|
||||
weight = 20
|
||||
weight = 10
|
||||
|
||||
/datum/round_event/wisdomcow/announce(fake)
|
||||
priority_announce("A wise cow has been spotted in the area. Be sure to ask for her advice.", "Nanotrasen Cow Ranching Agency")
|
||||
|
||||
@@ -2,18 +2,30 @@
|
||||
For the main html chat area
|
||||
*********************************/
|
||||
|
||||
//Precaching a bunch of shit
|
||||
/// Should match the value set in the browser js
|
||||
#define MAX_COOKIE_LENGTH 5
|
||||
|
||||
//Precaching a bunch of shit. Someone ship this out of here
|
||||
GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of icons for the browser output
|
||||
|
||||
//On client, created on login
|
||||
//lazy renaming to chat_output, instead renamed to old chatOutput
|
||||
/**
|
||||
* The chatOutput datum exists to handle the goonchat browser.
|
||||
* On client, created on Client/New()
|
||||
*/
|
||||
/datum/chatOutput
|
||||
var/client/owner //client ref
|
||||
/// The client that owns us.
|
||||
var/client/owner
|
||||
/// How many times client data has been checked
|
||||
var/total_checks = 0
|
||||
var/last_check = 0
|
||||
var/loaded = FALSE // Has the client loaded the browser output area?
|
||||
var/list/messageQueue //If they haven't loaded chat, this is where messages will go until they do
|
||||
var/cookieSent = FALSE // Has the client sent a cookie for analysis
|
||||
var/broken = FALSE
|
||||
/// When to next clear the client data checks counter
|
||||
var/next_time_to_clear = 0
|
||||
/// Has the client loaded the browser output area?
|
||||
var/loaded = FALSE
|
||||
/// If they haven't loaded chat, this is where messages will go until they do
|
||||
var/list/messageQueue
|
||||
var/cookieSent = FALSE // Has the client sent a cookie for analysis
|
||||
var/broken = FALSE
|
||||
var/list/connectionHistory //Contains the connection history passed from chat cookie
|
||||
var/adminMusicVolume = 25 //This is for the Play Global Sound verb
|
||||
|
||||
@@ -22,13 +34,18 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
messageQueue = list()
|
||||
connectionHistory = list()
|
||||
|
||||
/**
|
||||
* start: Tries to load the chat browser
|
||||
* Aborts if a problem is encountered.
|
||||
* Async because this is called from Client/New.
|
||||
*/
|
||||
/datum/chatOutput/proc/start()
|
||||
set waitfor = FALSE
|
||||
//Check for existing chat
|
||||
if(!owner)
|
||||
return FALSE
|
||||
|
||||
if(!winexists(owner, "browseroutput")) // Oh goddamnit.
|
||||
set waitfor = FALSE
|
||||
broken = TRUE
|
||||
message_admins("Couldn't start chat for [key_name_admin(owner)]!")
|
||||
. = FALSE
|
||||
@@ -43,6 +60,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Loads goonchat and sends assets.
|
||||
/datum/chatOutput/proc/load()
|
||||
set waitfor = FALSE
|
||||
if(!owner)
|
||||
@@ -53,6 +71,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
|
||||
owner << browse(file('code/modules/goonchat/browserassets/html/browserOutput.html'), "window=browseroutput")
|
||||
|
||||
/// Interprets input from the client. Will send data back if required.
|
||||
/datum/chatOutput/Topic(href, list/href_list)
|
||||
if(usr.client != owner)
|
||||
return TRUE
|
||||
@@ -83,20 +102,22 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
|
||||
if("setMusicVolume")
|
||||
data = setMusicVolume(arglist(params))
|
||||
|
||||
if("colorPresetPost") //User just swapped color presets in their goonchat preferences. Do we do anything else?
|
||||
switch(href_list["preset"])
|
||||
if("light")
|
||||
owner.force_white_theme()
|
||||
if("dark" || "normal")
|
||||
owner.force_dark_theme()
|
||||
|
||||
// if("swaptodarkmode")
|
||||
// swaptodarkmode()
|
||||
// if("swaptolightmode")
|
||||
// swaptolightmode()
|
||||
|
||||
if(data)
|
||||
ehjax_send(data = data)
|
||||
|
||||
|
||||
//Called on chat output done-loading by JS.
|
||||
/// Called on chat output done-loading by JS.
|
||||
/datum/chatOutput/proc/doneLoading()
|
||||
if(loaded)
|
||||
return
|
||||
@@ -113,34 +134,75 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
messageQueue = null
|
||||
sendClientData()
|
||||
|
||||
syncRegex()
|
||||
|
||||
//do not convert to to_chat()
|
||||
SEND_TEXT(owner, "<span class=\"userdanger\">Failed to load fancy chat, reverting to old chat. Certain features won't work.</span>")
|
||||
|
||||
/// Hides the standard output and makes the browser visible.
|
||||
/datum/chatOutput/proc/showChat()
|
||||
winset(owner, "output", "is-visible=false")
|
||||
winset(owner, "browseroutput", "is-disabled=false;is-visible=true")
|
||||
|
||||
/// Calls syncRegex on all currently owned chatOutput datums
|
||||
/proc/syncChatRegexes()
|
||||
for (var/user in GLOB.clients)
|
||||
var/client/C = user
|
||||
var/datum/chatOutput/Cchat = C.chatOutput
|
||||
if (Cchat && !Cchat.broken && Cchat.loaded)
|
||||
Cchat.syncRegex()
|
||||
|
||||
/// Used to dynamically add regexes to the browser output. Currently only used by the IC filter.
|
||||
/datum/chatOutput/proc/syncRegex()
|
||||
var/list/regexes = list()
|
||||
/*
|
||||
if (config.ic_filter_regex)
|
||||
regexes["show_filtered_ic_chat"] = list(
|
||||
config.ic_filter_regex.name,
|
||||
"ig",
|
||||
"<span class='boldwarning'>$1</span>"
|
||||
)
|
||||
*/
|
||||
if (regexes.len)
|
||||
ehjax_send(data = list("syncRegex" = regexes))
|
||||
|
||||
/// Sends json encoded data to the browser.
|
||||
/datum/chatOutput/proc/ehjax_send(client/C = owner, window = "browseroutput", data)
|
||||
if(islist(data))
|
||||
data = json_encode(data)
|
||||
C << output("[data]", "[window]:ehjaxCallback")
|
||||
|
||||
/datum/chatOutput/proc/sendMusic(music, pitch)
|
||||
/**
|
||||
* Sends music data to the browser. If enabled by the browser, it will start playing.
|
||||
* Arguments:
|
||||
* music must be a https adress.
|
||||
* extra_data is a list. The keys "pitch", "start" and "end" are used.
|
||||
** "pitch" determines the playback rate
|
||||
** "start" determines the start time of the sound
|
||||
** "end" determines when the musics stops playing
|
||||
*/
|
||||
/datum/chatOutput/proc/sendMusic(music, pitch, list/extra_data) //someone remove pitch
|
||||
if(!findtext(music, GLOB.is_http_protocol))
|
||||
return
|
||||
var/list/music_data = list("adminMusic" = url_encode(url_encode(music)))
|
||||
if(pitch)
|
||||
music_data["musicRate"] = pitch
|
||||
|
||||
if(extra_data?.len)
|
||||
music_data["musicRate"] = extra_data["pitch"] || pitch
|
||||
music_data["musicSeek"] = extra_data["start"]
|
||||
music_data["musicHalt"] = extra_data["end"]
|
||||
|
||||
ehjax_send(data = music_data)
|
||||
|
||||
/// Stops music playing throw the browser.
|
||||
/datum/chatOutput/proc/stopMusic()
|
||||
ehjax_send(data = "stopMusic")
|
||||
|
||||
/// Setter for adminMusicVolume. Sanitizes the value to between 0 and 100.
|
||||
/datum/chatOutput/proc/setMusicVolume(volume = "")
|
||||
if(volume)
|
||||
adminMusicVolume = clamp(text2num(volume), 0, 100)
|
||||
|
||||
//Sends client connection details to the chat to handle and save
|
||||
/// Sends client connection details to the chat to handle and save
|
||||
/datum/chatOutput/proc/sendClientData()
|
||||
//Get dem deets
|
||||
var/list/deets = list("clientData" = list())
|
||||
@@ -150,11 +212,11 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
var/data = json_encode(deets)
|
||||
ehjax_send(data = data)
|
||||
|
||||
//Called by client, sent data to investigate (cookie history so far)
|
||||
/// Called by client, sent data to investigate (cookie history so far)
|
||||
/datum/chatOutput/proc/analyzeClientData(cookie = "")
|
||||
//Spam check
|
||||
if(world.time > last_check + (3 SECONDS))
|
||||
last_check = world.time
|
||||
if(world.time > next_time_to_clear)
|
||||
next_time_to_clear = world.time + (3 SECONDS)
|
||||
total_checks = 0
|
||||
|
||||
total_checks += 1
|
||||
@@ -172,12 +234,13 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
if (connData && islist(connData) && connData.len > 0 && connData["connData"])
|
||||
connectionHistory = connData["connData"] //lol fuck
|
||||
var/list/found = new()
|
||||
if(connectionHistory.len > 5)
|
||||
|
||||
if(connectionHistory.len > MAX_COOKIE_LENGTH)
|
||||
message_admins("[key_name(src.owner)] was kicked for an invalid ban cookie)")
|
||||
qdel(owner)
|
||||
return
|
||||
|
||||
for(var/i in min(connectionHistory.len, 5) to 1 step -1)
|
||||
for(var/i in connectionHistory.len to 1 step -1)
|
||||
if(QDELETED(owner))
|
||||
//he got cleaned up before we were done
|
||||
return
|
||||
@@ -191,45 +254,33 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
|
||||
//Uh oh this fucker has a history of playing on a banned account!!
|
||||
if (found.len > 0)
|
||||
//TODO: add a new evasion ban for the CURRENT client details, using the matched row details
|
||||
message_admins("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
|
||||
log_admin_private("[key_name(owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
|
||||
|
||||
cookieSent = TRUE
|
||||
|
||||
//Called by js client every 60 seconds
|
||||
/// Called by js client every 60 seconds
|
||||
/datum/chatOutput/proc/ping()
|
||||
return "pong"
|
||||
|
||||
//Called by js client on js error
|
||||
/// Called by js client on js error
|
||||
/datum/chatOutput/proc/debug(error)
|
||||
log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
|
||||
|
||||
//Global chat procs
|
||||
/proc/to_chat_immediate(target, message, handle_whitespace=TRUE)
|
||||
/// Global chat proc. to_chat_immediate will circumvent SSchat and send data as soon as possible.
|
||||
/proc/to_chat_immediate(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE)
|
||||
if(!target || !message)
|
||||
return
|
||||
|
||||
//Ok so I did my best but I accept that some calls to this will be for shit like sound and images
|
||||
//It stands that we PROBABLY don't want to output those to the browser output so just handle them here
|
||||
if (istype(target, /savefile))
|
||||
CRASH("Invalid message! [message]")
|
||||
|
||||
if(!istext(message))
|
||||
if (istype(message, /image) || istype(message, /sound))
|
||||
CRASH("Invalid message! [message]")
|
||||
return
|
||||
|
||||
if(target == world)
|
||||
target = GLOB.clients
|
||||
|
||||
var/original_message = message
|
||||
//Some macros remain in the string even after parsing and fuck up the eventual output
|
||||
message = replacetext(message, "\improper", "")
|
||||
message = replacetext(message, "\proper", "")
|
||||
if(handle_whitespace)
|
||||
message = replacetext(message, "\n", "<br>")
|
||||
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
|
||||
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") //EIGHT SPACES IN TOTAL!!
|
||||
if(trailing_newline)
|
||||
message += "<br>"
|
||||
|
||||
if(islist(target))
|
||||
// Do the double-encoding outside the loop to save nanoseconds
|
||||
@@ -272,14 +323,19 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
// url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
|
||||
C << output(url_encode(url_encode(message)), "browseroutput:output")
|
||||
|
||||
/proc/to_chat(target, message, handle_whitespace = TRUE)
|
||||
/// Sends a text message to the target.
|
||||
/proc/to_chat(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE)
|
||||
if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
|
||||
to_chat_immediate(target, message, handle_whitespace)
|
||||
to_chat_immediate(target, message, handle_whitespace, trailing_newline, confidential)
|
||||
return
|
||||
SSchat.queue(target, message, handle_whitespace)
|
||||
SSchat.queue(target, message, handle_whitespace, trailing_newline, confidential)
|
||||
|
||||
/datum/chatOutput/proc/swaptolightmode() //Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation)
|
||||
/// Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation)
|
||||
/datum/chatOutput/proc/swaptolightmode()
|
||||
owner.force_white_theme()
|
||||
|
||||
/// Light mode stuff. (See darkmode.dm for documentation)
|
||||
/datum/chatOutput/proc/swaptodarkmode()
|
||||
owner.force_dark_theme()
|
||||
|
||||
#undef MAX_COOKIE_LENGTH
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
<a href="#" class="subCell toggle" id="toggleOptions" title="Options"><i class="fas fa-cog"></i></a>
|
||||
</div>
|
||||
<div class="sub" id="subOptions">
|
||||
<a href="#" class="subCell decreaseFont topCell" id="decreaseFont"><span>Decrease font size</span> <i class="fas fa-font">-</i></a>
|
||||
<a href="#" class="subCell increaseFont" id="increaseFont"><span>Increase font size</span> <i class="fas fa-font">+</i></a>
|
||||
<a href="#" class="subCell decreaseLineHeight" id="decreaseLineHeight"><span>Decrease line height</span> <i class="fas fa-text-height">-</i></a>
|
||||
<a href="#" class="subCell increaseLineHeight" id="increaseLineHeight"><span>Increase line height</span> <i class="fas fa-text-height">+</i></a>
|
||||
<a href="#" class="subCell decreaseFont topCell" id="decreaseFont"><span>Decrease font size</span> <i class="fas fa-font"></i></a>
|
||||
<a href="#" class="subCell increaseFont" id="increaseFont"><span>Increase font size</span> <i class="fas fa-font"></i></a>
|
||||
<a href="#" class="subCell decreaseLineHeight" id="decreaseLineHeight"><span>Decrease line height</span> <i class="fas fa-text-height"></i></a>
|
||||
<a href="#" class="subCell increaseLineHeight" id="increaseLineHeight"><span>Increase line height</span> <i class="fas fa-text-height"></i></a>
|
||||
<a href="#" class="subCell togglePing" id="togglePing"><span>Toggle ping display</span> <i class="fas fa-circle"></i></a>
|
||||
<a href="#" class="subCell highlightTerm" id="highlightTerm"><span>Highlight string</span> <i class="fas fa-tag"></i></a>
|
||||
<a href="#" class="subCell saveLog" id="saveLog"><span>Save chat log</span> <i class="fas fa-save"></i></a>
|
||||
|
||||
@@ -29,12 +29,13 @@ var opts = {
|
||||
'scrollSnapTolerance': 10, //If within x pixels of bottom
|
||||
'clickTolerance': 10, //Keep focus if outside x pixels of mousedown position on mouseup
|
||||
'imageRetryDelay': 50, //how long between attempts to reload images (in ms)
|
||||
'imageRetryLimit': 50, //how many attempts should we make?
|
||||
'imageRetryLimit': 50, //how many attempts should we make?
|
||||
'popups': 0, //Amount of popups opened ever
|
||||
'wasd': false, //Is the user in wasd mode?
|
||||
'priorChatHeight': 0, //Thing for height-resizing detection
|
||||
'restarting': false, //Is the round restarting?
|
||||
'colorPreset': 0, // index in the color presets list.
|
||||
//'darkmode':false, //Are we using darkmode? If not WHY ARE YOU LIVING IN 2009??? <- /tg/ take on darktheme
|
||||
|
||||
//Options menu
|
||||
'selectedSubLoop': null, //Contains the interval loop for closing the selected sub menu
|
||||
@@ -65,14 +66,17 @@ var opts = {
|
||||
'volumeUpdateDelay': 5000, //Time from when the volume updates to data being sent to the server
|
||||
'volumeUpdating': false, //True if volume update function set to fire
|
||||
'updatedVolume': 0, //The volume level that is sent to the server
|
||||
|
||||
'musicStartAt': 0, //The position the music starts playing
|
||||
'musicEndAt': 0, //The position the music... stops playing... if null, doesn't apply (so the music runs through)
|
||||
|
||||
'defaultMusicVolume': 25,
|
||||
|
||||
'messageCombining': true,
|
||||
|
||||
};
|
||||
var replaceRegexes = {};
|
||||
|
||||
// Array of names for chat display color presets.
|
||||
// Array of names for chat display color presets. CIT SPECIFIC.
|
||||
// If not set to normal, a CSS file `browserOutput_${name}.css` will be added to the head.
|
||||
var colorPresets = [
|
||||
'normal',
|
||||
@@ -84,12 +88,6 @@ function clamp(val, min, max) {
|
||||
return Math.max(min, Math.min(val, max))
|
||||
}
|
||||
|
||||
function outerHTML(el) {
|
||||
var wrap = document.createElement('div');
|
||||
wrap.appendChild(el.cloneNode(true));
|
||||
return wrap.innerHTML;
|
||||
}
|
||||
|
||||
//Polyfill for fucking date now because of course IE8 and below don't support it
|
||||
if (!Date.now) {
|
||||
Date.now = function now() {
|
||||
@@ -103,6 +101,7 @@ if (typeof String.prototype.trim !== 'function') {
|
||||
};
|
||||
}
|
||||
|
||||
// CIT SPECIFIC.
|
||||
function updateColorPreset() {
|
||||
var el = $("#colorPresetLink")[0];
|
||||
el.href = "browserOutput_"+colorPresets[opts.colorPreset]+".css";
|
||||
@@ -172,7 +171,7 @@ function byondDecode(message) {
|
||||
// The replace for + is because FOR SOME REASON, BYOND replaces spaces with a + instead of %20, and a plus with %2b.
|
||||
// Marvelous.
|
||||
message = message.replace(/\+/g, "%20");
|
||||
try {
|
||||
try {
|
||||
// This is a workaround for the above not always working when BYOND's shitty url encoding breaks. (byond bug id:2399401)
|
||||
if (decodeURIComponent) {
|
||||
message = decodeURIComponent(message);
|
||||
@@ -185,57 +184,71 @@ function byondDecode(message) {
|
||||
return message;
|
||||
}
|
||||
|
||||
//Actually turns the highlight term match into appropriate html
|
||||
function addHighlightMarkup(match) {
|
||||
var extra = '';
|
||||
if (opts.highlightColor) {
|
||||
extra += ' style="background-color: '+opts.highlightColor+'"';
|
||||
function replaceRegex() {
|
||||
var selectedRegex = replaceRegexes[$(this).attr('replaceRegex')];
|
||||
if (selectedRegex) {
|
||||
var replacedText = $(this).html().replace(selectedRegex[0], selectedRegex[1]);
|
||||
$(this).html(replacedText);
|
||||
}
|
||||
return '<span class="highlight"'+extra+'>'+match+'</span>';
|
||||
$(this).removeAttr('replaceRegex');
|
||||
}
|
||||
|
||||
//Highlights words based on user settings
|
||||
// Get a highlight markup span
|
||||
function createHighlightMarkup() {
|
||||
var extra = '';
|
||||
if (opts.highlightColor) {
|
||||
extra += ' style="background-color: ' + opts.highlightColor + '"';
|
||||
}
|
||||
return '<span class="highlight"' + extra + '></span>';
|
||||
}
|
||||
|
||||
// Get all child text nodes that match a regex pattern
|
||||
function getTextNodes(elem, pattern) {
|
||||
var result = $([]);
|
||||
$(elem).contents().each(function(idx, child) {
|
||||
if (child.nodeType === 3 && /\S/.test(child.nodeValue) && pattern.test(child.nodeValue)) {
|
||||
result = result.add(child);
|
||||
}
|
||||
else {
|
||||
result = result.add(getTextNodes(child, pattern));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Highlight all text terms matching the registered regex patterns
|
||||
function highlightTerms(el) {
|
||||
if (el.children.length > 0) {
|
||||
for(var h = 0; h < el.children.length; h++){
|
||||
highlightTerms(el.children[h]);
|
||||
}
|
||||
}
|
||||
var pattern = new RegExp("(" + opts.highlightTerms.join('|') + ")", 'gi');
|
||||
var nodes = getTextNodes(el, pattern);
|
||||
|
||||
var hasTextNode = false;
|
||||
for (var node = 0; node < el.childNodes.length; node++)
|
||||
{
|
||||
if (el.childNodes[node].nodeType === 3)
|
||||
{
|
||||
hasTextNode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasTextNode) { //If element actually has text
|
||||
var newText = '';
|
||||
for (var c = 0; c < el.childNodes.length; c++) { //Each child element
|
||||
if (el.childNodes[c].nodeType === 3) { //Is it text only?
|
||||
var words = el.childNodes[c].data.split(' ');
|
||||
for (var w = 0; w < words.length; w++) { //Each word in the text
|
||||
var newWord = null;
|
||||
for (var i = 0; i < opts.highlightTerms.length; i++) { //Each highlight term
|
||||
if (opts.highlightTerms[i] && words[w].toLowerCase().indexOf(opts.highlightTerms[i].toLowerCase()) > -1) { //If a match is found
|
||||
newWord = words[w].replace("<", "<").replace(new RegExp(opts.highlightTerms[i], 'gi'), addHighlightMarkup);
|
||||
break;
|
||||
}
|
||||
if (window.console)
|
||||
console.log(newWord)
|
||||
}
|
||||
newText += newWord || words[w].replace("<", "<");
|
||||
newText += w >= words.length - 1 ? '' : ' ';
|
||||
}
|
||||
} else { //Every other type of element
|
||||
newText += outerHTML(el.childNodes[c]);
|
||||
nodes.each(function (idx, node) {
|
||||
var content = $(node).text();
|
||||
var parent = $(node).parent();
|
||||
var pre = $(node.previousSibling);
|
||||
$(node).remove();
|
||||
content.split(pattern).forEach(function (chunk) {
|
||||
// Get our highlighted span/text node
|
||||
var toInsert = null;
|
||||
if (pattern.test(chunk)) {
|
||||
var tmpElem = $(createHighlightMarkup());
|
||||
tmpElem.text(chunk);
|
||||
toInsert = tmpElem;
|
||||
}
|
||||
}
|
||||
el.innerHTML = newText;
|
||||
}
|
||||
else {
|
||||
toInsert = document.createTextNode(chunk);
|
||||
}
|
||||
|
||||
// Insert back into our element
|
||||
if (pre.length == 0) {
|
||||
var result = parent.prepend(toInsert);
|
||||
pre = $(result[0].firstChild);
|
||||
}
|
||||
else {
|
||||
pre.after(toInsert);
|
||||
pre = $(pre[0].nextSibling);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function iconError(E) {
|
||||
@@ -268,41 +281,96 @@ function output(message, flag) {
|
||||
|
||||
message = byondDecode(message).trim();
|
||||
|
||||
//Stuff we do along with appending a message
|
||||
var atBottom = false;
|
||||
var bodyHeight = $('body').height();
|
||||
var messagesHeight = $messages.outerHeight();
|
||||
var scrollPos = $('body,html').scrollTop();
|
||||
|
||||
//Should we snap the output to the bottom?
|
||||
if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) {
|
||||
atBottom = true;
|
||||
if ($('#newMessages').length) {
|
||||
$('#newMessages').remove();
|
||||
}
|
||||
//If not, put the new messages box in
|
||||
} else {
|
||||
if ($('#newMessages').length) {
|
||||
var messages = $('#newMessages .number').text();
|
||||
messages = parseInt(messages);
|
||||
messages++;
|
||||
$('#newMessages .number').text(messages);
|
||||
if (messages == 2) {
|
||||
$('#newMessages .messageWord').append('s');
|
||||
//The behemoth of filter-code (for Admin message filters)
|
||||
//Note: This is proooobably hella inefficient
|
||||
var filteredOut = false;
|
||||
if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) {
|
||||
//Get this filter type (defined by class on message)
|
||||
var messageHtml = $.parseHTML(message),
|
||||
messageClasses;
|
||||
if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) {
|
||||
var internal = false;
|
||||
messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false);
|
||||
if (messageClasses) {
|
||||
for (var i = 0; i < messageClasses.length; i++) { //Every class
|
||||
if (messageClasses[i] == 'internal') {
|
||||
internal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!internal) {
|
||||
filteredOut = 'All';
|
||||
}
|
||||
} else {
|
||||
$messages.after('<a href="#" id="newMessages"><span class="number">1</span> new <span class="messageWord">message</span> <i class="icon-double-angle-down"></i></a>');
|
||||
//If the element or it's child have any classes
|
||||
if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) {
|
||||
messageClasses = $(messageHtml).attr('class').split(/\s+/);
|
||||
if (!!$(messageHtml).children().attr('class')) {
|
||||
messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/));
|
||||
}
|
||||
var tempCount = 0;
|
||||
for (var i = 0; i < messageClasses.length; i++) { //Every class
|
||||
var thisClass = messageClasses[i];
|
||||
$.each(opts.showMessagesFilters, function(key, val) { //Every filter
|
||||
if (key !== 'All' && val.show === false && typeof val.match != 'undefined') {
|
||||
for (var i = 0; i < val.match.length; i++) {
|
||||
var matchClass = val.match[i];
|
||||
if (matchClass == thisClass) {
|
||||
filteredOut = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filteredOut) return false;
|
||||
});
|
||||
if (filteredOut) break;
|
||||
tempCount++;
|
||||
}
|
||||
} else {
|
||||
if (!opts.showMessagesFilters['Misc'].show) {
|
||||
filteredOut = 'Misc';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Stuff we do along with appending a message
|
||||
var atBottom = false;
|
||||
if (!filteredOut) {
|
||||
var bodyHeight = $('body').height();
|
||||
var messagesHeight = $messages.outerHeight();
|
||||
var scrollPos = $('body,html').scrollTop();
|
||||
|
||||
//Should we snap the output to the bottom?
|
||||
if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) {
|
||||
atBottom = true;
|
||||
if ($('#newMessages').length) {
|
||||
$('#newMessages').remove();
|
||||
}
|
||||
//If not, put the new messages box in
|
||||
} else {
|
||||
if ($('#newMessages').length) {
|
||||
var messages = $('#newMessages .number').text();
|
||||
messages = parseInt(messages);
|
||||
messages++;
|
||||
$('#newMessages .number').text(messages);
|
||||
if (messages == 2) {
|
||||
$('#newMessages .messageWord').append('s');
|
||||
}
|
||||
} else {
|
||||
$messages.after('<a href="#" id="newMessages"><span class="number">1</span> new <span class="messageWord">message</span> <i class="icon-double-angle-down"></i></a>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opts.messageCount++;
|
||||
|
||||
//Pop the top message off if history limit reached
|
||||
//if (opts.messageCount >= opts.messageLimit) {
|
||||
//$messages.children('div.entry:first-child').remove();
|
||||
//opts.messageCount--; //I guess the count should only ever equal the limit
|
||||
//}
|
||||
if (opts.messageCount >= opts.messageLimit) {
|
||||
$messages.children('div.entry:first-child').remove();
|
||||
opts.messageCount--; //I guess the count should only ever equal the limit
|
||||
}
|
||||
|
||||
// Create the element - if combining is off, we use it, and if it's on, we
|
||||
// might discard it bug need to check its text content. Some messages vary
|
||||
@@ -323,6 +391,7 @@ function output(message, flag) {
|
||||
badge = $('<span/>', {'class': 'r', 'text': 2});
|
||||
}
|
||||
lastmessages.html(message);
|
||||
lastmessages.find('[replaceRegex]').each(replaceRegex);
|
||||
lastmessages.append(badge);
|
||||
badge.animate({
|
||||
"font-size": "0.9em"
|
||||
@@ -340,6 +409,13 @@ function output(message, flag) {
|
||||
//Actually append the message
|
||||
entry.className = 'entry';
|
||||
|
||||
if (filteredOut) {
|
||||
entry.className += ' hidden';
|
||||
entry.setAttribute('data-filter', filteredOut);
|
||||
}
|
||||
|
||||
$(entry).find('[replaceRegex]').each(replaceRegex);
|
||||
|
||||
$last_message = trimmed_message;
|
||||
$messages[0].appendChild(entry);
|
||||
$(entry).find("img.icon").error(iconError);
|
||||
@@ -360,11 +436,11 @@ function output(message, flag) {
|
||||
//Actually do the snap
|
||||
//Stuff we can do after the message shows can go here, in the interests of responsiveness
|
||||
if (opts.highlightTerms && opts.highlightTerms.length > 0) {
|
||||
highlightTerms(entry);
|
||||
highlightTerms($(entry));
|
||||
}
|
||||
}
|
||||
|
||||
if (atBottom) {
|
||||
if (!filteredOut && atBottom) {
|
||||
$('body,html').scrollTop($messages.outerHeight());
|
||||
}
|
||||
}
|
||||
@@ -408,6 +484,20 @@ function toHex(n) {
|
||||
return "0123456789ABCDEF".charAt((n-n%16)/16) + "0123456789ABCDEF".charAt(n%16);
|
||||
}
|
||||
|
||||
/*
|
||||
function swap() { //Swap to darkmode
|
||||
if (opts.darkmode){
|
||||
document.getElementById("sheetofstyles").href = "browserOutput_white.css";
|
||||
opts.darkmode = false;
|
||||
runByond('?_src_=chat&proc=swaptolightmode');
|
||||
} else {
|
||||
document.getElementById("sheetofstyles").href = "browserOutput.css";
|
||||
opts.darkmode = true;
|
||||
runByond('?_src_=chat&proc=swaptodarkmode');
|
||||
}
|
||||
setCookie('darkmode', (opts.darkmode ? 'true' : 'false'), 365);
|
||||
}
|
||||
*/
|
||||
function handleClientData(ckey, ip, compid) {
|
||||
//byond sends player info to here
|
||||
var currentData = {'ckey': ckey, 'ip': ip, 'compid': compid};
|
||||
@@ -488,6 +578,7 @@ function ehjaxCallback(data) {
|
||||
} else if (data.adminMusic) {
|
||||
if (typeof data.adminMusic === 'string') {
|
||||
var adminMusic = byondDecode(data.adminMusic);
|
||||
var bindLoadedData = false;
|
||||
adminMusic = adminMusic.match(/https?:\/\/\S+/) || '';
|
||||
if (data.musicRate) {
|
||||
var newRate = Number(data.musicRate);
|
||||
@@ -497,9 +588,32 @@ function ehjaxCallback(data) {
|
||||
} else {
|
||||
$('#adminMusic').prop('defaultPlaybackRate', 1.0);
|
||||
}
|
||||
if (data.musicSeek) {
|
||||
opts.musicStartAt = Number(data.musicSeek) || 0;
|
||||
bindLoadedData = true;
|
||||
} else {
|
||||
opts.musicStartAt = 0;
|
||||
}
|
||||
if (data.musicHalt) {
|
||||
opts.musicEndAt = Number(data.musicHalt) || null;
|
||||
bindLoadedData = true;
|
||||
}
|
||||
if (bindLoadedData) {
|
||||
$('#adminMusic').one('loadeddata', adminMusicLoadedData);
|
||||
}
|
||||
$('#adminMusic').prop('src', adminMusic);
|
||||
$('#adminMusic').trigger("play");
|
||||
}
|
||||
} else if (data.syncRegex) {
|
||||
for (var i in data.syncRegex) {
|
||||
|
||||
var regexData = data.syncRegex[i];
|
||||
var regexName = regexData[0];
|
||||
var regexFlags = regexData[1];
|
||||
var regexReplaced = regexData[2];
|
||||
|
||||
replaceRegexes[i] = [new RegExp(regexName, regexFlags), regexReplaced];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -530,6 +644,27 @@ function sendVolumeUpdate() {
|
||||
}
|
||||
}
|
||||
|
||||
function adminMusicEndCheck(event) {
|
||||
if (opts.musicEndAt) {
|
||||
if ($('#adminMusic').prop('currentTime') >= opts.musicEndAt) {
|
||||
$('#adminMusic').off(event);
|
||||
$('#adminMusic').trigger('pause');
|
||||
$('#adminMusic').prop('src', '');
|
||||
}
|
||||
} else {
|
||||
$('#adminMusic').off(event);
|
||||
}
|
||||
}
|
||||
|
||||
function adminMusicLoadedData(event) {
|
||||
if (opts.musicStartAt && ($('#adminMusic').prop('duration') === Infinity || (opts.musicStartAt <= $('#adminMusic').prop('duration'))) ) {
|
||||
$('#adminMusic').prop('currentTime', opts.musicStartAt);
|
||||
}
|
||||
if (opts.musicEndAt) {
|
||||
$('#adminMusic').on('timeupdate', adminMusicEndCheck);
|
||||
}
|
||||
}
|
||||
|
||||
function subSlideUp() {
|
||||
$(this).removeClass('scroll');
|
||||
$(this).css('height', '');
|
||||
@@ -608,23 +743,32 @@ $(function() {
|
||||
*
|
||||
******************************************/
|
||||
var savedConfig = {
|
||||
'sfontSize': getCookie('fontsize'),
|
||||
'slineHeight': getCookie('lineheight'),
|
||||
fontsize: getCookie('fontsize'), //no need for compatabiliy, cookie name is the same
|
||||
lineheight: getCookie('lineheight'),
|
||||
'spingDisabled': getCookie('pingdisabled'),
|
||||
'shighlightTerms': getCookie('highlightterms'),
|
||||
'shighlightColor': getCookie('highlightcolor'),
|
||||
'smusicVolume': getCookie('musicVolume'),
|
||||
'smessagecombining': getCookie('messagecombining'),
|
||||
'sdarkmode': getCookie('darkmode'),
|
||||
'scolorPreset': getCookie('colorpreset'),
|
||||
};
|
||||
|
||||
if (savedConfig.sfontSize) {
|
||||
$messages.css('font-size', savedConfig.sfontSize);
|
||||
internalOutput('<span class="internal boldnshit">Loaded font size setting of: '+savedConfig.sfontSize+'</span>', 'internal');
|
||||
if (savedConfig.fontsize) {
|
||||
$messages.css('font-size', savedConfig.fontsize);
|
||||
internalOutput('<span class="internal boldnshit">Loaded font size setting of: '+savedConfig.fontsize+'</span>', 'internal');
|
||||
}
|
||||
if (savedConfig.slineHeight) {
|
||||
$("body").css('line-height', savedConfig.slineHeight);
|
||||
internalOutput('<span class="internal boldnshit">Loaded line height setting of: '+savedConfig.slineHeight+'</span>', 'internal');
|
||||
if (savedConfig.lineheight) {
|
||||
$("body").css('line-height', savedConfig.lineheight);
|
||||
internalOutput('<span class="internal boldnshit">Loaded line height setting of: '+savedConfig.lineheight+'</span>', 'internal');
|
||||
}
|
||||
// if(savedConfig.sdarkmode == 'true'){
|
||||
// swap();
|
||||
// }
|
||||
if (savedConfig.scolorPreset) {
|
||||
opts.colorPreset = Number(savedConfig.scolorPreset);
|
||||
updateColorPreset();
|
||||
internalOutput('<span class="internal boldnshit">Loaded color preset of: '+colorPresets[opts.colorPreset]+'</span>', 'internal');
|
||||
}
|
||||
if (savedConfig.spingDisabled) {
|
||||
if (savedConfig.spingDisabled == 'true') {
|
||||
@@ -634,15 +778,11 @@ $(function() {
|
||||
internalOutput('<span class="internal boldnshit">Loaded ping display of: '+(opts.pingDisabled ? 'hidden' : 'visible')+'</span>', 'internal');
|
||||
}
|
||||
if (savedConfig.shighlightTerms) {
|
||||
var savedTerms = $.parseJSON(savedConfig.shighlightTerms);
|
||||
var actualTerms = '';
|
||||
for (var i = 0; i < savedTerms.length; i++) {
|
||||
if (savedTerms[i]) {
|
||||
actualTerms += savedTerms[i] + ', ';
|
||||
}
|
||||
}
|
||||
var savedTerms = $.parseJSON(savedConfig.shighlightTerms).filter(function (entry) {
|
||||
return entry !== null && /\S/.test(entry);
|
||||
});
|
||||
var actualTerms = savedTerms.length != 0 ? savedTerms.join(', ') : null;
|
||||
if (actualTerms) {
|
||||
actualTerms = actualTerms.substring(0, actualTerms.length - 2);
|
||||
internalOutput('<span class="internal boldnshit">Loaded highlight strings of: ' + actualTerms+'</span>', 'internal');
|
||||
opts.highlightTerms = savedTerms;
|
||||
}
|
||||
@@ -651,13 +791,6 @@ $(function() {
|
||||
opts.highlightColor = savedConfig.shighlightColor;
|
||||
internalOutput('<span class="internal boldnshit">Loaded highlight color of: '+savedConfig.shighlightColor+'</span>', 'internal');
|
||||
}
|
||||
|
||||
if (savedConfig.scolorPreset) {
|
||||
opts.colorPreset = Number(savedConfig.scolorPreset);
|
||||
updateColorPreset();
|
||||
internalOutput('<span class="internal boldnshit">Loaded color preset of: '+colorPresets[opts.colorPreset]+'</span>', 'internal');
|
||||
}
|
||||
|
||||
if (savedConfig.smusicVolume) {
|
||||
var newVolume = clamp(savedConfig.smusicVolume, 0, 100);
|
||||
$('#adminMusic').prop('volume', newVolume / 100);
|
||||
@@ -669,7 +802,7 @@ $(function() {
|
||||
else{
|
||||
$('#adminMusic').prop('volume', opts.defaultMusicVolume / 100);
|
||||
}
|
||||
|
||||
|
||||
if (savedConfig.smessagecombining) {
|
||||
if (savedConfig.smessagecombining == 'false') {
|
||||
opts.messageCombining = false;
|
||||
@@ -746,76 +879,17 @@ $(function() {
|
||||
href = escaper(href);
|
||||
runByond('?action=openLink&link='+href);
|
||||
}
|
||||
runByond('byond://winset?mapwindow.map.focus=true');
|
||||
});
|
||||
|
||||
//Fuck everything about this event. Will look into alternatives.
|
||||
$('body').on('keydown', function(e) {
|
||||
if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.ctrlKey || e.altKey || e.shiftKey) { //Band-aid "fix" for allowing ctrl+c copy paste etc. Needs a proper fix.
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
var k = e.which;
|
||||
// Hardcoded because else there would be no feedback message.
|
||||
if (k == 113) { // F2
|
||||
runByond('byond://winset?screenshot=auto');
|
||||
internalOutput('Screenshot taken', 'internal');
|
||||
}
|
||||
|
||||
var c = "";
|
||||
switch (k) {
|
||||
case 8:
|
||||
c = 'BACK';
|
||||
case 9:
|
||||
c = 'TAB';
|
||||
case 13:
|
||||
c = 'ENTER';
|
||||
case 19:
|
||||
c = 'PAUSE';
|
||||
case 27:
|
||||
c = 'ESCAPE';
|
||||
case 33: // Page up
|
||||
c = 'NORTHEAST';
|
||||
case 34: // Page down
|
||||
c = 'SOUTHEAST';
|
||||
case 35: // End
|
||||
c = 'SOUTHWEST';
|
||||
case 36: // Home
|
||||
c = 'NORTHWEST';
|
||||
case 37:
|
||||
c = 'WEST';
|
||||
case 38:
|
||||
c = 'NORTH';
|
||||
case 39:
|
||||
c = 'EAST';
|
||||
case 40:
|
||||
c = 'SOUTH';
|
||||
case 45:
|
||||
c = 'INSERT';
|
||||
case 46:
|
||||
c = 'DELETE';
|
||||
case 93: // That weird thing to the right of alt gr.
|
||||
c = 'APPS';
|
||||
|
||||
default:
|
||||
c = String.fromCharCode(k);
|
||||
}
|
||||
|
||||
if (c.length == 0) {
|
||||
if (!e.shiftKey) {
|
||||
c = c.toLowerCase();
|
||||
}
|
||||
runByond('byond://winset?mapwindow.map.focus=true;mainwindow.input.text='+c);
|
||||
return false;
|
||||
} else {
|
||||
runByond('byond://winset?mapwindow.map.focus=true');
|
||||
return false;
|
||||
}
|
||||
runByond('byond://winset?mapwindow.map.focus=true');
|
||||
});
|
||||
|
||||
//Mildly hacky fix for scroll issues on mob change (interface gets resized sometimes, messing up snap-scroll)
|
||||
@@ -843,6 +917,9 @@ $(function() {
|
||||
$('#toggleOptions').click(function(e) {
|
||||
handleToggleClick($subOptions, $(this));
|
||||
});
|
||||
// $('#darkmodetoggle').click(function(e) {
|
||||
// swap();
|
||||
// });
|
||||
$('#toggleAudio').click(function(e) {
|
||||
handleToggleClick($subAudio, $(this));
|
||||
});
|
||||
@@ -856,41 +933,31 @@ $(function() {
|
||||
});
|
||||
|
||||
$('#decreaseFont').click(function(e) {
|
||||
var fontSize = parseInt($messages.css('font-size'));
|
||||
fontSize = fontSize - 1 + 'px';
|
||||
$messages.css({'font-size': fontSize});
|
||||
setCookie('fontsize', fontSize, 365);
|
||||
internalOutput('<span class="internal boldnshit">Font size set to '+fontSize+'</span>', 'internal');
|
||||
savedConfig.fontsize = Math.max(parseInt(savedConfig.fontsize || 13) - 1, 1) + 'px';
|
||||
$messages.css({'font-size': savedConfig.fontsize});
|
||||
setCookie('fontsize', savedConfig.fontsize, 365);
|
||||
internalOutput('<span class="internal boldnshit">Font size set to '+savedConfig.fontsize+'</span>', 'internal');
|
||||
});
|
||||
|
||||
$('#increaseFont').click(function(e) {
|
||||
var fontSize = parseInt($messages.css('font-size'));
|
||||
fontSize = fontSize + 1 + 'px';
|
||||
$messages.css({'font-size': fontSize});
|
||||
setCookie('fontsize', fontSize, 365);
|
||||
internalOutput('<span class="internal boldnshit">Font size set to '+fontSize+'</span>', 'internal');
|
||||
savedConfig.fontsize = (parseInt(savedConfig.fontsize || 13) + 1) + 'px';
|
||||
$messages.css({'font-size': savedConfig.fontsize});
|
||||
setCookie('fontsize', savedConfig.fontsize, 365);
|
||||
internalOutput('<span class="internal boldnshit">Font size set to '+savedConfig.fontsize+'</span>', 'internal');
|
||||
});
|
||||
|
||||
$('#decreaseLineHeight').click(function(e) {
|
||||
var Heightline = parseFloat($("body").css('line-height'));
|
||||
var Sizefont = parseFloat($("body").css('font-size'));
|
||||
var lineheightvar = Heightline / Sizefont
|
||||
lineheightvar -= 0.1;
|
||||
lineheightvar = lineheightvar.toFixed(1)
|
||||
$("body").css({'line-height': lineheightvar});
|
||||
setCookie('lineheight', lineheightvar, 365);
|
||||
internalOutput('<span class="internal boldnshit">Line height set to '+lineheightvar+'</span>', 'internal');
|
||||
savedConfig.lineheight = Math.max(parseFloat(savedConfig.lineheight || 1.2) - 0.1, 0.1).toFixed(1);
|
||||
$("body").css({'line-height': savedConfig.lineheight});
|
||||
setCookie('lineheight', savedConfig.lineheight, 365);
|
||||
internalOutput('<span class="internal boldnshit">Line height set to '+savedConfig.lineheight+'</span>', 'internal');
|
||||
});
|
||||
|
||||
$('#increaseLineHeight').click(function(e) {
|
||||
var Heightline = parseFloat($("body").css('line-height'));
|
||||
var Sizefont = parseFloat($("body").css('font-size'));
|
||||
var lineheightvar = Heightline / Sizefont
|
||||
lineheightvar += 0.1;
|
||||
lineheightvar = lineheightvar.toFixed(1)
|
||||
$("body").css({'line-height': lineheightvar});
|
||||
setCookie('lineheight', lineheightvar, 365);
|
||||
internalOutput('<span class="internal boldnshit">Line height set to '+lineheightvar+'</span>', 'internal');
|
||||
savedConfig.lineheight = (parseFloat(savedConfig.lineheight || 1.2) + 0.1).toFixed(1);
|
||||
$("body").css({'line-height': savedConfig.lineheight});
|
||||
setCookie('lineheight', savedConfig.lineheight, 365);
|
||||
internalOutput('<span class="internal boldnshit">Line height set to '+savedConfig.lineheight+'</span>', 'internal');
|
||||
});
|
||||
|
||||
$('#togglePing').click(function(e) {
|
||||
@@ -908,13 +975,13 @@ $(function() {
|
||||
// Requires IE 10+ to issue download commands. Just opening a popup
|
||||
// window will cause Ctrl+S to save a blank page, ignoring innerHTML.
|
||||
if (!window.Blob) {
|
||||
output('<span class="big red">This function is only supported on IE 10+. Upgrade if possible.</span>', 'internal');
|
||||
output('<span class="big red">This function is only supported on IE 10 and up. Upgrade if possible.</span>', 'internal');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'browserOutput.css',
|
||||
url: 'browserOutput.css', // browserOutput_white.css
|
||||
success: function(styleData) {
|
||||
var blob = new Blob(['<head><title>Chat Log</title><style>', styleData, '</style></head><body>', $messages.html(), '</body>']);
|
||||
|
||||
@@ -958,20 +1025,12 @@ $(function() {
|
||||
$('body').on('submit', '#highlightTermForm', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var count = 0;
|
||||
while (count < opts.highlightLimit) {
|
||||
opts.highlightTerms = [];
|
||||
for (var count = 0; count < opts.highlightLimit; count++) {
|
||||
var term = $('#highlightTermInput'+count).val();
|
||||
if (term) {
|
||||
term = term.trim();
|
||||
if (term === '') {
|
||||
opts.highlightTerms[count] = null;
|
||||
} else {
|
||||
opts.highlightTerms[count] = term.toLowerCase();
|
||||
}
|
||||
} else {
|
||||
opts.highlightTerms[count] = null;
|
||||
if (term !== null && /\S/.test(term)) {
|
||||
opts.highlightTerms.push(term.trim().toLowerCase());
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
var color = $('#highlightColor').val();
|
||||
@@ -992,8 +1051,8 @@ $(function() {
|
||||
$messages.empty();
|
||||
opts.messageCount = 0;
|
||||
});
|
||||
|
||||
$('#changeColorPreset').click(function() {
|
||||
|
||||
$('#changeColorPreset').click(function() { //CIT SPECIFIC
|
||||
opts.colorPreset = (opts.colorPreset+1) % colorPresets.length;
|
||||
updateColorPreset();
|
||||
setCookie('colorpreset', opts.colorPreset, 365);
|
||||
@@ -1026,9 +1085,9 @@ $(function() {
|
||||
});
|
||||
|
||||
$('img.icon').error(iconError);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************
|
||||
*
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/stank = new
|
||||
stank.gases[/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.temperature = T20C // without this the room would eventually freeze and miasma mining would be easier
|
||||
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.set_temperature(T20C) // without this the room would eventually freeze and miasma mining would be easier
|
||||
T.assume_air(stank)
|
||||
T.air_update_turf()
|
||||
|
||||
|
||||
@@ -226,8 +226,8 @@
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/O = loc
|
||||
if(O.air)
|
||||
var/loc_gases = O.air.gases
|
||||
if(loc_gases[/datum/gas/oxygen] > 13)
|
||||
var/datum/gas_mixture/loc_air = O.air
|
||||
if(loc_air.get_moles(/datum/gas/oxygen) > 13)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -125,12 +125,12 @@
|
||||
return
|
||||
|
||||
// Negative Kelvin temperatures should never happen and if they do, normalize them
|
||||
if(source_air.temperature < TCMB)
|
||||
source_air.temperature = TCMB
|
||||
if(source_air.return_temperature() < TCMB)
|
||||
source_air.set_temperature(TCMB)
|
||||
|
||||
var/pressure_delta = target_pressure - target_air.return_pressure()
|
||||
if(pressure_delta > 0.1)
|
||||
var/transfer_moles = (pressure_delta*target_air.volume/(source_air.temperature * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY
|
||||
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)
|
||||
target_air.merge(removed)
|
||||
|
||||
@@ -171,14 +171,14 @@
|
||||
return
|
||||
|
||||
// Negative Kelvin temperatures should never happen and if they do, normalize them
|
||||
if(source_air.temperature < TCMB)
|
||||
source_air.temperature = TCMB
|
||||
if(source_air.return_temperature() < TCMB)
|
||||
source_air.set_temperature(TCMB)
|
||||
|
||||
if((source_air.return_pressure() < 0.01) || (target_air.return_pressure() >= PUMP_MAX_PRESSURE))
|
||||
return
|
||||
|
||||
//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.volume*PUMP_MAX_PRESSURE/source_air.return_pressure())/source_air.volume
|
||||
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)
|
||||
|
||||
@@ -351,10 +351,10 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
var/transfer_moles
|
||||
|
||||
//Negative Kelvins are an anomaly and should be normalized if encountered
|
||||
if(source_air.temperature < TCMB)
|
||||
source_air.temperature = TCMB
|
||||
if(source_air.return_temperature(TCMB))
|
||||
source_air.set_temperature(TCMB)
|
||||
|
||||
transfer_moles = (pressure_delta*contaminated_air.volume/(source_air.temperature * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY
|
||||
transfer_moles = (pressure_delta*contaminated_air.return_volume()/(source_air.return_temperature() * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY
|
||||
|
||||
//If there is nothing to transfer, just return
|
||||
if(transfer_moles <= 0)
|
||||
@@ -368,16 +368,15 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
//This is the gas that will be moved from source to filtered
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
|
||||
for(var/filtered_gas in removed.gases)
|
||||
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)
|
||||
//The gas that is put in all the filtered out gases
|
||||
filtered_out.temperature = removed.temperature
|
||||
filtered_out.gases[filtered_gas] = removed.gases[filtered_gas]
|
||||
filtered_out.set_temperature(removed.return_temperature())
|
||||
filtered_out.set_moles(filtered_gas, removed.get_moles(filtered_gas))
|
||||
|
||||
//The filtered out gas is entirely removed from the currently filtered gases
|
||||
removed.gases[filtered_gas] = 0
|
||||
GAS_GARBAGE_COLLECT(removed.gases)
|
||||
removed.set_moles(filtered_gas, 0)
|
||||
|
||||
//Check if the pressure is high enough to put stuff in filtered, or else just put it back in the source
|
||||
var/datum/gas_mixture/target = (filtered_air.return_pressure() < target_pressure ? filtered_air : source_air)
|
||||
@@ -444,7 +443,7 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
var/gas_percentage = round(max(min(get_pin_data(IC_INPUT, 4),100),0) / 100)
|
||||
|
||||
//Basically: number of moles = percentage of pressure filled up * efficiency coefficient * (pressure from both gases * volume of output) / (R * Temperature)
|
||||
var/transfer_moles = (get_pin_data(IC_INPUT, 5) / max(1,output_gases.return_pressure())) * PUMP_EFFICIENCY * (source_1_gases.return_pressure() * gas_percentage + source_2_gases.return_pressure() * (1 - gas_percentage)) * output_gases.volume/ (R_IDEAL_GAS_EQUATION * max(output_gases.temperature,TCMB))
|
||||
var/transfer_moles = (get_pin_data(IC_INPUT, 5) / max(1,output_gases.return_pressure())) * PUMP_EFFICIENCY * (source_1_gases.return_pressure() * gas_percentage + source_2_gases.return_pressure() * (1 - gas_percentage)) * output_gases.return_volume()/ (R_IDEAL_GAS_EQUATION * max(output_gases.return_temperature(),TCMB))
|
||||
|
||||
|
||||
if(transfer_moles <= 0)
|
||||
@@ -544,10 +543,10 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
push_data()
|
||||
|
||||
//Cool the tank if the power is on and the temp is above
|
||||
if(!power_draw_idle || air_contents.temperature < temperature)
|
||||
if(!power_draw_idle || air_contents.return_temperature() < temperature)
|
||||
return
|
||||
|
||||
air_contents.temperature = max(73.15,air_contents.temperature - (air_contents.temperature - temperature) * heater_coefficient)
|
||||
air_contents.set_temperature(max(73.15,air_contents.return_temperature() - (air_contents.return_temperature() - temperature) * heater_coefficient))
|
||||
|
||||
|
||||
// - heater tank - // **works**
|
||||
@@ -574,10 +573,10 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
push_data()
|
||||
|
||||
//Heat the tank if the power is on or its temperature is below what is set
|
||||
if(!power_draw_idle || air_contents.temperature > temperature)
|
||||
if(!power_draw_idle || air_contents.return_temperature() > temperature)
|
||||
return
|
||||
|
||||
air_contents.temperature = min(573.15,air_contents.temperature + (temperature - air_contents.temperature) * heater_coefficient)
|
||||
air_contents.set_temperature(min(573.15,air_contents.return_temperature() + (temperature - air_contents.return_temperature()) * heater_coefficient))
|
||||
|
||||
|
||||
// - atmospheric cooler - // **works**
|
||||
@@ -621,11 +620,11 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/turf_air = current_turf.return_air()
|
||||
if(!power_draw_idle || turf_air.temperature < temperature)
|
||||
if(!power_draw_idle || turf_air.return_temperature() < temperature)
|
||||
return
|
||||
|
||||
//Cool the gas
|
||||
turf_air.temperature = max(243.15,turf_air.temperature - (turf_air.temperature - temperature) * heater_coefficient)
|
||||
turf_air.set_temperature(max(243.15,turf_air.return_temperature() - (turf_air.return_temperature() - temperature) * heater_coefficient))
|
||||
|
||||
|
||||
// - atmospheric heater - // **works**
|
||||
@@ -650,11 +649,11 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/turf_air = current_turf.return_air()
|
||||
if(!power_draw_idle || turf_air.temperature > temperature)
|
||||
if(!power_draw_idle || turf_air.return_temperature() > temperature)
|
||||
return
|
||||
|
||||
//Heat the gas
|
||||
turf_air.temperature = min(323.15,turf_air.temperature + (temperature - turf_air.temperature) * heater_coefficient)
|
||||
turf_air.set_temperature(min(323.15,turf_air.return_temperature() + (temperature - turf_air.return_temperature()) * heater_coefficient))
|
||||
|
||||
|
||||
// - tank slot - // **works**
|
||||
|
||||
@@ -1162,12 +1162,11 @@
|
||||
activate_pin(3)
|
||||
return
|
||||
|
||||
var/list/gases = air_contents.gases
|
||||
var/list/gas_names = list()
|
||||
var/list/gas_amounts = list()
|
||||
for(var/id in gases)
|
||||
for(var/id in air_contents.get_gases())
|
||||
var/name = GLOB.meta_gas_names[id]
|
||||
var/amt = round(gases[id], 0.001)
|
||||
var/amt = round(air_contents.get_moles(id), 0.001)
|
||||
gas_names.Add(name)
|
||||
gas_amounts.Add(amt)
|
||||
|
||||
@@ -1175,7 +1174,7 @@
|
||||
set_pin_data(IC_OUTPUT, 2, gas_amounts)
|
||||
set_pin_data(IC_OUTPUT, 3, round(air_contents.total_moles(), 0.001))
|
||||
set_pin_data(IC_OUTPUT, 4, round(air_contents.return_pressure(), 0.001))
|
||||
set_pin_data(IC_OUTPUT, 5, round(air_contents.temperature, 0.001))
|
||||
set_pin_data(IC_OUTPUT, 5, round(air_contents.return_temperature(), 0.001))
|
||||
set_pin_data(IC_OUTPUT, 6, round(air_contents.return_volume(), 0.001))
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
@@ -213,6 +213,7 @@
|
||||
var/list/modelCache = build_cache(no_changeturf)
|
||||
var/space_key = modelCache[SPACE_KEY]
|
||||
var/list/bounds
|
||||
var/did_expand = FALSE
|
||||
src.bounds = bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF)
|
||||
var/datum/map_orientation_pattern/mode = forced_pattern || GLOB.map_orientation_patterns["[orientation]"] || GLOB.map_orientation_patterns["[SOUTH]"]
|
||||
var/invert_y = mode.invert_y
|
||||
@@ -235,6 +236,7 @@
|
||||
else
|
||||
while(parsed_z > world.maxz)
|
||||
world.incrementMaxZ()
|
||||
did_expand = TRUE
|
||||
if(!no_changeturf)
|
||||
WARNING("Z-level expansion occurred without no_changeturf set, this may cause problems when /turf/AfterChange is called")
|
||||
//these values are the same until a new gridset is reached.
|
||||
@@ -256,11 +258,13 @@
|
||||
continue
|
||||
else
|
||||
world.maxx = placement_x
|
||||
did_expand = TRUE
|
||||
if(placement_y > world.maxy)
|
||||
if(cropMap)
|
||||
break
|
||||
else
|
||||
world.maxy = placement_y
|
||||
did_expand = TRUE
|
||||
if(placement_x < 1)
|
||||
actual_x += xi
|
||||
continue
|
||||
@@ -301,6 +305,9 @@
|
||||
testing("Skipped loading [turfsSkipped] default turfs")
|
||||
#endif
|
||||
|
||||
if(did_expand)
|
||||
world.refresh_atmos_grid()
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/parsed_map/proc/build_cache(no_changeturf, bad_paths=null)
|
||||
|
||||
@@ -7,6 +7,20 @@
|
||||
return get_step(SSmapping.get_turf_below(get_turf(ref)), dir)
|
||||
return get_step(ref, dir)
|
||||
|
||||
/proc/get_multiz_accessible_levels(center_z)
|
||||
. = list(center_z)
|
||||
var/other_z = center_z
|
||||
var/offset
|
||||
while((offset = SSmapping.level_trait(other_z, ZTRAIT_DOWN)))
|
||||
other_z += offset
|
||||
. += other_z
|
||||
other_z = center_z
|
||||
while((offset = SSmapping.level_trait(other_z, ZTRAIT_UP)))
|
||||
other_z += offset
|
||||
. += other_z
|
||||
return .
|
||||
|
||||
|
||||
/proc/get_dir_multiz(turf/us, turf/them)
|
||||
us = get_turf(us)
|
||||
them = get_turf(them)
|
||||
@@ -32,16 +46,4 @@
|
||||
|
||||
/turf/proc/below()
|
||||
return get_step_multiz(src, DOWN)
|
||||
|
||||
/proc/dir_inverse_multiz(dir)
|
||||
var/holder = dir & (UP|DOWN)
|
||||
if((holder == NONE) || (holder == (UP|DOWN)))
|
||||
return turn(dir, 180)
|
||||
dir &= ~(UP|DOWN)
|
||||
dir = turn(dir, 180)
|
||||
if(holder == UP)
|
||||
holder = DOWN
|
||||
else
|
||||
holder = UP
|
||||
dir |= holder
|
||||
return dir
|
||||
|
||||
@@ -13,26 +13,23 @@
|
||||
|
||||
var/toxins_used = 0
|
||||
var/tox_detect_threshold = 0.02
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
|
||||
var/list/breath_gases = breath.gases
|
||||
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_gases[/datum/gas/plasma]/breath.total_moles())*breath_pressure
|
||||
var/Toxins_pp = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure
|
||||
|
||||
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
|
||||
adjustPlasma(breath_gases[/datum/gas/plasma]*250)
|
||||
adjustPlasma(breath.get_moles(/datum/gas/plasma)*250)
|
||||
throw_alert("alien_tox", /obj/screen/alert/alien_tox)
|
||||
|
||||
toxins_used = breath_gases[/datum/gas/plasma]
|
||||
toxins_used = breath.get_moles(/datum/gas/plasma)
|
||||
|
||||
else
|
||||
clear_alert("alien_tox")
|
||||
|
||||
//Breathe in toxins and out oxygen
|
||||
breath_gases[/datum/gas/plasma] -= toxins_used
|
||||
breath_gases[/datum/gas/oxygen] += toxins_used
|
||||
|
||||
GAS_GARBAGE_COLLECT(breath.gases)
|
||||
breath.adjust_moles(/datum/gas/plasma, -toxins_used)
|
||||
breath.adjust_moles(/datum/gas/oxygen, toxins_used)
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
@@ -36,8 +36,9 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/experience_pressure_difference()
|
||||
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
|
||||
/mob/living/carbon/human/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target)
|
||||
if(prob(pressure_difference * 2.5))
|
||||
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
|
||||
if(shoes && istype(shoes, /obj/item/clothing))
|
||||
var/obj/item/clothing/S = shoes
|
||||
if (S.clothing_flags & NOSLIP)
|
||||
|
||||
@@ -33,7 +33,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.gases[/datum/gas/oxygen] && (environment.gases[/datum/gas/oxygen]) >= 1) //Same threshhold that extinguishes fire
|
||||
if(environment.get_moles(/datum/gas/oxygen) >= 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>")
|
||||
|
||||
@@ -162,12 +162,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.temperature)/BREATH_VOLUME
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
|
||||
|
||||
var/list/breath_gases = breath.gases
|
||||
var/O2_partialpressure = (breath_gases[/datum/gas/oxygen]/breath.total_moles())*breath_pressure
|
||||
var/Toxins_partialpressure = (breath_gases[/datum/gas/plasma]/breath.total_moles())*breath_pressure
|
||||
var/CO2_partialpressure = (breath_gases[/datum/gas/carbon_dioxide]/breath.total_moles())*breath_pressure
|
||||
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
|
||||
|
||||
|
||||
//OXYGEN
|
||||
@@ -191,7 +190,7 @@
|
||||
var/ratio = 1 - O2_partialpressure/safe_oxy_min
|
||||
adjustOxyLoss(min(5*ratio, 3))
|
||||
failed_last_breath = 1
|
||||
oxygen_used = breath_gases[/datum/gas/oxygen]*ratio
|
||||
oxygen_used = breath.get_moles(/datum/gas/oxygen)*ratio
|
||||
else
|
||||
adjustOxyLoss(3)
|
||||
failed_last_breath = 1
|
||||
@@ -203,12 +202,12 @@
|
||||
o2overloadtime = 0 //reset our counter for this too
|
||||
if(health >= crit_threshold)
|
||||
adjustOxyLoss(-5)
|
||||
oxygen_used = breath_gases[/datum/gas/oxygen]
|
||||
oxygen_used = breath.get_moles(/datum/gas/oxygen)
|
||||
clear_alert("not_enough_oxy")
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "suffocation")
|
||||
|
||||
breath_gases[/datum/gas/oxygen] -= oxygen_used
|
||||
breath_gases[/datum/gas/carbon_dioxide] += oxygen_used
|
||||
breath.adjust_moles(/datum/gas/oxygen, -oxygen_used)
|
||||
breath.adjust_moles(/datum/gas/carbon_dioxide, oxygen_used)
|
||||
|
||||
//CARBON DIOXIDE
|
||||
if(CO2_partialpressure > safe_co2_max)
|
||||
@@ -227,15 +226,15 @@
|
||||
|
||||
//TOXINS/PLASMA
|
||||
if(Toxins_partialpressure > safe_tox_max)
|
||||
var/ratio = (breath_gases[/datum/gas/plasma]/safe_tox_max) * 10
|
||||
var/ratio = (breath.get_moles(/datum/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_gases[/datum/gas/nitrous_oxide])
|
||||
var/SA_partialpressure = (breath_gases[/datum/gas/nitrous_oxide]/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(/datum/gas/nitrous_oxide))
|
||||
var/SA_partialpressure = (breath.get_moles(/datum/gas/nitrous_oxide)/breath.total_moles())*breath_pressure
|
||||
if(SA_partialpressure > SA_para_min)
|
||||
Unconscious(60)
|
||||
if(SA_partialpressure > SA_sleep_min)
|
||||
@@ -248,26 +247,26 @@
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria")
|
||||
|
||||
//BZ (Facepunch port of their Agent B)
|
||||
if(breath_gases[/datum/gas/bz])
|
||||
var/bz_partialpressure = (breath_gases[/datum/gas/bz]/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(/datum/gas/bz))
|
||||
var/bz_partialpressure = (breath.get_moles(/datum/gas/bz)/breath.total_moles())*breath_pressure
|
||||
if(bz_partialpressure > 1)
|
||||
hallucination += 10
|
||||
else if(bz_partialpressure > 0.01)
|
||||
hallucination += 5
|
||||
|
||||
//TRITIUM
|
||||
if(breath_gases[/datum/gas/tritium])
|
||||
var/tritium_partialpressure = (breath_gases[/datum/gas/tritium]/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(/datum/gas/tritium))
|
||||
var/tritium_partialpressure = (breath.get_moles(/datum/gas/tritium)/breath.total_moles())*breath_pressure
|
||||
radiation += tritium_partialpressure/10
|
||||
|
||||
//NITRYL
|
||||
if(breath_gases[/datum/gas/nitryl])
|
||||
var/nitryl_partialpressure = (breath_gases[/datum/gas/nitryl]/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(/datum/gas/nitryl))
|
||||
var/nitryl_partialpressure = (breath.get_moles(/datum/gas/nitryl)/breath.total_moles())*breath_pressure
|
||||
adjustFireLoss(nitryl_partialpressure/4)
|
||||
|
||||
//MIASMA
|
||||
if(breath_gases[/datum/gas/miasma])
|
||||
var/miasma_partialpressure = (breath_gases[/datum/gas/miasma]/breath.total_moles())*breath_pressure
|
||||
if(breath.get_moles(/datum/gas/miasma))
|
||||
var/miasma_partialpressure = (breath.get_moles(/datum/gas/miasma)/breath.total_moles())*breath_pressure
|
||||
if(miasma_partialpressure > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
|
||||
if(prob(0.05 * miasma_partialpressure))
|
||||
@@ -307,11 +306,6 @@
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
|
||||
|
||||
|
||||
|
||||
GAS_GARBAGE_COLLECT(breath.gases)
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
@@ -370,9 +364,9 @@
|
||||
|
||||
var/datum/gas_mixture/stank = new
|
||||
|
||||
stank.gases[/datum/gas/miasma] = 0.1
|
||||
stank.set_moles(/datum/gas/miasma,0.1)
|
||||
|
||||
stank.temperature = BODYTEMP_NORMAL
|
||||
stank.set_temperature(BODYTEMP_NORMAL)
|
||||
|
||||
miasma_turf.assume_air(stank)
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
|
||||
if(abs(BODYTEMP_NORMAL - breath.temperature) > 50)
|
||||
switch(breath.temperature)
|
||||
if(abs(BODYTEMP_NORMAL - breath.return_temperature()) > 50)
|
||||
switch(breath.return_temperature())
|
||||
if(-INFINITY to 120)
|
||||
adjustFireLoss(3)
|
||||
if(120 to 200)
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
ExtinguishMob()
|
||||
return
|
||||
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
|
||||
if(G.gases[/datum/gas/oxygen] < 1)
|
||||
if(G.get_moles(/datum/gas/oxygen, 1))
|
||||
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
|
||||
return
|
||||
var/turf/location = get_turf(src)
|
||||
|
||||
@@ -914,7 +914,7 @@
|
||||
floating_need_update = TRUE
|
||||
|
||||
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
|
||||
var/loc_temp = environment ? environment.temperature : T0C
|
||||
var/loc_temp = environment ? environment.return_temperature() : T0C
|
||||
if(isobj(loc))
|
||||
var/obj/oloc = loc
|
||||
var/obj_temp = oloc.return_temperature()
|
||||
|
||||
@@ -88,11 +88,22 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
|
||||
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
|
||||
|
||||
var/ic_blocked = FALSE
|
||||
/*
|
||||
if(client && !forced && config.ic_filter_regex && findtext(message, config.ic_filter_regex))
|
||||
//The filter doesn't act on the sanitized message, but the raw message.
|
||||
ic_blocked = TRUE
|
||||
*/
|
||||
if(sanitize)
|
||||
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
if(!message || message == "")
|
||||
return
|
||||
|
||||
if(ic_blocked)
|
||||
//The filter warning message shows the sanitized message though.
|
||||
to_chat(src, "<span class='warning'>That message contained a word prohibited in IC chat! Consider reviewing the server rules.\n<span replaceRegex='show_filtered_ic_chat'>\"[message]\"</span></span>")
|
||||
return
|
||||
|
||||
var/datum/saymode/saymode = SSradio.saymodes[talk_key]
|
||||
var/message_mode = get_message_mode(message)
|
||||
var/original_message = message
|
||||
|
||||
@@ -565,7 +565,6 @@
|
||||
dat += "Unable to obtain a reading.<br>"
|
||||
else
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/list/env_gases = environment.gases
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles()
|
||||
@@ -573,11 +572,11 @@
|
||||
dat += "Air Pressure: [round(pressure,0.1)] kPa<br>"
|
||||
|
||||
if (total_moles)
|
||||
for(var/id in env_gases)
|
||||
var/gas_level = env_gases[id]/total_moles
|
||||
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 += "Temperature: [round(environment.temperature-T0C)]°C<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>"
|
||||
return dat
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
desc = "Known for its wisdom, shares it with all"
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/wisdomcow = 1) //truly the best meat
|
||||
gold_core_spawnable = FALSE
|
||||
speak_chance = 30 //the cow is eager to share its wisdom!
|
||||
speak_chance = 10 //the cow is eager to share its wisdom! //but is wise enough to not lag the server too bad
|
||||
milk_reagent = /datum/reagent/medicine/liquid_wisdom
|
||||
|
||||
/mob/living/simple_animal/cow/wisdom/Initialize()
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
return
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/T = src.loc
|
||||
if(T.air && T.air.gases[/datum/gas/carbon_dioxide])
|
||||
var/co2 = T.air.gases[/datum/gas/carbon_dioxide]
|
||||
if(T.air)
|
||||
var/co2 = T.air.get_moles(/datum/gas/carbon_dioxide)
|
||||
if(co2 > 0)
|
||||
if(prob(25))
|
||||
var/amt = min(co2, 9)
|
||||
T.air.gases[/datum/gas/carbon_dioxide] -= amt
|
||||
T.air.adjust_moles(/datum/gas/carbon_dioxide, -amt)
|
||||
T.atmos_spawn_air("o2=[amt]")
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/AttackingTarget()
|
||||
|
||||
@@ -252,14 +252,11 @@
|
||||
if(isturf(src.loc) && isopenturf(src.loc))
|
||||
var/turf/open/ST = src.loc
|
||||
if(ST.air)
|
||||
var/ST_gases = ST.air.gases
|
||||
|
||||
var/tox = ST_gases[/datum/gas/plasma]
|
||||
var/oxy = ST_gases[/datum/gas/oxygen]
|
||||
var/n2 = ST_gases[/datum/gas/nitrogen]
|
||||
var/co2 = ST_gases[/datum/gas/carbon_dioxide]
|
||||
|
||||
GAS_GARBAGE_COLLECT(ST.air.gases)
|
||||
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)
|
||||
|
||||
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
|
||||
. = FALSE
|
||||
|
||||
@@ -128,9 +128,7 @@
|
||||
Tempstun = 0
|
||||
|
||||
if(stat != DEAD)
|
||||
var/bz_percentage =0
|
||||
if(environment.gases[/datum/gas/bz])
|
||||
bz_percentage = environment.gases[/datum/gas/bz] / environment.total_moles()
|
||||
var/bz_percentage = environment.total_moles() ? (environment.get_moles(/datum/gas/bz) / environment.total_moles()) : 0
|
||||
var/stasis = (bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) || force_stasis
|
||||
|
||||
if(stat == CONSCIOUS && stasis)
|
||||
|
||||
+64
-14
@@ -66,11 +66,10 @@
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
var/t = "<span class='notice'>Coordinates: [x],[y] \n</span>"
|
||||
t += "<span class='danger'>Temperature: [environment.temperature] \n</span>"
|
||||
for(var/id in environment.gases)
|
||||
var/gas = environment.gases[id]
|
||||
if(gas)
|
||||
t+="<span class='notice'>[GLOB.meta_gas_names[id]]: [gas] \n</span>"
|
||||
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>"
|
||||
|
||||
to_chat(usr, t)
|
||||
|
||||
@@ -288,8 +287,14 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
|
||||
. = view(dist, src)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_FOV_VIEW, .)
|
||||
|
||||
//mob verbs are faster than object verbs. See https://secure.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine()
|
||||
/mob/verb/examinate(atom/A as mob|obj|turf in fov_view()) //It used to be oview(12), but I can't really say why
|
||||
/**
|
||||
* Examine a mob
|
||||
*
|
||||
* mob verbs are faster than object verbs. See
|
||||
* [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716)
|
||||
* for why this isn't atom/verb/examine()
|
||||
*/
|
||||
/mob/verb/examinate(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why
|
||||
set name = "Examine"
|
||||
set category = "IC"
|
||||
|
||||
@@ -297,18 +302,63 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
|
||||
// shift-click catcher may issue examinate() calls for out-of-sight turfs
|
||||
return
|
||||
|
||||
if(is_blind(src))
|
||||
if(is_blind())
|
||||
to_chat(src, "<span class='warning'>Something is there but you can't see it!</span>")
|
||||
return
|
||||
|
||||
face_atom(A)
|
||||
var/flags = SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
|
||||
if(flags & COMPONENT_DENY_EXAMINATE)
|
||||
if(flags & COMPONENT_EXAMINATE_BLIND)
|
||||
to_chat(src, "<span class='warning'>Something is there but you can't see it!</span>")
|
||||
return
|
||||
var/list/result = A.examine(src)
|
||||
var/list/result
|
||||
if(client)
|
||||
LAZYINITLIST(client.recent_examines)
|
||||
if(isnull(client.recent_examines[A]) || client.recent_examines[A] < world.time)
|
||||
result = A.examine(src)
|
||||
client.recent_examines[A] = world.time + EXAMINE_MORE_TIME // set the value to when the examine cooldown ends
|
||||
RegisterSignal(A, COMSIG_PARENT_QDELETING, .proc/clear_from_recent_examines, override=TRUE) // to flush the value if deleted early
|
||||
addtimer(CALLBACK(src, .proc/clear_from_recent_examines, A), EXAMINE_MORE_TIME)
|
||||
handle_eye_contact(A)
|
||||
else
|
||||
result = A.examine_more(src)
|
||||
else
|
||||
result = A.examine(src) // if a tree is examined but no client is there to see it, did the tree ever really exist?
|
||||
|
||||
to_chat(src, result.Join("\n"))
|
||||
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
|
||||
|
||||
/mob/proc/clear_from_recent_examines(atom/A)
|
||||
if(!client)
|
||||
return
|
||||
UnregisterSignal(A, COMSIG_PARENT_QDELETING)
|
||||
LAZYREMOVE(client.recent_examines, A)
|
||||
|
||||
/**
|
||||
* handle_eye_contact() is called when we examine() something. If we examine an alive mob with a mind who has examined us in the last second within 5 tiles, we make eye contact!
|
||||
*
|
||||
* Note that if either party has their face obscured, the other won't get the notice about the eye contact
|
||||
* Also note that examine_more() doesn't proc this or extend the timer, just because it's simpler this way and doesn't lose much.
|
||||
* The nice part about relying on examining is that we don't bother checking visibility, because we already know they were both visible to each other within the last second, and the one who triggers it is currently seeing them
|
||||
*/
|
||||
/mob/proc/handle_eye_contact(mob/living/examined_mob)
|
||||
return
|
||||
|
||||
/mob/living/handle_eye_contact(mob/living/examined_mob)
|
||||
if(!istype(examined_mob) || src == examined_mob || examined_mob.stat >= UNCONSCIOUS || !client || !examined_mob.client?.recent_examines || !(src in examined_mob.client.recent_examines))
|
||||
return
|
||||
|
||||
if(get_dist(src, examined_mob) > EYE_CONTACT_RANGE)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/examined_carbon = examined_mob
|
||||
// check to see if their face is blocked (or if they're not a carbon, in which case they can't block their face anyway)
|
||||
if(!istype(examined_carbon) || (!(examined_carbon.wear_mask && examined_carbon.wear_mask.flags_inv & HIDEFACE) && !(examined_carbon.head && examined_carbon.head.flags_inv & HIDEFACE)))
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_EYECONTACT, examined_mob, TRUE) != COMSIG_BLOCK_EYECONTACT)
|
||||
var/msg = "<span class='smallnotice'>You make eye contact with [examined_mob].</span>"
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, src, msg), 3) // so the examine signal has time to fire and this will print after
|
||||
|
||||
var/mob/living/carbon/us_as_carbon = src // i know >casting as subtype, but this isn't really an inheritable check
|
||||
if(!istype(us_as_carbon) || (!(us_as_carbon.wear_mask && us_as_carbon.wear_mask.flags_inv & HIDEFACE) && !(us_as_carbon.head && us_as_carbon.head.flags_inv & HIDEFACE)))
|
||||
if(SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT)
|
||||
var/msg = "<span class='smallnotice'>[src] makes eye contact with you.</span>"
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, examined_mob, msg), 3)
|
||||
|
||||
//same as above
|
||||
//note: ghosts can point, this is intended
|
||||
|
||||
@@ -50,12 +50,16 @@
|
||||
usr.emote("me",1,message,TRUE)
|
||||
|
||||
/mob/say_mod(input, message_mode)
|
||||
if(message_mode == MODE_WHISPER_CRIT)
|
||||
return ..()
|
||||
if((input[1] == "!") && (length_char(input) > 1))
|
||||
message_mode = MODE_CUSTOM_SAY
|
||||
return copytext_char(input, 2)
|
||||
var/customsayverb = findtext(input, "*")
|
||||
if(customsayverb && message_mode != MODE_WHISPER_CRIT)
|
||||
if(customsayverb)
|
||||
message_mode = MODE_CUSTOM_SAY
|
||||
return lowertext(copytext_char(input, 1, customsayverb))
|
||||
else
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/proc/uncostumize_say(input, message_mode)
|
||||
. = input
|
||||
|
||||
@@ -72,20 +72,22 @@
|
||||
data["active"] = TRUE
|
||||
data["SM_integrity"] = active.get_integrity()
|
||||
data["SM_power"] = active.power
|
||||
data["SM_ambienttemp"] = air.temperature
|
||||
data["SM_ambienttemp"] = air.return_temperature()
|
||||
data["SM_ambientpressure"] = air.return_pressure()
|
||||
//data["SM_EPR"] = round((air.total_moles / air.group_multiplier) / 23.1, 0.01)
|
||||
var/list/gasdata = list()
|
||||
|
||||
|
||||
if(air.total_moles())
|
||||
for(var/gasid in air.gases)
|
||||
gasdata.Add(list(list(
|
||||
"name"= GLOB.meta_gas_names[gasid],
|
||||
"amount" = round(100*air.gases[gasid]/air.total_moles(),0.01))))
|
||||
for(var/gasid in air.get_gases())
|
||||
var/amount = air.get_moles(gasid)
|
||||
if(amount)
|
||||
gasdata.Add(list(list(
|
||||
"name"= GLOB.meta_gas_names[gasid],
|
||||
"amount" = round(100*amount/air.total_moles(),0.01))))
|
||||
|
||||
else
|
||||
for(var/gasid in air.gases)
|
||||
for(var/gasid in air.get_gases())
|
||||
gasdata.Add(list(list(
|
||||
"name"= GLOB.meta_gas_names[gasid],
|
||||
"amount" = 0)))
|
||||
|
||||
@@ -169,6 +169,12 @@
|
||||
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
|
||||
|
||||
|
||||
/obj/item/paper/examine_more(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/paper/proc/show_content(mob/user)
|
||||
user.examinate(src)
|
||||
|
||||
/obj/item/paper/verb/rename()
|
||||
set name = "Rename paper"
|
||||
set category = "Object"
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
var/cold_air_heat_capacity = cold_air.heat_capacity()
|
||||
var/hot_air_heat_capacity = hot_air.heat_capacity()
|
||||
|
||||
var/delta_temperature = hot_air.temperature - cold_air.temperature
|
||||
var/delta_temperature = hot_air.return_temperature() - cold_air.return_temperature()
|
||||
|
||||
|
||||
if(delta_temperature > 0 && cold_air_heat_capacity > 0 && hot_air_heat_capacity > 0)
|
||||
@@ -68,8 +68,8 @@
|
||||
var/heat = energy_transfer*(1-efficiency)
|
||||
lastgen += energy_transfer*efficiency
|
||||
|
||||
hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity
|
||||
cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity
|
||||
hot_air.set_temperature(hot_air.return_temperature() - energy_transfer/hot_air_heat_capacity)
|
||||
cold_air.set_temperature(cold_air.return_temperature() + heat/cold_air_heat_capacity)
|
||||
|
||||
//add_avail(lastgen) This is done in process now
|
||||
// update icon overlays only if displayed level has changed
|
||||
@@ -116,11 +116,11 @@
|
||||
t += "<BR>"
|
||||
|
||||
t += "<B><font color='blue'>Cold loop</font></B><BR>"
|
||||
t += "Temperature Inlet: [round(cold_circ_air2.temperature, 0.1)] K / Outlet: [round(cold_circ_air1.temperature, 0.1)] K<BR>"
|
||||
t += "Temperature Inlet: [round(cold_circ_air2.return_temperature(), 0.1)] K / Outlet: [round(cold_circ_air1.return_temperature(), 0.1)] K<BR>"
|
||||
t += "Pressure Inlet: [round(cold_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(cold_circ_air1.return_pressure(), 0.1)] kPa<BR>"
|
||||
|
||||
t += "<B><font color='red'>Hot loop</font></B><BR>"
|
||||
t += "Temperature Inlet: [round(hot_circ_air2.temperature, 0.1)] K / Outlet: [round(hot_circ_air1.temperature, 0.1)] K<BR>"
|
||||
t += "Temperature Inlet: [round(hot_circ_air2.return_temperature(), 0.1)] K / Outlet: [round(hot_circ_air1.return_temperature(), 0.1)] K<BR>"
|
||||
t += "Pressure Inlet: [round(hot_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(hot_circ_air1.return_pressure(), 0.1)] kPa<BR>"
|
||||
|
||||
t += "</div>"
|
||||
|
||||
@@ -47,31 +47,29 @@
|
||||
if(!loaded_tank)
|
||||
return
|
||||
if(!bitcoinmining)
|
||||
if(!loaded_tank.air_contents.gases[/datum/gas/plasma])
|
||||
if(loaded_tank.air_contents.get_moles(/datum/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.gases[/datum/gas/plasma])
|
||||
loaded_tank.air_contents.gases[/datum/gas/plasma] -= 2.7 * gasdrained
|
||||
loaded_tank.air_contents.gases[/datum/gas/tritium] += 2.7 * gasdrained
|
||||
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
|
||||
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/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.gases[/datum/gas/tritium] || !loaded_tank.air_contents.gases[/datum/gas/oxygen])
|
||||
if(!loaded_tank.air_contents.get_moles(/datum/gas/tritium) || !loaded_tank.air_contents.get_moles(/datum/gas/oxygen))
|
||||
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.gases[/datum/gas/tritium] -= gasdrained
|
||||
loaded_tank.air_contents.gases[/datum/gas/oxygen] -= gasdrained
|
||||
loaded_tank.air_contents.gases[/datum/gas/carbon_dioxide] += gasdrained*2
|
||||
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
|
||||
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)
|
||||
var/bitcoins_mined = stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG)
|
||||
if(D)
|
||||
@@ -86,9 +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
|
||||
if(loaded_tank)
|
||||
fuel = loaded_tank.air_contents.gases[/datum/gas/plasma]
|
||||
var/fuel = loaded_tank.air_contents.get_moles(/datum/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
|
||||
|
||||
@@ -211,10 +211,10 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
if(get_integrity() < SUPERMATTER_DANGER_PERCENT)
|
||||
return SUPERMATTER_DANGER
|
||||
|
||||
if((get_integrity() < SUPERMATTER_WARNING_PERCENT) || (air.temperature > CRITICAL_TEMPERATURE))
|
||||
if((get_integrity() < SUPERMATTER_WARNING_PERCENT) || (air.return_temperature() > CRITICAL_TEMPERATURE))
|
||||
return SUPERMATTER_WARNING
|
||||
|
||||
if(air.temperature > (CRITICAL_TEMPERATURE * 0.8))
|
||||
if(air.return_temperature() > (CRITICAL_TEMPERATURE * 0.8))
|
||||
return SUPERMATTER_NOTIFY
|
||||
|
||||
if(power > 5)
|
||||
@@ -342,13 +342,13 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
else
|
||||
if(takes_damage)
|
||||
//causing damage
|
||||
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.return_temperature() - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
damage = max(damage + (max(combined_gas - MOLE_PENALTY_THRESHOLD, 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
|
||||
//healing damage
|
||||
if(combined_gas < MOLE_PENALTY_THRESHOLD)
|
||||
damage = max(damage + (min(removed.temperature - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ), 0)
|
||||
damage = max(damage + (min(removed.return_temperature() - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ), 0)
|
||||
|
||||
//capping damage
|
||||
damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage)
|
||||
@@ -358,15 +358,15 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
//calculating gas related values
|
||||
combined_gas = max(removed.total_moles(), 0)
|
||||
|
||||
plasmacomp = max(removed.gases[/datum/gas/plasma]/combined_gas, 0)
|
||||
o2comp = max(removed.gases[/datum/gas/oxygen]/combined_gas, 0)
|
||||
co2comp = max(removed.gases[/datum/gas/carbon_dioxide]/combined_gas, 0)
|
||||
pluoxiumcomp = max(removed.gases[/datum/gas/pluoxium]/combined_gas, 0)
|
||||
tritiumcomp = max(removed.gases[/datum/gas/tritium]/combined_gas, 0)
|
||||
bzcomp = max(removed.gases[/datum/gas/bz]/combined_gas, 0)
|
||||
plasmacomp = max(removed.get_moles(/datum/gas/plasma)/combined_gas, 0)
|
||||
o2comp = max(removed.get_moles(/datum/gas/oxygen)/combined_gas, 0)
|
||||
co2comp = max(removed.get_moles(/datum/gas/carbon_dioxide)/combined_gas, 0)
|
||||
tritiumcomp = max(removed.get_moles(/datum/gas/tritium)/combined_gas, 0)
|
||||
bzcomp = max(removed.get_moles(/datum/gas/bz)/combined_gas, 0)
|
||||
|
||||
n2ocomp = max(removed.gases[/datum/gas/nitrous_oxide]/combined_gas, 0)
|
||||
n2comp = max(removed.gases[/datum/gas/nitrogen]/combined_gas, 0)
|
||||
pluoxiumcomp = max(removed.get_moles(/datum/gas/pluoxium)/combined_gas, 0)
|
||||
n2ocomp = max(removed.get_moles(/datum/gas/nitrous_oxide)/combined_gas, 0)
|
||||
n2comp = max(removed.get_moles(/datum/gas/nitrogen)/combined_gas, 0)
|
||||
|
||||
if(pluoxiumcomp >= 0.15)
|
||||
pluoxiumbonus = 1 //makes pluoxium only work at 15%+
|
||||
@@ -404,7 +404,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
temp_factor = 30
|
||||
icon_state = base_icon_state
|
||||
|
||||
power = max( (removed.temperature * temp_factor / T0C) * gasmix_power_ratio + power, 0) //Total laser power plus an overload
|
||||
power = max( (removed.return_temperature() * temp_factor / T0C) * gasmix_power_ratio + power, 0) //Total laser power plus an overload
|
||||
|
||||
if(prob(50))
|
||||
radiation_pulse(src, power * (1 + (tritiumcomp * TRITIUM_RADIOACTIVITY_MODIFIER) + ((pluoxiumcomp * PLUOXIUM_RADIOACTIVITY_MODIFIER) * pluoxiumbonus) * (power_transmission_bonus/(10-(bzcomp * BZ_RADIOACTIVITY_MODIFIER))))) // Rad Modifiers BZ(500%), Tritium(300%), and Pluoxium(-200%)
|
||||
@@ -420,14 +420,14 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
|
||||
//Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock
|
||||
//is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall.
|
||||
removed.temperature += ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER)
|
||||
removed.set_temperature(removed.return_temperature() + ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER))
|
||||
|
||||
removed.temperature = max(0, min(removed.temperature, 2500 * dynamic_heat_modifier))
|
||||
removed.set_temperature(max(0, min(removed.return_temperature(), 2500 * dynamic_heat_modifier)))
|
||||
|
||||
//Calculate how much gas to release
|
||||
removed.gases[/datum/gas/plasma] += max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)
|
||||
removed.adjust_moles(/datum/gas/plasma, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0))
|
||||
|
||||
removed.gases[/datum/gas/oxygen] += max(((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)
|
||||
removed.adjust_moles(/datum/gas/oxygen, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0))
|
||||
|
||||
if(produces_gas)
|
||||
env.merge(removed)
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
|
||||
// Weird function but it works. Should be something else...
|
||||
|
||||
var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4
|
||||
var/newrpm = ((compressor.gas_contained.return_temperature()) * compressor.gas_contained.total_moles())/4
|
||||
|
||||
newrpm = max(0, newrpm)
|
||||
|
||||
@@ -329,7 +329,8 @@
|
||||
data["online"] = compressor?.starter
|
||||
data["power"] = DisplayPower(compressor?.turbine?.lastgen)
|
||||
data["rpm"] = compressor?.rpm
|
||||
data["temp"] = compressor?.gas_contained.temperature
|
||||
data["temp"] = compressor?.gas_contained.return_temperature()
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/turbine_computer/ui_act(action, params)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
if(T.air)
|
||||
if(T.initial_gas_mix)
|
||||
T.air.parse_gas_string(T.initial_gas_mix)
|
||||
T.temperature = T.air.temperature
|
||||
T.temperature = T.air.return_temperature()
|
||||
else
|
||||
T.air.copy_from_turf(T)
|
||||
SSair.add_to_active(T)
|
||||
|
||||
@@ -271,7 +271,7 @@
|
||||
if(isopenturf(T))
|
||||
var/turf/open/OT = T
|
||||
OT.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure.
|
||||
OT.air.temperature -= MOLES_CELLSTANDARD*100*reac_volume/OT.air.heat_capacity() // reduces environment temperature by 5K per unit.
|
||||
OT.air.set_temperature(OT.air.return_temperature() - MOLES_CELLSTANDARD*100*reac_volume/OT.air.heat_capacity()) // reduces environment temperature by 5K per unit.
|
||||
|
||||
/datum/reagent/consumable/condensedcapsaicin
|
||||
name = "Condensed Capsaicin"
|
||||
@@ -506,7 +506,7 @@
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
|
||||
if(hotspot)
|
||||
var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles())
|
||||
lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0)
|
||||
lowertemp.set_temperature(max( min(lowertemp.return_temperature()-2000,lowertemp.return_temperature() / 2) ,0))
|
||||
lowertemp.react(src)
|
||||
T.assume_air(lowertemp)
|
||||
qdel(hotspot)
|
||||
|
||||
@@ -928,10 +928,18 @@
|
||||
M.adjustOxyLoss(-20, 0)
|
||||
M.adjustToxLoss(-20, 0)
|
||||
M.updatehealth()
|
||||
var/tplus = world.time - M.timeofdeath
|
||||
if(M.revive())
|
||||
M.grab_ghost()
|
||||
M.emote("gasp")
|
||||
log_combat(M, M, "revived", src)
|
||||
var/list/policies = CONFIG_GET(keyed_list/policyconfig)
|
||||
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit)
|
||||
var/late = timelimit && (tplus > timelimit)
|
||||
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
|
||||
if(policy)
|
||||
to_chat(M, policy)
|
||||
M.log_message("revived using strange reagent, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME)
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
if(hotspot && !isspaceturf(T))
|
||||
if(T.air)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
G.temperature = max(min(G.temperature-(CT*1000),G.temperature/CT),TCMB)
|
||||
G.set_temperature(max(min(G.return_temperature()-(CT*1000),G.return_temperature()/CT),TCMB))
|
||||
G.react(src)
|
||||
qdel(hotspot)
|
||||
var/obj/effect/acid/A = (locate(/obj/effect/acid) in T)
|
||||
@@ -1154,6 +1154,13 @@
|
||||
/mob/living/proc/bluespace_shuffle()
|
||||
do_teleport(src, get_turf(src), 5, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
|
||||
/datum/reagent/telecrystal
|
||||
name = "Telecrystal Dust"
|
||||
description = "A blood-red dust comprised of something that was much more useful when it was intact."
|
||||
reagent_state = SOLID
|
||||
color = "#660000" // rgb: 102, 0, 0.
|
||||
taste_description = "contraband"
|
||||
|
||||
/datum/reagent/aluminium
|
||||
name = "Aluminium"
|
||||
description = "A silvery white and ductile member of the boron group of chemical elements."
|
||||
|
||||
@@ -281,8 +281,8 @@
|
||||
if(hotspot && !isspaceturf(T))
|
||||
if(T.air)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(G.temperature > T20C)
|
||||
G.temperature = max(G.temperature/2,T20C)
|
||||
if(G.return_temperature() > T20C)
|
||||
G.set_temperature(max(G.return_temperature()/2,T20C))
|
||||
G.react(src)
|
||||
qdel(hotspot)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
trunk_check()
|
||||
|
||||
air_contents = new /datum/gas_mixture()
|
||||
//gas.volume = 1.05 * CELLSTANDARD
|
||||
//air_contents.set_volume(1.05 * CELLSTANDARD)
|
||||
update_icon()
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD //we need turfs to have air
|
||||
@@ -443,8 +443,8 @@
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure()
|
||||
|
||||
if(env.temperature > 0)
|
||||
var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION)
|
||||
if(env.return_temperature() > 0)
|
||||
var/transfer_moles = 0.1 * pressure_delta*air_contents.return_volume()/(env.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = env.remove(transfer_moles)
|
||||
|
||||
@@ -368,7 +368,7 @@
|
||||
var/heat_capacity = removed.heat_capacity()
|
||||
if(heat_capacity == 0 || heat_capacity == null)
|
||||
heat_capacity = 1
|
||||
removed.temperature = min((removed.temperature*heat_capacity + 100000)/heat_capacity, 1000)
|
||||
removed.set_temperature(min((removed.return_temperature()*heat_capacity + 100000)/heat_capacity, 1000))
|
||||
env.merge(removed)
|
||||
air_update_turf()
|
||||
investigate_log("Experimentor has released hot air.", INVESTIGATE_EXPERIMENTOR)
|
||||
@@ -414,7 +414,7 @@
|
||||
var/heat_capacity = removed.heat_capacity()
|
||||
if(heat_capacity == 0 || heat_capacity == null)
|
||||
heat_capacity = 1
|
||||
removed.temperature = (removed.temperature*heat_capacity - 75000)/heat_capacity
|
||||
removed.set_temperature((removed.return_temperature()*heat_capacity - 75000)/heat_capacity)
|
||||
env.merge(removed)
|
||||
air_update_turf()
|
||||
investigate_log("Experimentor has released cold air.", INVESTIGATE_EXPERIMENTOR)
|
||||
|
||||
@@ -59,14 +59,14 @@
|
||||
|
||||
/obj/machinery/rnd/server/proc/get_env_temp()
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
return environment.temperature
|
||||
return environment.return_temperature()
|
||||
|
||||
/obj/machinery/rnd/server/proc/produce_heat(heat_amt)
|
||||
if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater.
|
||||
var/turf/L = loc
|
||||
if(istype(L))
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
if(env.temperature < (heat_amt+T0C))
|
||||
if(env.return_temperature() < (heat_amt+T0C))
|
||||
|
||||
var/transfer_moles = 0.25 * env.total_moles()
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
var/heat_capacity = removed.heat_capacity()
|
||||
if(heat_capacity == 0 || heat_capacity == null)
|
||||
heat_capacity = 1
|
||||
removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000)
|
||||
removed.set_temperature(min((removed.return_temperature()*heat_capacity + heating_power)/heat_capacity, 1000))
|
||||
|
||||
env.merge(removed)
|
||||
air_update_turf()
|
||||
|
||||
@@ -100,9 +100,8 @@ Chilling extracts:
|
||||
for(var/turf/open/T in A)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(istype(G))
|
||||
G.gases[/datum/gas/plasma] = 0
|
||||
G.set_moles(/datum/gas/plasma, 0)
|
||||
filtered = TRUE
|
||||
GAS_GARBAGE_COLLECT(G.gases)
|
||||
T.air_update_turf()
|
||||
if(filtered)
|
||||
user.visible_message("<span class='notice'>Cracks spread throughout [src], and some air is sucked in!</span>")
|
||||
@@ -308,4 +307,4 @@ Chilling extracts:
|
||||
user.visible_message("<span class='warning'>[src] reflects an array of dazzling colors and light, energy rushing to nearby doors!</span>")
|
||||
for(var/obj/machinery/door/airlock/door in area)
|
||||
new /obj/effect/forcefield/slimewall/rainbow(door.loc)
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1)
|
||||
target.adjustOxyLoss(-50, 0)
|
||||
target.updatehealth()
|
||||
var/tplus = world.time - target.timeofdeath
|
||||
if(target.revive())
|
||||
user.visible_message("...[target] wakes up, alive and aware!", "<span class='notice'><b>IT'S ALIVE!</b></span>")
|
||||
target.visible_message("...[target] wakes up, alive and aware!")
|
||||
@@ -68,6 +69,13 @@
|
||||
for(var/obj/item/organ/O in target.internal_organs)//zap those buggers back to life!
|
||||
if(O.organ_flags & ORGAN_FAILING)
|
||||
O.applyOrganDamage(-5)
|
||||
var/list/policies = CONFIG_GET(keyed_list/policyconfig)
|
||||
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit)
|
||||
var/late = timelimit && (tplus > timelimit)
|
||||
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
|
||||
if(policy)
|
||||
to_chat(target, policy)
|
||||
target.log_message("revived using surgical revival, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME)
|
||||
return TRUE
|
||||
else
|
||||
user.visible_message("...[target.p_they()] convulses, then lies still.")
|
||||
|
||||
@@ -133,13 +133,11 @@
|
||||
|
||||
var/gas_breathed = 0
|
||||
|
||||
var/list/breath_gases = breath.gases
|
||||
|
||||
//Partial pressures in our breath
|
||||
var/O2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen])+(8*breath.get_breath_partial_pressure(breath_gases[/datum/gas/pluoxium]))
|
||||
var/N2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrogen])
|
||||
var/Toxins_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma])
|
||||
var/CO2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide])
|
||||
var/O2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/oxygen))+(8*breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/pluoxium)))
|
||||
var/N2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrogen))
|
||||
var/Toxins_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma))
|
||||
var/CO2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/carbon_dioxide))
|
||||
|
||||
|
||||
//-- OXY --//
|
||||
@@ -147,7 +145,7 @@
|
||||
//Too much oxygen! //Yes, some species may not like it.
|
||||
if(safe_oxygen_max)
|
||||
if((O2_pp > safe_oxygen_max) && safe_oxygen_max == 0) //I guess plasma men technically need to have a check.
|
||||
var/ratio = (breath_gases[/datum/gas/oxygen]/safe_oxygen_max) * 10
|
||||
var/ratio = (breath.get_moles(/datum/gas/oxygen)/safe_oxygen_max) * 10
|
||||
H.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type)
|
||||
H.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy)
|
||||
|
||||
@@ -170,18 +168,18 @@
|
||||
//Too little oxygen!
|
||||
if(safe_oxygen_min)
|
||||
if(O2_pp < safe_oxygen_min)
|
||||
gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen])
|
||||
gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath.get_moles(/datum/gas/oxygen))
|
||||
H.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
|
||||
else
|
||||
H.failed_last_breath = FALSE
|
||||
if(H.health >= H.crit_threshold)
|
||||
H.adjustOxyLoss(-breathModifier) //More damaged lungs = slower oxy rate up to a factor of half
|
||||
gas_breathed = breath_gases[/datum/gas/oxygen]
|
||||
gas_breathed = breath.get_moles(/datum/gas/oxygen)
|
||||
H.clear_alert("not_enough_oxy")
|
||||
|
||||
//Exhale
|
||||
breath_gases[/datum/gas/oxygen] -= gas_breathed
|
||||
breath_gases[/datum/gas/carbon_dioxide] += gas_breathed
|
||||
breath.adjust_moles(/datum/gas/oxygen, -gas_breathed)
|
||||
breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed)
|
||||
gas_breathed = 0
|
||||
|
||||
//-- Nitrogen --//
|
||||
@@ -189,7 +187,7 @@
|
||||
//Too much nitrogen!
|
||||
if(safe_nitro_max)
|
||||
if(N2_pp > safe_nitro_max)
|
||||
var/ratio = (breath_gases[/datum/gas/nitrogen]/safe_nitro_max) * 10
|
||||
var/ratio = (breath.get_moles(/datum/gas/nitrogen)/safe_nitro_max) * 10
|
||||
H.apply_damage_type(clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type)
|
||||
H.throw_alert("too_much_nitro", /obj/screen/alert/too_much_nitro)
|
||||
H.losebreath += 2
|
||||
@@ -199,18 +197,18 @@
|
||||
//Too little nitrogen!
|
||||
if(safe_nitro_min)
|
||||
if(N2_pp < safe_nitro_min)
|
||||
gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath_gases[/datum/gas/nitrogen])
|
||||
gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.get_moles(/datum/gas/nitrogen))
|
||||
H.throw_alert("nitro", /obj/screen/alert/not_enough_nitro)
|
||||
else
|
||||
H.failed_last_breath = FALSE
|
||||
if(H.health >= H.crit_threshold)
|
||||
H.adjustOxyLoss(-breathModifier)
|
||||
gas_breathed = breath_gases[/datum/gas/nitrogen]
|
||||
gas_breathed = breath.get_moles(/datum/gas/nitrogen)
|
||||
H.clear_alert("nitro")
|
||||
|
||||
//Exhale
|
||||
breath_gases[/datum/gas/nitrogen] -= gas_breathed
|
||||
breath_gases[/datum/gas/carbon_dioxide] += gas_breathed
|
||||
breath.adjust_moles(/datum/gas/nitrogen, -gas_breathed)
|
||||
breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed)
|
||||
gas_breathed = 0
|
||||
|
||||
//-- CO2 --//
|
||||
@@ -236,18 +234,18 @@
|
||||
//Too little CO2!
|
||||
if(safe_co2_min)
|
||||
if(CO2_pp < safe_co2_min)
|
||||
gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath_gases[/datum/gas/carbon_dioxide])
|
||||
gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath.get_moles(/datum/gas/carbon_dioxide))
|
||||
H.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2)
|
||||
else
|
||||
H.failed_last_breath = FALSE
|
||||
if(H.health >= H.crit_threshold)
|
||||
H.adjustOxyLoss(-breathModifier)
|
||||
gas_breathed = breath_gases[/datum/gas/carbon_dioxide]
|
||||
gas_breathed = breath.get_moles(/datum/gas/carbon_dioxide)
|
||||
H.clear_alert("not_enough_co2")
|
||||
|
||||
//Exhale
|
||||
breath_gases[/datum/gas/carbon_dioxide] -= gas_breathed
|
||||
breath_gases[/datum/gas/oxygen] += gas_breathed
|
||||
breath.adjust_moles(/datum/gas/carbon_dioxide, -gas_breathed)
|
||||
breath.adjust_moles(/datum/gas/oxygen, gas_breathed)
|
||||
gas_breathed = 0
|
||||
|
||||
|
||||
@@ -256,7 +254,7 @@
|
||||
//Too much toxins!
|
||||
if(safe_toxins_max)
|
||||
if(Toxins_pp > safe_toxins_max)
|
||||
var/ratio = (breath_gases[/datum/gas/plasma]/safe_toxins_max) * 10
|
||||
var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_toxins_max) * 10
|
||||
H.apply_damage_type(clamp(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type)
|
||||
H.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
|
||||
else
|
||||
@@ -266,18 +264,18 @@
|
||||
//Too little toxins!
|
||||
if(safe_toxins_min)
|
||||
if(Toxins_pp < safe_toxins_min)
|
||||
gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath_gases[/datum/gas/plasma])
|
||||
gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath.get_moles(/datum/gas/plasma))
|
||||
H.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox)
|
||||
else
|
||||
H.failed_last_breath = FALSE
|
||||
if(H.health >= H.crit_threshold)
|
||||
H.adjustOxyLoss(-breathModifier)
|
||||
gas_breathed = breath_gases[/datum/gas/plasma]
|
||||
gas_breathed = breath.get_moles(/datum/gas/plasma)
|
||||
H.clear_alert("not_enough_tox")
|
||||
|
||||
//Exhale
|
||||
breath_gases[/datum/gas/plasma] -= gas_breathed
|
||||
breath_gases[/datum/gas/carbon_dioxide] += gas_breathed
|
||||
breath.adjust_moles(/datum/gas/plasma, -gas_breathed)
|
||||
breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed)
|
||||
gas_breathed = 0
|
||||
|
||||
|
||||
@@ -287,7 +285,7 @@
|
||||
|
||||
// N2O
|
||||
|
||||
var/SA_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrous_oxide])
|
||||
var/SA_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrous_oxide))
|
||||
if(SA_pp > SA_para_min) // Enough to make us stunned for a bit
|
||||
H.Unconscious(60) // 60 gives them one second to wake up and run away a bit!
|
||||
if(SA_pp > SA_sleep_min) // Enough to make us sleep as well
|
||||
@@ -301,7 +299,7 @@
|
||||
|
||||
// BZ
|
||||
|
||||
var/bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz])
|
||||
var/bz_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/bz))
|
||||
if(bz_pp > BZ_trip_balls_min)
|
||||
H.hallucination += 10
|
||||
H.reagents.add_reagent(/datum/reagent/bz_metabolites,5)
|
||||
@@ -314,14 +312,14 @@
|
||||
|
||||
|
||||
// Tritium
|
||||
var/trit_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/tritium])
|
||||
var/trit_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/tritium))
|
||||
if (trit_pp > 50)
|
||||
H.radiation += trit_pp/2 //If you're breathing in half an atmosphere of radioactive gas, you fucked up.
|
||||
else
|
||||
H.radiation += trit_pp/10
|
||||
|
||||
// Nitryl
|
||||
var/nitryl_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitryl])
|
||||
var/nitryl_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitryl))
|
||||
if (prob(nitryl_pp))
|
||||
to_chat(H, "<span class='alert'>Your mouth feels like it's burning!</span>")
|
||||
if (nitryl_pp >40)
|
||||
@@ -332,22 +330,22 @@
|
||||
H.silent = max(H.silent, 3)
|
||||
else
|
||||
H.adjustFireLoss(nitryl_pp/4)
|
||||
gas_breathed = breath_gases[/datum/gas/nitryl]
|
||||
gas_breathed = breath.get_moles(/datum/gas/nitryl)
|
||||
if (gas_breathed > gas_stimulation_min)
|
||||
H.reagents.add_reagent(/datum/reagent/nitryl,1)
|
||||
|
||||
breath_gases[/datum/gas/nitryl]-=gas_breathed
|
||||
breath.adjust_moles(/datum/gas/nitryl, -gas_breathed)
|
||||
|
||||
// Stimulum
|
||||
gas_breathed = breath_gases[/datum/gas/stimulum]
|
||||
gas_breathed = breath.get_moles(/datum/gas/stimulum)
|
||||
if (gas_breathed > gas_stimulation_min)
|
||||
var/existing = H.reagents.get_reagent_amount(/datum/reagent/stimulum)
|
||||
H.reagents.add_reagent(/datum/reagent/stimulum, max(0, 5 - existing))
|
||||
breath_gases[/datum/gas/stimulum]-=gas_breathed
|
||||
breath.adjust_moles(/datum/gas/stimulum, -gas_breathed)
|
||||
|
||||
// Miasma
|
||||
if (breath_gases[/datum/gas/miasma])
|
||||
var/miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma])
|
||||
if (breath.get_moles(/datum/gas/miasma))
|
||||
var/miasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/miasma))
|
||||
if(miasma_pp > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
|
||||
//Miasma sickness
|
||||
@@ -387,14 +385,13 @@
|
||||
// Then again, this is a purely hypothetical scenario and hardly reachable
|
||||
owner.adjust_disgust(0.1 * miasma_pp)
|
||||
|
||||
breath_gases[/datum/gas/miasma]-=gas_breathed
|
||||
breath.adjust_moles(/datum/gas/miasma, -gas_breathed)
|
||||
|
||||
// Clear out moods when no miasma at all
|
||||
else
|
||||
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
|
||||
handle_breath_temperature(breath, H)
|
||||
GAS_GARBAGE_COLLECT(breath.gases)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -416,7 +413,7 @@
|
||||
|
||||
|
||||
/obj/item/organ/lungs/proc/handle_breath_temperature(datum/gas_mixture/breath, mob/living/carbon/human/H) // called by human/life, handles temperatures
|
||||
var/breath_temperature = breath.temperature
|
||||
var/breath_temperature = breath.return_temperature()
|
||||
|
||||
if(!HAS_TRAIT(H, TRAIT_RESISTCOLD)) // COLD DAMAGE
|
||||
var/cold_modifier = H.dna.species.coldmod
|
||||
@@ -533,8 +530,8 @@
|
||||
|
||||
/obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
if (breath && breath.gases[/datum/gas/plasma])
|
||||
var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma])
|
||||
if (breath)
|
||||
var/plasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma))
|
||||
owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you.
|
||||
|
||||
/obj/item/organ/lungs/yamerol
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
if(istype(loc, /turf/))//Only concern is adding an organ to a freezer when the area around it is cold.
|
||||
var/turf/T = loc
|
||||
var/datum/gas_mixture/enviro = T.return_air()
|
||||
local_temp = enviro.temperature
|
||||
local_temp = enviro.return_temperature()
|
||||
|
||||
else if(!owner && ismob(loc))
|
||||
var/mob/M = loc
|
||||
@@ -132,7 +132,7 @@
|
||||
return TRUE
|
||||
var/turf/T = M.loc
|
||||
var/datum/gas_mixture/enviro = T.return_air()
|
||||
local_temp = enviro.temperature
|
||||
local_temp = enviro.return_temperature()
|
||||
|
||||
if(owner)
|
||||
//Don't interfere with bodies frozen by structures.
|
||||
|
||||
Reference in New Issue
Block a user