Files
Paradise/code/LINDA/LINDA_turf_tile.dm
2018-10-08 22:48:00 +01:00

556 lines
16 KiB
Plaintext

/turf
var/pressure_difference = 0
var/pressure_direction = 0
var/atmos_adjacent_turfs = 0
var/atmos_adjacent_turfs_amount = 0
var/atmos_supeconductivity = 0
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
qdel(giver)
return 0
/turf/return_air()
//Create gas mixture to hold data for passing
var/datum/gas_mixture/GM = new
GM.oxygen = oxygen
GM.carbon_dioxide = carbon_dioxide
GM.nitrogen = nitrogen
GM.toxins = toxins
GM.temperature = temperature
return GM
/turf/remove_air(amount as num)
var/datum/gas_mixture/GM = new
var/sum = oxygen + carbon_dioxide + nitrogen + toxins
if(sum>0)
GM.oxygen = (oxygen/sum)*amount
GM.carbon_dioxide = (carbon_dioxide/sum)*amount
GM.nitrogen = (nitrogen/sum)*amount
GM.toxins = (toxins/sum)*amount
GM.temperature = temperature
return GM
/turf/simulated
var/datum/excited_group/excited_group
var/excited = 0
var/recently_active = 0
var/datum/gas_mixture/air
var/archived_cycle = 0
var/current_cycle = 0
var/icy = 0
var/icyoverlay
var/obj/effect/hotspot/active_hotspot
var/temperature_archived //USED ONLY FOR SOLIDS
var/atmos_overlay_type = "" //current active overlay
/turf/simulated/New()
..()
if(!blocks_air)
air = new
air.oxygen = oxygen
air.carbon_dioxide = carbon_dioxide
air.nitrogen = nitrogen
air.toxins = toxins
air.temperature = temperature
update_visuals()
/turf/simulated/Destroy()
visibilityChanged()
QDEL_NULL(active_hotspot)
return ..()
/turf/simulated/assume_air(datum/gas_mixture/giver)
if(!giver) return 0
var/datum/gas_mixture/receiver = air
if(istype(receiver))
air.merge(giver)
update_visuals()
return 1
else return ..()
/turf/simulated/proc/copy_air_with_tile(turf/simulated/T)
if(istype(T) && T.air && air)
air.copy_from(T.air)
/turf/simulated/proc/copy_air(datum/gas_mixture/copy)
if(air && copy)
air.copy_from(copy)
/turf/simulated/return_air()
if(air)
return air
else
return ..()
/turf/simulated/remove_air(amount as num)
if(air)
var/datum/gas_mixture/removed = null
removed = air.remove(amount)
update_visuals()
return removed
else
return ..()
/turf/simulated/proc/mimic_temperature_solid(turf/model, conduction_coefficient)
var/delta_temperature = (temperature_archived - model.temperature)
if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER))
var/heat = conduction_coefficient*delta_temperature* \
(heat_capacity*model.heat_capacity/(heat_capacity+model.heat_capacity))
temperature -= heat/heat_capacity
/turf/simulated/proc/share_temperature_mutual_solid(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER && heat_capacity && sharer.heat_capacity)
var/heat = conduction_coefficient*delta_temperature* \
(heat_capacity*sharer.heat_capacity/(heat_capacity+sharer.heat_capacity))
temperature -= heat/heat_capacity
sharer.temperature += heat/sharer.heat_capacity
/turf/simulated/proc/process_cell()
if(archived_cycle < SSair.times_fired) //archive self if not already done
archive()
current_cycle = SSair.times_fired
var/remove = 1 //set by non simulated turfs who are sharing with this turf
for(var/direction in cardinal)
if(!(atmos_adjacent_turfs & direction))
continue
var/turf/enemy_tile = get_step(src, direction)
if(istype(enemy_tile,/turf/simulated))
var/turf/simulated/enemy_simulated = enemy_tile
if(current_cycle > enemy_simulated.current_cycle)
enemy_simulated.archive()
/******************* GROUP HANDLING START *****************************************************************/
if(enemy_simulated.excited)
if(excited_group)
if(enemy_simulated.excited_group)
if(excited_group != enemy_simulated.excited_group)
excited_group.merge_groups(enemy_simulated.excited_group) //combine groups
share_air(enemy_simulated) //share
else
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
excited_group.add_turf(enemy_simulated) //add enemy to our group
share_air(enemy_simulated) //share
else
if(enemy_simulated.excited_group)
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
enemy_simulated.excited_group.add_turf(src) //join self to enemy group
share_air(enemy_simulated) //share
else
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
var/datum/excited_group/EG = new //generate new group
EG.add_turf(src)
EG.add_turf(enemy_simulated)
share_air(enemy_simulated) //share
else
if(!air.compare(enemy_simulated.air)) //compare if
SSair.add_to_active(enemy_simulated) //excite enemy
if(excited_group)
excited_group.add_turf(enemy_simulated) //add enemy to group
else
var/datum/excited_group/EG = new //generate new group
EG.add_turf(src)
EG.add_turf(enemy_simulated)
share_air(enemy_simulated) //share
/******************* GROUP HANDLING FINISH *********************************************************************/
else
if(!air.check_turf(enemy_tile, atmos_adjacent_turfs_amount))
var/difference = air.mimic(enemy_tile,atmos_adjacent_turfs_amount)
if(difference)
if(difference > 0)
consider_pressure_difference(enemy_tile, difference)
else
enemy_tile.consider_pressure_difference(src, difference)
remove = 0
if(excited_group)
last_share_check()
air.react()
if(air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
hotspot_expose(air.temperature, CELL_VOLUME)
for(var/atom/movable/item in src)
item.temperature_expose(air, air.temperature, CELL_VOLUME)
temperature_expose(air, air.temperature, CELL_VOLUME)
if(air.temperature > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION)
if(consider_superconductivity(starting = 1))
remove = 0
if(air.temperature < T0C && air.return_pressure() > 10)
icy = 1
else if(air.temperature > T0C)
icy = 0
update_visuals()
if(!excited_group && remove == 1)
SSair.remove_from_active(src)
/turf/simulated/proc/archive()
if(air) //For open space like floors
air.archive()
temperature_archived = temperature
archived_cycle = SSair.times_fired
/turf/simulated/proc/update_visuals()
if(icy && !icyoverlay)
overlays |= icemaster
icyoverlay = icemaster
else if(icyoverlay && !icy)
icyoverlay = null
overlays -= icemaster
var/new_overlay_type = tile_graphic()
if(new_overlay_type == atmos_overlay_type)
return
var/atmos_overlay = get_atmos_overlay_by_name(atmos_overlay_type)
if(atmos_overlay)
overlays -= atmos_overlay
mouse_opacity = MOUSE_OPACITY_ICON
atmos_overlay = get_atmos_overlay_by_name(new_overlay_type)
if(atmos_overlay)
overlays += atmos_overlay
atmos_overlay_type = new_overlay_type
/turf/simulated/proc/get_atmos_overlay_by_name(var/name)
switch(name)
if("plasma")
return plmaster
if("sleeping_agent")
return slmaster
return null
/turf/simulated/proc/tile_graphic()
if(air.toxins > MOLES_PLASMA_VISIBLE)
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
return "plasma"
var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air.trace_gases
if(sleeping_agent && (sleeping_agent.moles > 1))
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
return "sleeping_agent"
return null
/turf/simulated/proc/share_air(var/turf/simulated/T)
if(T.current_cycle < current_cycle)
var/difference
difference = air.share(T.air, atmos_adjacent_turfs_amount)
if(difference)
if(difference > 0)
consider_pressure_difference(T, difference)
else
T.consider_pressure_difference(src, difference)
last_share_check()
/turf/proc/consider_pressure_difference(var/turf/simulated/T, var/difference)
SSair.high_pressure_delta |= src
if(difference > pressure_difference)
pressure_direction = get_dir(src, T)
pressure_difference = difference
/turf/simulated/proc/last_share_check()
if(air.last_share > MINIMUM_AIR_TO_SUSPEND)
excited_group.reset_cooldowns()
/turf/proc/high_pressure_movements()
for(var/atom/movable/M in src)
M.experience_pressure_difference(pressure_difference, pressure_direction)
/atom/movable/var/pressure_resistance = 5
/atom/movable/var/throw_pressure_limit = 15
/atom/movable/var/last_forced_movement = 0
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction)
if(last_forced_movement >= SSair.times_fired)
return 0
else if(!anchored && !pulledby)
var/turf/target = get_turf(src)
var/datum/gas_mixture/target_air = target.return_air()
if(isspaceturf(target) || isunsimulatedturf(target) || pressure_resistance > target_air.return_pressure())
return 0
if(pressure_difference >= throw_pressure_limit)
var/general_direction = get_edge_target_turf(src, direction)
if(last_forced_movement + 10 < SSair.times_fired && is_valid_tochat_target(src)) //the first check prevents spamming throw to_chat
to_chat(src, "<span class='userdanger'>The pressure sends you flying!</span>")
spawn()
var/max_distance = 14 // reduce by one each calculation to prevent infinate loops.
var/min_observed_pressure = INFINITY
var/turf/possible_target = get_turf(src)
while(!isspaceturf(target) && !isunsimulatedturf(target) && max_distance > 0)
max_distance--
target_air = target.return_air()
min_observed_pressure = target_air.return_pressure()
possible_target = get_step_towards(target,general_direction)
if(istype(possible_target, /turf/space))
target = possible_target
break
if(!CanAtmosPass(possible_target))
target = possible_target
max_distance = 0
break
var/datum/gas_mixture/possible_target_air = possible_target.return_air()
if(possible_target_air.return_pressure() > min_observed_pressure)
target = possible_target
break
target = possible_target
if(max_distance)
throw_at(target, get_dist(src, target), pressure_difference / 200, null, 0, 0, null)
else
throw_at(target, pressure_difference / 10, pressure_difference / 200, null, 0, 0, null)
last_forced_movement = SSair.times_fired
return 1
else if(pressure_difference > pressure_resistance)
spawn()
step(src, direction)
last_forced_movement = SSair.times_fired
return 1
return 0
/datum/excited_group
var/list/turf_list = list()
var/breakdown_cooldown = 0
/datum/excited_group/New()
if(SSair)
SSair.excited_groups += src
/datum/excited_group/proc/add_turf(var/turf/simulated/T)
turf_list += T
T.excited_group = src
T.recently_active = 1
reset_cooldowns()
/datum/excited_group/proc/merge_groups(var/datum/excited_group/E)
if(turf_list.len > E.turf_list.len)
SSair.excited_groups -= E
for(var/turf/simulated/T in E.turf_list)
T.excited_group = src
turf_list += T
reset_cooldowns()
else
SSair.excited_groups -= src
for(var/turf/simulated/T in turf_list)
T.excited_group = E
E.turf_list += T
E.reset_cooldowns()
/datum/excited_group/proc/reset_cooldowns()
breakdown_cooldown = 0
/datum/excited_group/proc/self_breakdown()
var/datum/gas_mixture/A = new
var/datum/gas/sleeping_agent/S = new
A.trace_gases += S
for(var/turf/simulated/T in turf_list)
A.oxygen += T.air.oxygen
A.carbon_dioxide+= T.air.carbon_dioxide
A.nitrogen += T.air.nitrogen
A.toxins += T.air.toxins
if(T.air.trace_gases.len)
for(var/datum/gas/N in T.air.trace_gases)
S.moles += N.moles
for(var/turf/simulated/T in turf_list)
T.air.oxygen = A.oxygen/turf_list.len
T.air.carbon_dioxide= A.carbon_dioxide/turf_list.len
T.air.nitrogen = A.nitrogen/turf_list.len
T.air.toxins = A.toxins/turf_list.len
if(S.moles > 0)
if(T.air.trace_gases.len)
for(var/datum/gas/G in T.air.trace_gases)
G.moles = S.moles/turf_list.len
else
var/datum/gas/sleeping_agent/G = new
G.moles = S.moles/turf_list.len
T.air.trace_gases += G
T.update_visuals()
/datum/excited_group/proc/dismantle()
for(var/turf/simulated/T in turf_list)
T.excited = 0
T.recently_active = 0
T.excited_group = null
SSair.active_turfs -= T
garbage_collect()
/datum/excited_group/proc/garbage_collect()
for(var/turf/simulated/T in turf_list)
T.excited_group = null
turf_list.Cut()
SSair.excited_groups -= src
turf/simulated/proc/super_conduct()
var/conductivity_directions = 0
if(blocks_air)
//Does not participate in air exchange, so will conduct heat across all four borders at this time
conductivity_directions = NORTH|SOUTH|EAST|WEST
if(archived_cycle < SSair.times_fired)
archive()
else
//Does particate in air exchange so only consider directions not considered during process_cell()
for(var/direction in cardinal)
if(!(atmos_adjacent_turfs & direction) && !(atmos_supeconductivity & direction))
conductivity_directions += direction
if(conductivity_directions>0)
//Conduct with tiles around me
for(var/direction in cardinal)
if(conductivity_directions&direction)
var/turf/neighbor = get_step(src,direction)
if(!neighbor.thermal_conductivity)
continue
if(istype(neighbor, /turf/simulated)) //anything under this subtype will share in the exchange
var/turf/simulated/T = neighbor
if(T.archived_cycle < SSair.times_fired)
T.archive()
if(T.air)
if(air) //Both tiles are open
air.temperature_share(T.air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
else //Solid but neighbor is open
T.air.temperature_turf_share(src, T.thermal_conductivity)
SSair.add_to_active(T, 0)
else
if(air) //Open but neighbor is solid
air.temperature_turf_share(T, T.thermal_conductivity)
else //Both tiles are solid
share_temperature_mutual_solid(T, T.thermal_conductivity)
T.temperature_expose(null, T.temperature, null)
T.consider_superconductivity()
else
if(air) //Open
air.temperature_mimic(neighbor, neighbor.thermal_conductivity)
else
mimic_temperature_solid(neighbor, neighbor.thermal_conductivity)
radiate_to_spess()
//Conduct with air on my tile if I have it
if(air)
air.temperature_turf_share(src, thermal_conductivity)
//Make sure still hot enough to continue conducting heat
if(air.temperature < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)
SSair.active_super_conductivity -= src
return 0
else
if(temperature < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)
SSair.active_super_conductivity -= src
return 0
turf/simulated/proc/consider_superconductivity(starting)
if(!thermal_conductivity)
return 0
if(air)
if(air.temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
return 0
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 0
else
if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION))
return 0
SSair.active_super_conductivity |= src
return 1
turf/simulated/proc/radiate_to_spess() //Radiate excess tile heat to space
if(temperature > T0C) //Considering 0 degC as te break even point for radiation in and out
var/delta_temperature = (temperature_archived - 2.7) //hardcoded space temperature
if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER))
var/heat = thermal_conductivity*delta_temperature* \
(heat_capacity*700000/(heat_capacity+700000)) //700000 is the heat_capacity from a space turf, hardcoded here
temperature -= heat/heat_capacity
/turf/proc/Initialize_Atmos(times_fired)
CalculateAdjacentTurfs()
/turf/simulated/Initialize_Atmos(times_fired)
..()
update_visuals()
for(var/direction in cardinal)
if(!(atmos_adjacent_turfs & direction))
continue
var/turf/enemy_tile = get_step(src, direction)
if(istype(enemy_tile, /turf/simulated))
var/turf/simulated/enemy_simulated = enemy_tile
if(!air.compare(enemy_simulated.air))
excited = 1
SSair.active_turfs |= src
break
else
if(!air.check_turf_total(enemy_tile))
excited = 1
SSair.active_turfs |= src