VG ZAS Fire stolen

This commit is contained in:
Chinsky
2013-11-03 20:28:26 +04:00
parent a7be4d9353
commit 8274114e47
2 changed files with 230 additions and 177 deletions

View File

@@ -11,8 +11,6 @@ Attach to transfer valve and open. BOOM.
*/
//Some legacy definitions so fires can be started.
atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return null
@@ -21,160 +19,164 @@ atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed
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)
if(!air_contents)
if(fire_protection > world.time-300)
return 0
/*if(active_hotspot)
if(soh)
if(air_contents.toxins > 0.5 && air_contents.oxygen > 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
if(locate(/obj/fire) in src)
return 1
var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
var/datum/gas_mixture/air_contents = return_air()
if(!air_contents || exposed_temperature < PLASMA_MINIMUM_BURN_TEMPERATURE)
return 0
var/igniting = 0
var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in src
if(air_contents.calculate_firelevel(liquid) > vsc.IgnitionLevel && (fuel || liquid || air_contents.toxins > 0.5))
if(air_contents.check_combustability(liquid))
igniting = 1
if(air_contents.oxygen < 0.5)
return 0
if(! (locate(/obj/fire) in src))
var/obj/fire/F = new(src,1000)
F.temperature = exposed_temperature
F.volume = CELL_VOLUME
//active_hotspot.just_spawned = (current_cycle < air_master.current_cycle)
//remove just_spawned protection if no longer processing this cell
new /obj/fire(src,1000)
return igniting
obj
fire
//Icon for fire on turfs.
/obj/fire
//Icon for fire on turfs.
anchored = 1
mouse_opacity = 0
anchored = 1
mouse_opacity = 0
//luminosity = 3
//luminosity = 3
icon = 'icons/effects/fire.dmi'
icon = 'icons/effects/fire.dmi'
icon_state = "1"
layer = TURF_LAYER
var/firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
/obj/fire/process()
. = 1
//get location and check if it is in a proper ZAS zone
var/turf/simulated/S = loc
if(!istype(S))
del src
if(!S.zone)
del src
var/datum/gas_mixture/air_contents = S.return_air()
//get liquid fuels on the ground.
var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S
//and the volatile stuff from the air
var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
//since the air is processed in fractions, we need to make sure not to have any minuscle residue or
//the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour
if(air_contents.oxygen < 0.001)
air_contents.oxygen = 0
if(air_contents.toxins < 0.001)
air_contents.toxins = 0
if(fuel)
if(fuel.moles < 0.001)
air_contents.trace_gases.Remove(fuel)
//check if there is something to combust
if(!air_contents.check_recombustability(liquid))
//del src
RemoveFire()
//get a firelevel and set the icon
firelevel = air_contents.calculate_firelevel(liquid)
if(firelevel > 6)
icon_state = "3"
SetLuminosity(7)
else if(firelevel > 2.5)
icon_state = "2"
SetLuminosity(5)
else
icon_state = "1"
SetLuminosity(3)
var
volume = CELL_VOLUME
temperature = PLASMA_MINIMUM_BURN_TEMPERATURE
firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
archived_firelevel = 0
//im not sure how to implement a version that works for every creature so for now monkeys are firesafe
for(var/mob/living/carbon/human/M in loc)
M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans!
for(var/atom/A in loc)
A.fire_act(air_contents, air_contents.temperature, air_contents.return_volume())
//spread
for(var/direction in cardinal)
if(S.air_check_directions&direction) //Grab all valid bordering tiles
process()
. = 1
var/turf/simulated/enemy_tile = get_step(S, direction)
if(firelevel > vsc.IgnitionLevel)
if(istype(enemy_tile))
var/datum/gas_mixture/acs = enemy_tile.return_air()
var/obj/effect/decal/cleanable/liquid_fuel/liq = locate() in enemy_tile
if(!acs) continue
if(!acs.check_recombustability(liq)) continue
//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 -= 1.5
continue
var/turf/simulated/floor/S = loc
if(!S.zone) del src //Cannot exist where zones are broken.
//Spread the fire.
if(!(locate(/obj/fire) in enemy_tile))
if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0))
new/obj/fire(enemy_tile,firelevel)
if(istype(S))
var
datum/gas_mixture/air_contents = S.return_air()
//Get whatever trace fuels are in the area
datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
//Also get liquid fuels on the ground.
obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S
//seperate part of the present gas
//this is done to prevent the fire burning all gases in a single pass
var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate)
///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR ///////////////////////////////////////////////
var/datum/gas_mixture/flow = air_contents.remove_ratio(0.25)
//The reason we're taking a part of the air instead of all of it is so that it doesn't jump to
//the fire's max temperature instantaneously.
if(flow)
firelevel = air_contents.calculate_firelevel(liquid)
if(flow.check_recombustability(liquid))
//Ensure flow temperature is higher than minimum fire temperatures.
//this creates some energy ex nihilo but is necessary to get a fire started
//lets just pretend this energy comes from the ignition source and dont mention this again
//flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature)
//Ensure that there is an appropriate amount of fuel and O2 here.
if(firelevel > 0.25 && flow.oxygen > 0.3 && (air_contents.toxins || fuel || liquid))
//burn baby burn!
for(var/direction in cardinal)
if(S.air_check_directions&direction) //Grab all valid bordering tiles
flow.zburn(liquid,1)
//merge the air back
S.assume_air(flow)
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 -= 1.5
continue
//Spread the fire.
if(!(locate(/obj/fire) in enemy_tile))
if( prob( firelevel*10 ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0))
new/obj/fire(enemy_tile,firelevel)
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.
if(firelevel > 6)
icon_state = "3"
else if(firelevel > 2.5)
icon_state = "2"
else
icon_state = "1"
//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)
if(fuel && fuel.moles <= 0.00001)
del fuel
else
del src
///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on //////////////////////////////////////////////////////////////////
S.assume_air(flow) //Then put it back where you found it.
/obj/fire/New(newLoc,fl)
..()
else
del src
else
del src
else
del src
if(!istype(loc, /turf))
del src
dir = pick(cardinal)
SetLuminosity(3)
firelevel = fl
air_master.active_hotspots.Add(src)
for(var/mob/living/carbon/human/M in loc)
M.FireBurn(temperature, min(max(0.1,firelevel / 20),10)) //Burn the humans!
/obj/fire/Del()
if (istype(loc, /turf/simulated))
SetLuminosity(0)
loc = null
air_master.active_hotspots.Remove(src)
New(newLoc,fl)
..()
..()
if(!istype(loc, /turf))
del src
/obj/fire/proc/RemoveFire()
if (istype(loc, /turf/simulated))
SetLuminosity(0)
loc = null
air_master.active_hotspots.Remove(src)
dir = pick(cardinal)
//sd_SetLuminosity(3,2,0)
firelevel = fl
air_master.active_hotspots.Add(src)
Del()
if (istype(loc, /turf/simulated))
//sd_SetLuminosity(0)
loc = null
air_master.active_hotspots.Remove(src)
..()
turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
@@ -182,22 +184,19 @@ turf/proc/apply_fire_protection()
turf/simulated/apply_fire_protection()
fire_protection = world.time
datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/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_FLASHPOINT && !reacting)
reacting = 1
datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, force_burn)
var/value = 0
if(temperature > PLASMA_MINIMUM_BURN_TEMPERATURE && reacting)
var
total_fuel = toxins
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((temperature > PLASMA_MINIMUM_BURN_TEMPERATURE || force_burn) && check_recombustability(liquid))
var/total_fuel = 0
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
total_fuel += toxins
if(fuel)
//Volatile Fuel
total_fuel += fuel.moles
fuel_sources++
if(liquid)
//Liquid Fuel
@@ -205,72 +204,126 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid)
del liquid
else
total_fuel += liquid.amount
fuel_sources++
//Toxins
if(toxins > 0.3) fuel_sources++
//Calculate the firelevel.
var/firelevel = calculate_firelevel(liquid)
if(!fuel_sources) return 0 //If there's no fuel, there's no burn. Can't divide by zero anyway.
//get the current inner energy of the gas mix
//this must be taken here to prevent the addition or deletion of energy by a changing heat capacity
var/starting_energy = temperature * heat_capacity()
if(oxygen > 0.3)
//determine the amount of oxygen used
var/total_oxygen = min(oxygen, 2 * total_fuel)
//Calculate the firelevel.
var/firelevel = calculate_firelevel(liquid)
//determine the amount of fuel actually used
var/used_fuel_ratio = min(oxygen / 2 , total_fuel) / total_fuel
total_fuel = total_fuel * used_fuel_ratio
//Reaches a maximum practical temperature of around 4500.
var/total_reactants = total_fuel + total_oxygen
//Increase temperature.
temperature = max( 1700*log(0.4*firelevel + 1.23) , temperature )
//determine the amount of reactants actually reacting
var/used_reactants_ratio = min( max(total_reactants * firelevel / vsc.fire_firelevel_multiplier, 0.2), total_reactants) / total_reactants
//Consume some gas.
var/consumed_gas = min(oxygen,0.05*firelevel,total_fuel) / fuel_sources
//remove and add gasses as calculated
oxygen -= min(oxygen, total_oxygen * used_reactants_ratio )
oxygen = max(0,oxygen-consumed_gas)
toxins -= min(toxins, (toxins * used_fuel_ratio * used_reactants_ratio ) * 3)
if(toxins < 0)
toxins = 0
toxins = max(0,toxins-consumed_gas)
carbon_dioxide += max(2 * total_fuel, 0)
carbon_dioxide += consumed_gas*2
if(fuel)
fuel.moles -= (fuel.moles * used_fuel_ratio * used_reactants_ratio) * 5 //Fuel burns 5 times as quick
if(fuel.moles <= 0) del fuel
if(fuel)
fuel.moles -= consumed_gas
if(fuel.moles <= 0) del fuel
if(liquid)
liquid.amount -= (liquid.amount * used_fuel_ratio * used_reactants_ratio) * 5 // liquid fuel burns 5 times as quick
if(liquid)
liquid.amount -= consumed_gas
if(liquid.amount <= 0) del liquid
if(liquid.amount <= 0) del liquid
update_values()
return consumed_gas*fuel_sources
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * total_fuel) / heat_capacity()
else
reacting = 0
update_values()
value = total_reactants * used_reactants_ratio
return value
datum/gas_mixture/proc/check_recombustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
//this is a copy proc to continue a fire after its been started.
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
if(oxygen && (toxins || fuel || liquid))
if(liquid)
return 1
if (toxins)
return 1
if(fuel)
return 1
return 0
datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
//this check comes up very often and is thus centralized here to ease adding stuff
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
if(oxygen && (toxins || fuel || liquid))
if(liquid)
return 1
if (toxins >= 0.7)
return 1
if(fuel && fuel.moles >= 1.4)
return 1
return 0
datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/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
liquid_concentration = 0
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
oxy_concentration = oxygen / volume
tox_concentration = toxins / volume
fuel_concentration = 0
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
var/total_fuel = 0
var/firelevel = 0
if(fuel) fuel_concentration = (fuel.moles) / volume
if(liquid) liquid_concentration = (liquid.amount*15) / volume
return (oxy_concentration + tox_concentration + liquid_concentration + fuel_concentration)*100
if(check_recombustability(liquid))
/mob/living/carbon/human/proc/FireBurn(last_temperature, mx as num)
total_fuel += toxins
if(liquid)
total_fuel += liquid.amount
if(fuel)
total_fuel += fuel.moles
var/total_combustables = (total_fuel + oxygen)
if(total_fuel > 0 && oxygen > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = total_combustables / (total_combustables + nitrogen + carbon_dioxide)
//calculates how close the mixture of the reactants is to the optimum
var/mix_multiplier = 1 / (1 + (5 * ((oxygen / total_combustables) ^2)))
//toss everything together
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
return max( 0, firelevel)
/mob/living/proc/FireBurn(var/firelevel, var/last_temperature, var/pressure)
var/mx = 5 * firelevel/vsc.fire_firelevel_multiplier * min(pressure / ONE_ATMOSPHERE, 1)
apply_damage(2.5*mx, BURN)
/mob/living/carbon/human/FireBurn(var/firelevel, var/last_temperature, var/pressure)
//Burns mobs due to fire. Respects heat transfer coefficients on various body parts.
//Due to TG reworking how fireprotection works, this is kinda less meaningful.
var
head_exposure = 1
chest_exposure = 1
groin_exposure = 1
legs_exposure = 1
arms_exposure = 1
var/head_exposure = 1
var/chest_exposure = 1
var/groin_exposure = 1
var/legs_exposure = 1
var/arms_exposure = 1
//Get heat transfer coefficients for clothing.
@@ -289,6 +342,8 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue
legs_exposure = 0
if(C.body_parts_covered & ARMS)
arms_exposure = 0
//minimize this for low-pressure enviroments
var/mx = 5 * firelevel/vsc.fire_firelevel_multiplier * min(pressure / ONE_ATMOSPHERE, 1)
//Always check these damage procs first if fire damage isn't working. They're probably what's wrong.
@@ -299,5 +354,3 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue
apply_damage(0.6*mx*legs_exposure, BURN, "r_leg", 0, 0, "Fire")
apply_damage(0.4*mx*arms_exposure, BURN, "l_arm", 0, 0, "Fire")
apply_damage(0.4*mx*arms_exposure, BURN, "r_arm", 0, 0, "Fire")
//flash_pain()

View File

@@ -1,7 +1,7 @@
var/global/vs_control/vsc = new
/vs_control
/* var/fire_consuption_rate = 0.25
var/fire_consuption_rate = 0.25
var/fire_consuption_rate_NAME = "Fire - Air Consumption Ratio"
var/fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick."
@@ -12,7 +12,7 @@ var/global/vs_control/vsc = new
var/fire_fuel_energy_release = 397000
var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
*/
var/IgnitionLevel = 0.5
var/IgnitionLevel_DESC = "Determines point at which fire can ignite"