mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Added comments and updated the changelog.
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
This object is contained within zone/var/connections. It's generated whenever two turfs from different zones are linked.
|
||||
Indirect connections will not merge the two zones after they reach equilibrium.
|
||||
*/
|
||||
|
||||
connection
|
||||
var
|
||||
turf //The turfs involved in the connection.
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
zone
|
||||
New(turf/start)
|
||||
//Get the turfs that are part of the zone using a floodfill method
|
||||
if(istype(start,/list))
|
||||
contents = start
|
||||
else
|
||||
contents = FloodFill(start)
|
||||
|
||||
//Change all the zone vars of the turfs, check for space to be added to space_tiles.
|
||||
for(var/turf/T in contents)
|
||||
T.zone = src
|
||||
if(istype(T,/turf/space))
|
||||
AddSpace(T)
|
||||
|
||||
//Generate the gas_mixture for use in this zone by using the average of the gases
|
||||
//defined at startup.
|
||||
air = new
|
||||
var/members = contents.len
|
||||
for(var/turf/simulated/T in contents)
|
||||
@@ -18,8 +24,12 @@ zone
|
||||
air.temperature += T.temperature / members
|
||||
air.group_multiplier = contents.len
|
||||
air.update_values()
|
||||
|
||||
//Add this zone to the global list.
|
||||
zones += src
|
||||
|
||||
Del()
|
||||
//Ensuring the zone list doesn't get clogged with null values.
|
||||
zones -= src
|
||||
. = ..()
|
||||
|
||||
@@ -31,17 +41,23 @@ proc/FloodFill(turf/start)
|
||||
|
||||
while(open.len)
|
||||
for(var/turf/T in open)
|
||||
//Stop if there's a door, even if it's open. These are handled by indirect connection.
|
||||
if(!T.HasDoor())
|
||||
|
||||
for(var/d in cardinal)
|
||||
var/turf/O = get_step(T,d)
|
||||
//Simple pass check.
|
||||
if(O.ZCanPass(T) && !(O in open) && !(O in closed))
|
||||
open += O
|
||||
|
||||
open -= T
|
||||
closed += T
|
||||
|
||||
return closed
|
||||
|
||||
turf/proc/ZCanPass(turf/T)
|
||||
//Fairly standard pass checks for turfs, objects and directional windows. Also stops at the edge of space.
|
||||
|
||||
if(istype(T,/turf/space)) return 0
|
||||
else
|
||||
if(T.blocks_air||blocks_air)
|
||||
@@ -52,6 +68,7 @@ turf/proc/ZCanPass(turf/T)
|
||||
continue
|
||||
if(!obstacle.CanPass(0, T, 0, 1))
|
||||
return 0
|
||||
|
||||
for(var/obj/obstacle in T)
|
||||
if(istype(obstacle,/obj/machinery/door) && !istype(obstacle,/obj/machinery/door/window))
|
||||
continue
|
||||
|
||||
@@ -5,7 +5,7 @@ var/list/zones = list()
|
||||
zone
|
||||
var
|
||||
dbg_output = 0 //Enables debug output.
|
||||
rebuild = 0 //If 1, zone will be rebuilt on next process.
|
||||
rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used.
|
||||
datum/gas_mixture/air //The air contents of the zone.
|
||||
list/contents //All the tiles that are contained in this zone.
|
||||
list/connections // /connection objects which refer to connections with other zones, e.g. through a door.
|
||||
|
||||
207
code/ZAS/Fire.dm
207
code/ZAS/Fire.dm
@@ -1,11 +1,14 @@
|
||||
vs_control/var/IgnitionLevel = 10 //Moles of oxygen+plasma - co2 needed to burn.
|
||||
|
||||
#define OXYGEN
|
||||
//Some legacy definitions so fires can be started.
|
||||
atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return null
|
||||
|
||||
|
||||
turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
|
||||
|
||||
|
||||
|
||||
turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
if(fire_protection > world.time-300) return
|
||||
var/datum/gas_mixture/air_contents = return_air(1)
|
||||
@@ -40,109 +43,6 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
|
||||
return igniting
|
||||
|
||||
obj/effect/hotspot
|
||||
//Icon for fire on turfs, also helps for nurturing small fires until they are full tile
|
||||
|
||||
anchored = 1
|
||||
|
||||
mouse_opacity = 0
|
||||
|
||||
//luminosity = 3
|
||||
|
||||
icon = 'fire.dmi'
|
||||
icon_state = "1"
|
||||
|
||||
layer = TURF_LAYER
|
||||
|
||||
var
|
||||
volume = 125
|
||||
temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
|
||||
just_spawned = 1
|
||||
|
||||
bypassing = 0
|
||||
|
||||
obj/effect/hotspot/proc/perform_exposure()
|
||||
var/turf/simulated/floor/location = loc
|
||||
if(!istype(location))
|
||||
return 0
|
||||
|
||||
if(volume > CELL_VOLUME*0.95)
|
||||
bypassing = 1
|
||||
else bypassing = 0
|
||||
|
||||
if(bypassing)
|
||||
if(!just_spawned)
|
||||
volume = location.air.fuel_burnt*FIRE_GROWTH_RATE
|
||||
temperature = location.air.temperature
|
||||
else
|
||||
var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.volume)
|
||||
|
||||
affected.temperature = temperature
|
||||
|
||||
affected.react()
|
||||
|
||||
temperature = affected.temperature
|
||||
volume = affected.fuel_burnt*FIRE_GROWTH_RATE
|
||||
|
||||
location.assume_air(affected)
|
||||
|
||||
for(var/atom/item in loc)
|
||||
item.temperature_expose(null, temperature, volume)
|
||||
|
||||
obj/effect/hotspot/process(turf/simulated/list/possible_spread)
|
||||
if(just_spawned)
|
||||
just_spawned = 0
|
||||
return 0
|
||||
|
||||
var/turf/simulated/floor/location = loc
|
||||
if(!istype(location))
|
||||
del(src)
|
||||
|
||||
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
|
||||
del(src)
|
||||
|
||||
if(location.air.toxins < 0.5 || location.air.oxygen < 0.5)
|
||||
del(src)
|
||||
|
||||
|
||||
perform_exposure()
|
||||
|
||||
if(location.wet) location.wet = 0
|
||||
|
||||
if(bypassing)
|
||||
icon_state = "3"
|
||||
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
|
||||
|
||||
for(var/turf/simulated/possible_target in possible_spread)
|
||||
if(!locate(/obj/effect/hotspot) in possible_target)
|
||||
possible_target.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
|
||||
|
||||
else
|
||||
if(volume > CELL_VOLUME*0.4)
|
||||
icon_state = "2"
|
||||
else
|
||||
icon_state = "1"
|
||||
|
||||
return 1
|
||||
|
||||
obj/effect/hotspot/New()
|
||||
..()
|
||||
dir = pick(cardinal)
|
||||
sd_SetLuminosity(3)
|
||||
|
||||
obj/effect/hotspot/Del()
|
||||
src.sd_SetLuminosity(0)
|
||||
loc = null
|
||||
..()
|
||||
|
||||
var
|
||||
fire_ratio_1 = 0.05
|
||||
|
||||
obj
|
||||
fire
|
||||
//Icon for fire on turfs, also helps for nurturing small fires until they are full tile
|
||||
@@ -160,73 +60,82 @@ obj
|
||||
var
|
||||
volume = CELL_VOLUME
|
||||
temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
firelevel = 10000
|
||||
firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
|
||||
archived_firelevel = 0
|
||||
|
||||
process()
|
||||
|
||||
if(firelevel > vsc.IgnitionLevel)
|
||||
|
||||
var/turf/simulated/floor/S = loc
|
||||
if(!S.zone) del src
|
||||
//src.temperature += (src.firelevel/FireTempDivider+FireOffset - src.temperature) / FireRate
|
||||
if(!S.zone) del src //Cannot exist where zones are broken.
|
||||
|
||||
if(istype(S,/turf/simulated/floor))
|
||||
var
|
||||
datum/gas_mixture/air_contents = S.return_air()
|
||||
//Get whatever trace fuels are in the area
|
||||
datum/gas/volatile_fuel/fuel = locate(/datum/gas/volatile_fuel/) in air_contents.trace_gases
|
||||
//Also get liquid fuels on the ground.
|
||||
obj/liquid_fuel/liquid = locate() in S
|
||||
|
||||
firelevel = air_contents.calculate_firelevel(liquid)
|
||||
|
||||
//Ensure that there is an appropriate amount of fuel and O2 here.
|
||||
if(firelevel > 25 && (air_contents.toxins || fuel || liquid))
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(S.air_check_directions&direction) //Grab all valid bordering tiles
|
||||
|
||||
var/turf/simulated/enemy_tile = get_step(S, direction)
|
||||
|
||||
if(istype(enemy_tile))
|
||||
//If extinguisher mist passed over the turf it's trying to spread to, don't spread and
|
||||
//reduce firelevel.
|
||||
if(enemy_tile.fire_protection > world.time-30)
|
||||
firelevel -= 150
|
||||
continue
|
||||
|
||||
//Spread the fire.
|
||||
if(!(locate(/obj/fire) in enemy_tile))
|
||||
if( prob( firelevel/2.5 ) )
|
||||
new/obj/fire(enemy_tile,firelevel)
|
||||
// else
|
||||
// world << "Spread Probability: [firelevel/(vsc.IgnitionLevel*0.1)]%."
|
||||
// else
|
||||
// world << "There's a fire there bitch."
|
||||
// else
|
||||
// world << "[enemy_tile] cannot be spread to."
|
||||
//else
|
||||
// world << "Not enough firelevel to spread: [firelevel]/[vsc.IgnitionLevel*1.5]"
|
||||
|
||||
var/datum/gas_mixture/flow = air_contents.remove_ratio(0.5)
|
||||
//n = PV/RT, taking the volume of a single tile from the gas.
|
||||
var/datum/gas_mixture/flow = air_contents.remove_ratio(0.5) //Take half the air from the room I guess.
|
||||
|
||||
if(flow)
|
||||
|
||||
//Ensure adequate oxygen and fuel.
|
||||
if(flow.oxygen > 0.3 && (flow.toxins || fuel || liquid))
|
||||
|
||||
//Change icon depending on the fuel, and thus temperature.
|
||||
icon_state = "1"
|
||||
if(firelevel > 25)
|
||||
icon_state = "2"
|
||||
if(firelevel > 100)
|
||||
icon_state = "3"
|
||||
|
||||
//Ensure flow temperature is higher than minimum fire temperatures.
|
||||
flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature)
|
||||
|
||||
//Burn the gas mixture.
|
||||
flow.zburn(liquid)
|
||||
|
||||
else
|
||||
|
||||
del src
|
||||
|
||||
|
||||
S.assume_air(flow)
|
||||
S.assume_air(flow) //Then put it back where you found it.
|
||||
|
||||
else
|
||||
//world << "No air at all."
|
||||
del src
|
||||
else
|
||||
del src
|
||||
else
|
||||
//world << "Insufficient fire level for ignition: [firelevel]/[IgnitionLevel]"
|
||||
del src
|
||||
|
||||
for(var/mob/living/carbon/human/M in loc)
|
||||
M.FireBurn(min(max(0.1,firelevel / 20),10))
|
||||
M.FireBurn(min(max(0.1,firelevel / 20),10)) //Burn the humans!
|
||||
|
||||
|
||||
New(newLoc,fl)
|
||||
@@ -235,7 +144,7 @@ obj
|
||||
sd_SetLuminosity(3)
|
||||
firelevel = fl
|
||||
for(var/mob/living/carbon/human/M in loc)
|
||||
M.FireBurn(min(max(0.1,firelevel / 20),10))
|
||||
M.FireBurn(min(max(0.1,firelevel / 20),10)) //Burn the humans!
|
||||
|
||||
Del()
|
||||
if (istype(loc, /turf/simulated))
|
||||
@@ -246,23 +155,29 @@ obj
|
||||
..()
|
||||
|
||||
obj/liquid_fuel
|
||||
//Liquid fuel is used for things that used to rely on volatile fuels or plasma being contained to a couple tiles.
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "fuel"
|
||||
layer = TURF_LAYER+0.2
|
||||
anchored = 1
|
||||
var/amount = 1
|
||||
var/amount = 1 //Basically moles.
|
||||
|
||||
New(newLoc,amt=1)
|
||||
src.amount = amt
|
||||
|
||||
//Be absorbed by any other liquid fuel in the tile.
|
||||
for(var/obj/liquid_fuel/other in newLoc)
|
||||
if(other != src)
|
||||
other.amount += src.amount
|
||||
spawn other.Spread()
|
||||
del src
|
||||
return
|
||||
|
||||
Spread()
|
||||
. = ..()
|
||||
|
||||
proc/Spread()
|
||||
//Allows liquid fuels to sometimes flow into other tiles.
|
||||
if(amount < 0.5) return
|
||||
var/turf/simulated/S = loc
|
||||
if(!istype(S)) return
|
||||
@@ -277,22 +192,23 @@ obj/liquid_fuel
|
||||
icon_state = "mustard"
|
||||
anchored = 0
|
||||
New(newLoc, amt = 1, d = 0)
|
||||
dir = d
|
||||
dir = d //Setting this direction means you won't get torched by your own flamethrower.
|
||||
. = ..()
|
||||
Spread()
|
||||
//The spread for flamethrower fuel is much more precise, to create a wide fire pattern.
|
||||
if(amount < 0.1) return
|
||||
var/turf/simulated/S = loc
|
||||
if(!istype(S)) return
|
||||
|
||||
for(var/d in list(turn(dir,90),turn(dir,-90)))
|
||||
if(S.air_check_directions & d)
|
||||
var/turf/simulated/O = get_step(S,d)
|
||||
new/obj/liquid_fuel/flamethrower_fuel(O,amount*0.25,d)
|
||||
O.hotspot_expose((T20C*2) + 380,500)
|
||||
O.hotspot_expose((T20C*2) + 380,500) //Light flamethrower fuel on fire immediately.
|
||||
|
||||
amount *= 0.5
|
||||
|
||||
vs_control/var/switch_fire = 1
|
||||
|
||||
turf/simulated/var/fire_protection = 0
|
||||
turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
|
||||
|
||||
turf/proc/apply_fire_protection()
|
||||
turf/simulated/apply_fire_protection()
|
||||
@@ -300,50 +216,72 @@ turf/simulated/apply_fire_protection()
|
||||
|
||||
datum/gas_mixture/proc
|
||||
zburn(obj/liquid_fuel/liquid)
|
||||
//This proc is similar to fire(), but uses a simple logarithm to calculate temp, and is thus more stable with ZAS.
|
||||
if(temperature > PLASMA_MINIMUM_BURN_TEMPERATURE)
|
||||
var
|
||||
total_fuel = toxins
|
||||
fuel_sources = 0
|
||||
fuel_sources = 0 //We'll divide by this later so that fuel is consumed evenly.
|
||||
datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
|
||||
if(fuel)
|
||||
//Volatile Fuel
|
||||
total_fuel += fuel.moles
|
||||
fuel_sources++
|
||||
|
||||
if(liquid)
|
||||
//Liquid Fuel
|
||||
if(liquid.amount <= 0)
|
||||
del liquid
|
||||
else
|
||||
total_fuel += liquid.amount
|
||||
fuel_sources++
|
||||
|
||||
//Toxins
|
||||
if(toxins > 0.3) fuel_sources++
|
||||
|
||||
if(!fuel_sources) return 0
|
||||
if(oxygen > 0.3 && total_fuel)
|
||||
if(!fuel_sources) return 0 //If there's no fuel, there's no burn. Can't divide by zero anyway.
|
||||
|
||||
if(oxygen > 0.3)
|
||||
|
||||
//Calculate the firelevel.
|
||||
var/firelevel = calculate_firelevel(liquid)
|
||||
//f(x) = 1000ln(0.01x + 1.45)
|
||||
|
||||
//Reaches a maximum practical temperature of around 2750.
|
||||
|
||||
temperature = 1000*log(0.016*firelevel + 1.45)
|
||||
|
||||
//Consume some gas.
|
||||
var/consumed_gas = min(oxygen,0.002*firelevel,total_fuel) / fuel_sources
|
||||
|
||||
oxygen -= consumed_gas
|
||||
|
||||
toxins = max(0,toxins-consumed_gas)
|
||||
|
||||
if(fuel)
|
||||
fuel.moles -= consumed_gas
|
||||
if(fuel.moles <= 0) del fuel
|
||||
|
||||
if(liquid)
|
||||
liquid.amount -= consumed_gas
|
||||
if(liquid.amount <= 0) del liquid
|
||||
|
||||
update_values()
|
||||
return consumed_gas*fuel_sources
|
||||
return 0
|
||||
|
||||
calculate_firelevel(obj/liquid_fuel/liquid)
|
||||
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
|
||||
var
|
||||
datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
fuel_level = 0
|
||||
liquid_level = 0
|
||||
|
||||
if(fuel) fuel_level = fuel.moles
|
||||
if(liquid) liquid_level = liquid.amount
|
||||
return oxygen + toxins + liquid_level*15 + fuel_level*5
|
||||
|
||||
/mob/living/carbon/human/proc/FireBurn(mx as num)
|
||||
//NO! NOT INTO THE PIT! IT BURRRRRNS!
|
||||
//Burns mobs due to fire. Respects heat transfer coefficients on various body parts.
|
||||
|
||||
var
|
||||
head_exposure = 1
|
||||
@@ -352,6 +290,7 @@ datum/gas_mixture/proc
|
||||
legs_exposure = 1
|
||||
arms_exposure = 1
|
||||
|
||||
//Get heat transfer coefficients for clothing.
|
||||
for(var/obj/item/clothing/C in src)
|
||||
if(l_hand == C || r_hand == C) continue
|
||||
if(C.body_parts_covered & HEAD)
|
||||
@@ -365,8 +304,6 @@ datum/gas_mixture/proc
|
||||
if(C.body_parts_covered & ARMS)
|
||||
arms_exposure *= C.heat_transfer_coefficient
|
||||
|
||||
mx *= 1
|
||||
|
||||
//Always check these damage procs first if fire damage isn't working. They're probably what's wrong.
|
||||
|
||||
apply_damage(2.5*mx*head_exposure, BURN, "head", 0, 0, "Fire")
|
||||
|
||||
@@ -1,43 +1,34 @@
|
||||
zone
|
||||
proc
|
||||
AddTurf(turf/T)
|
||||
//Adds the turf to contents, increases the size of the zone, and sets the zone var.
|
||||
if(T in contents) return
|
||||
contents += T
|
||||
air.group_multiplier++
|
||||
T.zone = src
|
||||
RemoveTurf(turf/T)
|
||||
//Same, but in reverse.
|
||||
if(!(T in contents)) return
|
||||
contents -= T
|
||||
air.group_multiplier--
|
||||
T.zone = null
|
||||
|
||||
DivideAir(ratio)
|
||||
ratio = min(1,max(0,ratio))
|
||||
air.oxygen *= ratio
|
||||
air.oxygen = QUANTIZE(air.oxygen)
|
||||
air.nitrogen *= ratio
|
||||
air.nitrogen = QUANTIZE(air.nitrogen)
|
||||
air.toxins *= ratio
|
||||
air.toxins = QUANTIZE(air.toxins)
|
||||
air.carbon_dioxide *= ratio
|
||||
air.carbon_dioxide = QUANTIZE(air.carbon_dioxide)
|
||||
if(air.trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in air.trace_gases)
|
||||
trace_gas.moles *= ratio
|
||||
trace_gas.moles = QUANTIZE(trace_gas.moles)
|
||||
air.temperature = air.temperature*ratio + TCMB*(1-ratio)
|
||||
air.temperature = QUANTIZE(air.temperature)
|
||||
|
||||
AddSpace(turf/space/S)
|
||||
//Adds a space tile to the list, and creates the list if null.
|
||||
if(istype(S,/turf/space))
|
||||
if(!space_tiles) space_tiles = list()
|
||||
space_tiles += S
|
||||
|
||||
RemoveSpace(turf/space/S)
|
||||
//Removes a space tile from the list, and deletes the list if length is 0.
|
||||
if(space_tiles)
|
||||
space_tiles -= S
|
||||
if(!space_tiles.len) space_tiles = null
|
||||
|
||||
turf/proc/HasDoor(turf/O)
|
||||
//Checks for the presence of doors, used for zone spreading and connection.
|
||||
//A positive numerical argument checks only for closed doors.
|
||||
//Another turf as an argument checks for windoors between here and there.
|
||||
for(var/obj/machinery/door/D in src)
|
||||
if(isnum(O) && O)
|
||||
if(!D.density) continue
|
||||
@@ -48,6 +39,7 @@ turf/proc/HasDoor(turf/O)
|
||||
return 1
|
||||
|
||||
turf/proc/find_zone()
|
||||
//Allows newly generated turfs to join up with a nearby zone.
|
||||
if(world.time < 10) return
|
||||
for(var/d in cardinal)
|
||||
var/turf/T = get_step(src,d)
|
||||
@@ -59,6 +51,7 @@ turf/proc/find_zone()
|
||||
ZConnect(src,T)
|
||||
|
||||
turf/proc/check_connections()
|
||||
//Checks for new connections that can be made.
|
||||
for(var/d in cardinal)
|
||||
var/turf/T = get_step(src,d)
|
||||
if(!T || !T.zone || !T.CanPass(0,src,0,0)) continue
|
||||
@@ -66,6 +59,7 @@ turf/proc/check_connections()
|
||||
ZConnect(src,T)
|
||||
|
||||
turf/proc/check_for_space()
|
||||
//Checks for space around the turf.
|
||||
for(var/d in cardinal)
|
||||
var/turf/T = get_step(src,d)
|
||||
if(istype(T,/turf/space) && T.CanPass(0,src,0,0))
|
||||
@@ -73,97 +67,125 @@ turf/proc/check_for_space()
|
||||
|
||||
proc
|
||||
ZMerge(zone/A,zone/B)
|
||||
//world << "Merge occured."
|
||||
//Merges two zones so that they are one.
|
||||
var
|
||||
a_size = A.air.group_multiplier
|
||||
b_size = B.air.group_multiplier
|
||||
c_size = a_size + b_size
|
||||
new_contents = A.contents + B.contents
|
||||
|
||||
//Set air multipliers to one so air represents gas per tile.
|
||||
A.air.group_multiplier = 1
|
||||
B.air.group_multiplier = 1
|
||||
|
||||
//Remove some air proportional to the size of this zone.
|
||||
A.air.remove_ratio(a_size/c_size)
|
||||
B.air.remove_ratio(b_size/c_size)
|
||||
|
||||
//Merge the gases and set the multiplier to the sum of the old ones.
|
||||
A.air.merge(B.air)
|
||||
A.air.group_multiplier = c_size
|
||||
|
||||
//Check for connections to merge into the new zone.
|
||||
for(var/connection/C in B.connections)
|
||||
if((C.A in new_contents) && (C.B in new_contents))
|
||||
del C
|
||||
continue
|
||||
if(!A.connections) A.connections = list()
|
||||
A.connections += C
|
||||
|
||||
//Add space tiles.
|
||||
A.space_tiles += B.space_tiles
|
||||
|
||||
//Add contents.
|
||||
A.contents = new_contents
|
||||
|
||||
//Set all the zone vars.
|
||||
for(var/turf/T in B.contents)
|
||||
T.zone = A
|
||||
|
||||
del B
|
||||
|
||||
ZConnect(turf/A,turf/B)
|
||||
//Connects two zones by forming a connection object representing turfs A and B.
|
||||
|
||||
//Make sure that if it's space, it gets added to space_tiles instead.
|
||||
if(istype(B,/turf/space))
|
||||
if(A.zone)
|
||||
A.zone.AddSpace(B)
|
||||
//world << "Space added."
|
||||
return
|
||||
if(istype(A,/turf/space))
|
||||
if(B.zone)
|
||||
B.zone.AddSpace(A)
|
||||
//world << "Space added."
|
||||
return
|
||||
|
||||
//Make some preliminary checks to see if the connection is valid.
|
||||
if(!A.zone || !B.zone) return
|
||||
if(A.zone == B.zone) return
|
||||
if(!A.CanPass(0,B,0,0)) return
|
||||
|
||||
//Ensure the connection isn't already made.
|
||||
for(var/connection/C in A.zone.connections)
|
||||
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
||||
return
|
||||
var/connection/C = new(A,B)
|
||||
if(A.HasDoor(B) || B.HasDoor(A)) C.indirect = 1
|
||||
//world << "Connection Formed: [A] --> [B] [(C.indirect?"Indirect":"Direct")]"
|
||||
//A.overlays += 'zone_connection_A.dmi'
|
||||
//B.overlays += 'zone_connection_B.dmi'
|
||||
//spawn(10)
|
||||
// A.overlays -= 'zone_connection_A.dmi'
|
||||
// B.overlays -= 'zone_connection_B.dmi'
|
||||
|
||||
var/connection/C = new(A,B)
|
||||
|
||||
//Ensure zones separated by doors do not merge.
|
||||
if(A.HasDoor(B) || B.HasDoor(A)) C.indirect = 1
|
||||
|
||||
ZDisconnect(turf/A,turf/B)
|
||||
//Removes a zone connection. Can split zones in the case of a permanent barrier.
|
||||
|
||||
//If one of them doesn't have a zone, it might be space, so check for that.
|
||||
if(A.zone && B.zone)
|
||||
//If the two zones are different, just remove a connection.
|
||||
if(A.zone != B.zone)
|
||||
for(var/connection/C in A.zone.connections)
|
||||
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
||||
//world << "Connection Dissolved: [A] -/-> [B] [(C.indirect?"Indirect":"Direct")]"
|
||||
/*A.overlays += 'zone_connection_A.dmi'
|
||||
B.overlays += 'zone_connection_B.dmi'
|
||||
spawn(10)
|
||||
A.overlays -= 'zone_connection_A.dmi'
|
||||
B.overlays -= 'zone_connection_B.dmi'*/
|
||||
del C
|
||||
//If they're the same, split the zone at this line.
|
||||
else
|
||||
//Preliminary checks to prevent stupidity.
|
||||
if(A == B) return
|
||||
if(A.CanPass(0,B,0,0)) return
|
||||
if(A.HasDoor(B) || B.HasDoor(A)) return
|
||||
|
||||
//Do a test fill. If turf B is still in the floodfill, then the zone isn't really split.
|
||||
var/zone/oldzone = A.zone
|
||||
var/list/test = FloodFill(A)
|
||||
if(B in test) return
|
||||
|
||||
else
|
||||
var/zone/Z = new(test,oldzone.air)
|
||||
var/zone/Z = new(test,oldzone.air) //Create a new zone based on the old air and the test fill.
|
||||
|
||||
//Add connections from the old zone.
|
||||
for(var/connection/C in oldzone.connections)
|
||||
if((A in Z.contents) || (B in Z.contents))
|
||||
if(!Z.connections) Z.connections = list()
|
||||
Z.connections += C
|
||||
|
||||
//Check for space.
|
||||
for(var/turf/T in test)
|
||||
T.check_for_space()
|
||||
|
||||
//Make a new, identical air mixture for the other zone.
|
||||
var/datum/gas_mixture/Y_Air = new
|
||||
Y_Air.copy_from(oldzone.air)
|
||||
var/zone/Y = new(B,Y_Air)
|
||||
|
||||
var/zone/Y = new(B,Y_Air) //Make a new zone starting at B and using Y_Air.
|
||||
|
||||
//Add relevant connections from old zone.
|
||||
for(var/connection/C in oldzone.connections)
|
||||
if((A in Y.contents) || (B in Y.contents))
|
||||
if(!Y.connections) Y.connections = list()
|
||||
Y.connections += C
|
||||
|
||||
//Add the remaining space tiles to this zone.
|
||||
for(var/turf/space/T in oldzone.space_tiles)
|
||||
if(!(T in Z.space_tiles))
|
||||
Y.AddSpace(T)
|
||||
|
||||
oldzone.air = null
|
||||
del oldzone
|
||||
else
|
||||
|
||||
@@ -1,94 +1,35 @@
|
||||
pl_control/var
|
||||
PLASMA_DMG = 3
|
||||
PLASMA_DMG_NAME = "Plasma Damage Multiplier"
|
||||
PLASMA_DMG_DESC = "Multiplier on how much damage inhaling plasma can do."
|
||||
|
||||
CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth.
|
||||
CLOTH_CONTAMINATION_NAME = "Plasma - Cloth Contamination"
|
||||
CLOTH_CONTAMINATION_RANDOM = 60
|
||||
CLOTH_CONTAMINATION_METHOD = "Toggle"
|
||||
CLOTH_CONTAMINATION_DESC = "If set to nonzero, plasma will contaminate cloth items (uniforms, backpacks, etc.)\
|
||||
and cause a small amount of damage over time to anyone carrying or wearing them. Contamination can be washed off in the washer."
|
||||
|
||||
ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or
|
||||
//decontaminated.
|
||||
ALL_ITEM_CONTAMINATION_NAME = "Plasma - Full Contamination"
|
||||
ALL_ITEM_CONTAMINATION_RANDOM = 10
|
||||
ALL_ITEM_CONTAMINATION_METHOD = "Toggle"
|
||||
ALL_ITEM_CONTAMINATION_DESC = "Like Cloth Contamination, but all item types are susceptible."
|
||||
|
||||
PLASMAGUARD_ONLY = 0
|
||||
PLASMAGUARD_ONLY_NAME = "Plasma - Biosuits/Spacesuits Only"
|
||||
PLASMAGUARD_ONLY_RANDOM = 20
|
||||
PLASMAGUARD_ONLY_METHOD = "Toggle"
|
||||
PLASMAGUARD_ONLY_DESC = "If on, any suits that are not biosuits or space suits will not protect against contamination."
|
||||
|
||||
//CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters,
|
||||
//CANISTER_CORROSION_RANDOM = 20 //or it will corrode the tank.
|
||||
//CANISTER_CORROSION_METHOD = "Toggle"
|
||||
PLASMAGUARD_ONLY = 0 //If this is on, only biosuits and spacesuits protect against contamination and ill effects.
|
||||
|
||||
GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 10,000.
|
||||
GENETIC_CORRUPTION_NAME = "Plasma - Genetic Corruption"
|
||||
GENETIC_CORRUPTION_RANDOM = "PROB10/3d6"
|
||||
GENETIC_CORRUPTION_METHOD = "Numeric"
|
||||
GENETIC_CORRUPTION_DESC = "When set to a probability in 1000, any humans in plasma will have this chance to develop a random mutation."
|
||||
|
||||
SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
|
||||
SKIN_BURNS_NAME = "Plasma - Skin Burns"
|
||||
SKIN_BURNS_RANDOM = 10
|
||||
SKIN_BURNS_METHOD = "Toggle"
|
||||
SKIN_BURNS_DESC = "When toggled, humans with exposed skin will suffer burns (similar to mustard gas) in plasma."
|
||||
|
||||
//PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time.
|
||||
//PLASMA_INJECTS_TOXINS_RANDOM = 30
|
||||
//PLASMA_INJECTS_TOXINS_METHOD = "Toggle"
|
||||
|
||||
EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
|
||||
EYE_BURNS_NAME = "Plasma - Eye Burns"
|
||||
EYE_BURNS_RANDOM = 30
|
||||
EYE_BURNS_METHOD = "Toggle"
|
||||
EYE_BURNS_DESC = "When toggled, humans without masks that cover the eyes will suffer temporary blurriness and sight loss,\
|
||||
and may need glasses to see again if exposed for long durations."
|
||||
|
||||
//N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high.
|
||||
//N2O_REACTION_RANDOM = 5
|
||||
|
||||
//PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay!
|
||||
//PLASMA_COLOR_RANDOM = "PICKonturf,onturf"
|
||||
|
||||
//PLASMA_DMG_OFFSET = 1
|
||||
//PLASMA_DMG_OFFSET_RANDOM = "1d5"
|
||||
//PLASMA_DMG_QUOTIENT = 10
|
||||
//PLASMA_DMG_QUOTIENT_RANDOM = "1d10+4"
|
||||
|
||||
CONTAMINATION_LOSS = 0.01
|
||||
CONTAMINATION_LOSS_NAME = "Plasma - Contamination Damage"
|
||||
CONTAMINATION_LOSS_DESC = "A number representing the damage done per life cycle by contaminated items."
|
||||
|
||||
PLASMA_HALLUCINATION = 1
|
||||
PLASMA_HALLUCINATION_NAME = "Plasma - Hallucination"
|
||||
PLASMA_HALLUCINATION_METHOD = "Toggle"
|
||||
PLASMA_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\
|
||||
who breathe plasma."
|
||||
PLASMA_HALLUCINATION = 0
|
||||
|
||||
N2O_HALLUCINATION = 1
|
||||
N2O_HALLUCINATION_NAME = "Nitrous Oxide - Hallucination"
|
||||
N2O_HALLUCINATION_METHOD = "Toggle"
|
||||
N2O_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\
|
||||
who breathe N2O."
|
||||
//CONTAMINATION_LOSS_RANDOM = "5d5"
|
||||
//Plasma has a chance to be a different color.
|
||||
|
||||
|
||||
obj/var/contaminated = 0
|
||||
|
||||
obj/item/proc
|
||||
can_contaminate()
|
||||
//Clothing and backpacks can be contaminated.
|
||||
if(flags & PLASMAGUARD) return 0
|
||||
if((flags & SUITSPACE) && !vsc.plc.PLASMAGUARD_ONLY) return 1
|
||||
if(vsc.plc.ALL_ITEM_CONTAMINATION) return 1
|
||||
if(flags & SUITSPACE) return 0
|
||||
else if(istype(src,/obj/item/clothing)) return 1
|
||||
else if(istype(src,/obj/item/weapon/storage/backpack)) return 1
|
||||
|
||||
contaminate()
|
||||
//Do a contamination overlay? Temporary measure to keep contamination less deadly than it was.
|
||||
if(!contaminated)
|
||||
contaminated = 1
|
||||
overlays += 'icons/effects/contamination.dmi'
|
||||
@@ -100,6 +41,8 @@ obj/item/proc
|
||||
/mob/proc/contaminate()
|
||||
|
||||
/mob/living/carbon/human/contaminate()
|
||||
//See if anything can be contaminated.
|
||||
|
||||
if(!pl_suit_protected())
|
||||
suit_contamination()
|
||||
|
||||
@@ -109,25 +52,26 @@ obj/item/proc
|
||||
if(istype(back,/obj/item/weapon/storage/backpack))
|
||||
back.contaminate()
|
||||
|
||||
/*if(l_hand)
|
||||
if(l_hand.can_contaminate()) l_hand.contaminate()
|
||||
if(r_hand)
|
||||
if(r_hand.can_contaminate()) r_hand.contaminate()
|
||||
if(belt)
|
||||
if(belt.can_contaminate()) belt.contaminate()*/
|
||||
|
||||
/mob/proc/pl_effects()
|
||||
|
||||
/mob/living/carbon/human/pl_effects()
|
||||
//Handles all the bad things plasma can do.
|
||||
|
||||
//Contamination
|
||||
if(vsc.plc.CLOTH_CONTAMINATION) contaminate()
|
||||
|
||||
//Anything else requires them to not be dead.
|
||||
if(stat >= 2)
|
||||
return
|
||||
|
||||
//Burn skin if exposed.
|
||||
if(vsc.plc.SKIN_BURNS)
|
||||
if(!pl_head_protected() || !pl_suit_protected())
|
||||
burn_skin(0.75)
|
||||
if(prob(20)) src << "\red Your skin burns!"
|
||||
updatehealth()
|
||||
|
||||
//Burn eyes if exposed.
|
||||
if(vsc.plc.EYE_BURNS)
|
||||
if(!head)
|
||||
if(!wear_mask)
|
||||
@@ -136,13 +80,14 @@ obj/item/proc
|
||||
if(!(wear_mask.flags & MASKCOVERSEYES))
|
||||
burn_eyes()
|
||||
else
|
||||
if(!(head.flags & MASKCOVERSEYES))
|
||||
if(!(head.flags & HEADCOVERSEYES))
|
||||
if(!wear_mask)
|
||||
burn_eyes()
|
||||
else
|
||||
if(!(wear_mask.flags & MASKCOVERSEYES))
|
||||
burn_eyes()
|
||||
|
||||
//Genetic Corruption
|
||||
if(vsc.plc.GENETIC_CORRUPTION)
|
||||
if(rand(1,10000) < vsc.plc.GENETIC_CORRUPTION)
|
||||
randmutb(src)
|
||||
@@ -150,6 +95,7 @@ obj/item/proc
|
||||
domutcheck(src,null)
|
||||
|
||||
/mob/living/carbon/human/proc/burn_eyes()
|
||||
//The proc that handles eye burning.
|
||||
if(prob(20)) src << "\red Your eyes burn!"
|
||||
eye_stat += 2.5
|
||||
eye_blurry = min(eye_blurry+1.5,50)
|
||||
@@ -159,6 +105,7 @@ obj/item/proc
|
||||
eye_stat = 0
|
||||
|
||||
/mob/living/carbon/human/proc/pl_head_protected()
|
||||
//Checks if the head is adequately sealed.
|
||||
if(head)
|
||||
if(vsc.plc.PLASMAGUARD_ONLY)
|
||||
if(head.flags & PLASMAGUARD || head.flags & HEADSPACE) return 1
|
||||
@@ -167,6 +114,7 @@ obj/item/proc
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/pl_suit_protected()
|
||||
//Checks if the suit is adequately sealed.
|
||||
if(wear_suit)
|
||||
if(vsc.plc.PLASMAGUARD_ONLY)
|
||||
if(wear_suit.flags & PLASMAGUARD || wear_suit.flags & SUITSPACE) return 1
|
||||
@@ -175,6 +123,7 @@ obj/item/proc
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/suit_contamination()
|
||||
//Runs over the things that can be contaminated and does so.
|
||||
if(w_uniform) w_uniform.contaminate()
|
||||
if(shoes) shoes.contaminate()
|
||||
if(gloves) gloves.contaminate()
|
||||
@@ -182,6 +131,7 @@ obj/item/proc
|
||||
|
||||
turf/Entered(obj/item/I)
|
||||
. = ..()
|
||||
//Items that are in plasma, but not on a mob, can still be contaminated.
|
||||
if(istype(I) && vsc.plc.CLOTH_CONTAMINATION)
|
||||
var/datum/gas_mixture/env = return_air(1)
|
||||
if(env.toxins > MOLES_PLASMA_VISIBLE + 1)
|
||||
|
||||
@@ -2,19 +2,26 @@
|
||||
var/explosion_halt = 0
|
||||
zone
|
||||
proc/process()
|
||||
//Does rebuilding stuff. Not sure if used.
|
||||
if(rebuild)
|
||||
//Deletes zone if empty.
|
||||
if(!contents.len)
|
||||
del src
|
||||
return 0
|
||||
|
||||
//Choose a random turf and regenerate the zone from it.
|
||||
var
|
||||
turf/sample = pick(contents)
|
||||
list/new_contents = FloodFill(sample)
|
||||
problem = 0
|
||||
|
||||
//If something isn't carried over, there was a complication.
|
||||
for(var/turf/T in contents)
|
||||
if(!(T in new_contents))
|
||||
problem = 1
|
||||
|
||||
if(problem)
|
||||
//Build some new zones for stuff that wasn't included.
|
||||
var/list/rebuild_turfs = list()
|
||||
for(var/turf/T in contents - new_contents)
|
||||
contents -= T
|
||||
@@ -26,11 +33,13 @@ zone
|
||||
Z.air.copy_from(air)
|
||||
rebuild = 0
|
||||
|
||||
//Sometimes explosions will cause the air to be deleted for some reason.
|
||||
if(!air)
|
||||
air = new()
|
||||
air.adjustGases(MOLES_O2STANDARD, 0, MOLES_N2STANDARD, 0, list())
|
||||
world.log << "Air object lost in zone. Regenerating."
|
||||
|
||||
//Counting up space.
|
||||
var/total_space = 0
|
||||
|
||||
if(space_tiles)
|
||||
@@ -38,44 +47,60 @@ zone
|
||||
if(!istype(T,/turf/space)) space_tiles -= T
|
||||
total_space = length(space_tiles)
|
||||
|
||||
if(total_space) // SPAAAAAAAAAACE
|
||||
//var/old_pressure = air.pressure
|
||||
//Add checks to ensure that we're not sucking air out of an empty room.
|
||||
if(total_space && air.total_moles > 0.1 && air.temperature > TCMB+0.5)
|
||||
//If there is space, air should flow out of the zone.
|
||||
ShareSpace(air,total_space*(vsc.zone_share_percent/100))
|
||||
//var/p_diff = old_pressure - air.pressure
|
||||
//if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) AirflowSpace(src,p_diff)
|
||||
|
||||
//React the air here.
|
||||
air.react(null,0)
|
||||
|
||||
//Check the graphic.
|
||||
var/check = air.check_tile_graphic()
|
||||
|
||||
//Only run through the individual turfs if there's reason to.
|
||||
if(check || air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
|
||||
|
||||
for(var/turf/simulated/S in contents)
|
||||
//Update overlays.
|
||||
if(check)
|
||||
if(S.HasDoor(1))
|
||||
S.update_visuals()
|
||||
else
|
||||
S.update_visuals(air)
|
||||
|
||||
//Expose stuff to extreme heat.
|
||||
if(air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
|
||||
for(var/atom/movable/item in S)
|
||||
item.temperature_expose(air, air.temperature, CELL_VOLUME)
|
||||
S.temperature_expose(air, air.temperature, CELL_VOLUME)
|
||||
|
||||
//Archive graphic so we can know if it's different.
|
||||
air.graphic_archived = air.graphic
|
||||
|
||||
//Ensure temperature does not reach absolute zero.
|
||||
air.temperature = max(TCMB,air.temperature)
|
||||
|
||||
//Handle connections to other zones.
|
||||
if(length(connections))
|
||||
for(var/connection/C in connections)
|
||||
//Check if the connection is valid first.
|
||||
C.Cleanup()
|
||||
//Do merging if conditions are met. Specifically, if there's a non-door connection
|
||||
//to somewhere with space, the zones are merged regardless of equilibrium, to speed
|
||||
//up spacing in areas with double-plated windows.
|
||||
if(C && !C.indirect && C.A.zone && C.B.zone)
|
||||
if(C.A.zone.air.compare(C.B.zone.air) || total_space)
|
||||
ZMerge(C.A.zone,C.B.zone)
|
||||
|
||||
//Share some
|
||||
for(var/zone/Z in connected_zones)
|
||||
//var/p_diff = (air.return_pressure()-Z.air.return_pressure())*connected_zones[Z]*(vsc.zone_share_percent/100)
|
||||
//if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) Airflow(src,Z,p_diff)
|
||||
ShareRatio(air,Z.air,connected_zones[Z]*(vsc.zone_share_percent/100))
|
||||
//Ensure we're not doing pointless calculations on equilibrium zones.
|
||||
if(abs(air.total_moles - Z.air.total_moles) > 0.1 || abs(air.temperature - Z.air.temperature) > 0.1)
|
||||
ShareRatio(air,Z.air,connected_zones[Z]*(vsc.zone_share_percent/100))
|
||||
|
||||
proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, ratio)
|
||||
//Shares a specific ratio of gas between mixtures using simple weighted averages.
|
||||
var
|
||||
size = max(1,A.group_multiplier)
|
||||
share_size = max(1,B.group_multiplier)
|
||||
@@ -138,9 +163,8 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, ratio)
|
||||
if(A.compare(B)) return 1
|
||||
else return 0
|
||||
|
||||
/* See? Now that's how it's done. */
|
||||
|
||||
proc/ShareSpace(datum/gas_mixture/A, ratio)
|
||||
//A modified version of ShareRatio for spacing gas at the same rate as if it were going into a huge airless room.
|
||||
var
|
||||
size = max(1,A.group_multiplier)
|
||||
share_size = 2000 //A huge value because space is huge.
|
||||
@@ -179,6 +203,7 @@ proc/ShareSpace(datum/gas_mixture/A, ratio)
|
||||
|
||||
zone/proc
|
||||
connected_zones()
|
||||
//A legacy proc for getting connected zones.
|
||||
. = list()
|
||||
for(var/connection/C in connections)
|
||||
var/zone/Z
|
||||
|
||||
@@ -56,6 +56,17 @@ Stuff which is in development and not yet visible to players or just code relate
|
||||
should be listed in the changelog upon commit though. Thanks. -->
|
||||
|
||||
<!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here -->
|
||||
|
||||
<div class="commit sansserif">
|
||||
<h2 class="date">5/26/2012</h2>
|
||||
<h3 class="author">Aryn updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Airflow works on a room-by-room basis rather than on individual tiles. Rooms will depressurize much faster than they did, though not too fast for balance reasons.</li>
|
||||
<li class="tweak">Fire now works on a logarithmic scale based on oxygen and fuel content. This is a far more complex tweak under the hood than it is in game.</li>
|
||||
<li class="rscadd">Plasma now has increased toxicity and can burn exposed skin and eyes. In addition, because of the new air, it fills the room instantaneously. Try not to spill any.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="commit sansserif">
|
||||
<h2 class="date">26 May 2012</h2>
|
||||
<h3 class="author">Erthilo updated:</h3>
|
||||
|
||||
Reference in New Issue
Block a user