diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index 023d60acf0..31c3085f40 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -30,7 +30,7 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh) var/igniting = 0 var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in src - + if(air_contents.check_combustability(liquid)) igniting = 1 @@ -55,28 +55,87 @@ obj icon = 'fire.dmi' icon_state = "1" - layer = TURF_LAYER + layer = TURF_LAYER + 0.2 var firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel() process() . = 1 - + //get location and check if it is in a proper ZAS zone var/turf/simulated/floor/S = loc if(!S.zone) del src - + if(!istype(S)) 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 - + //get scorchmarks + var/obj/effect/decal/cleanable/scorchmark/scorch = locate() in S + + //check if it found a scorchmark and add one if there isnt one already + if (!scorch) + scorch = new/obj/effect/decal/cleanable/scorchmark(S,0) + + //try to burn the floor + //initialize the temperature needed for burning the floor + //initialize the fuel gained by burning this floor + //initialize the speed modifier for the floor to catch on fire + var/floor_target_temp = 0 + var/floor_fuel = 1 + var/floor_speed_modifier = 1 + if(S.is_plasteel_floor()) + floor_target_temp = 800 + else if (S.is_light_floor()) + floor_target_temp = 600 + else if (S.is_grass_floor()) + floor_target_temp = 500 + floor_fuel = 2 + floor_speed_modifier = 1.5 + else if (S.is_wood_floor()) + floor_target_temp = 500 + floor_fuel = 3 + floor_speed_modifier = 1.25 + else if (S.is_carpet_floor()) + floor_target_temp = 500 + floor_fuel = 3 + floor_speed_modifier = 1.5 + else + floor_target_temp = 1200 + floor_speed_modifier = 0.8 + + //check if the floor is burnable + if(floor_target_temp > 0) + //calculate a random factor for the equation + var/turf_burn_random = max( min(floor_speed_modifier * 5 * ( ( max(air_contents.temperature - floor_target_temp,0) / floor_target_temp )^2 ), 100), 0) + //check if the random check is passed + if (prob(turf_burn_random)) + //check if the tile has already been damaged once + if (S.burnt || S.broken) + //check if the tile is plating, if not break it and release some fuel, also some randomness to slow down the process + if (!S.is_plating() && prob(10)) + scorch.amount += floor_fuel + S.break_tile_to_plating() + + //damage it and release fuel + else + scorch.amount += floor_fuel + S.burn_tile() + + //now burn some items! + for(var/obj/o in loc) + if(o.fire_min_burn_temp) + var/obj_burn_random = max( min(o.fire_burn_multiplier * 5 * ( ( max(air_contents.temperature - o.fire_min_burn_temp,0) / o.fire_min_burn_temp )^2 ), 100), 0) + if(prob(obj_burn_random)) + scorch.amount += fire_fuel_worth + o.fire_burn() + //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) @@ -86,29 +145,29 @@ obj if(fuel) if(fuel.moles < 0.001) air_contents.trace_gases.Remove(fuel) - + //check if there is something to combust - if(!air_contents.check_combustability(liquid)) + if(!air_contents.check_combustability(liquid,scorch)) del src - + //get a firelevel and set the icon - firelevel = air_contents.calculate_firelevel(liquid) - - if(firelevel > 6) + firelevel = air_contents.calculate_firelevel(liquid,scorch) + + if(firelevel > 3) icon_state = "3" SetLuminosity(7) - else if(firelevel > 2.5) + else if(firelevel > 2) icon_state = "2" SetLuminosity(5) else icon_state = "1" SetLuminosity(3) - + //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! - + //spread! for(var/direction in cardinal) if(S.air_check_directions&direction) //Grab all valid bordering tiles @@ -118,7 +177,7 @@ obj 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) + if(prob( 100 * (1 - min( max( ( (world.time - 30) - enemy_tile.fire_protection ), 0 ) / 30, 1) ) ) ) firelevel -= 1.5 continue @@ -126,29 +185,29 @@ obj 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) - + //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 /////////////////////////////////////////////// - + if(flow) - if(flow.check_combustability(liquid)) + if(flow.check_combustability(liquid,scorch)) //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) - + //burn baby burn! - flow.zburn(liquid,1) - + flow.zburn(liquid,scorch,1) + //merge the air back S.assume_air(flow) ///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on ////////////////////////////////////////////////////////////////// - + New(newLoc,fl) ..() @@ -178,15 +237,15 @@ turf/simulated/apply_fire_protection() fire_protection = world.time -datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force_burn) +datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, obj/effect/decal/cleanable/scorchmark/scorch, force_burn) var/value = 0 - - if((temperature > PLASMA_MINIMUM_BURN_TEMPERATURE || force_burn) && check_combustability(liquid) ) - var/total_fuel = 0 + + if((temperature > PLASMA_MINIMUM_BURN_TEMPERATURE || force_burn) && check_combustability(liquid,scorch) ) + 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 @@ -198,8 +257,12 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force else total_fuel += liquid.amount + if(scorch) + //fuel created by destroying objects and turfs + total_fuel += scorch.amount + //Calculate the firelevel. - var/firelevel = calculate_firelevel(liquid) + var/firelevel = calculate_firelevel(liquid, scorch) //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 @@ -207,7 +270,7 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force //determine the amount of oxygen used var/total_oxygen = min(oxygen, 2 * total_fuel) - + //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 @@ -232,33 +295,39 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force liquid.amount -= liquid.amount * used_fuel_ratio * used_reactants_ratio if(liquid.amount <= 0) del liquid + if(scorch) + scorch.amount -= min(scorch.amount, scorch.amount * used_fuel_ratio * used_reactants_ratio) + //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() - + update_values() value = total_reactants * used_reactants_ratio return value -datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid) +datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid, obj/effect/decal/cleanable/scorchmark/scorch) //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 + + var/datum/gas/volatile_fuel/fuel = locate() in trace_gases var/value = 0 - + if(oxygen && (toxins || fuel || liquid)) value = 1 - + else if (scorch) + if (oxygen && scorch.amount > 0) + value = 1 + return value -datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid) +datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid, obj/effect/decal/cleanable/scorchmark/scorch) //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 var/total_fuel = 0 var/firelevel = 0 - + if(check_combustability(liquid)) - + total_fuel += toxins if(liquid) @@ -267,17 +336,20 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue if(fuel) total_fuel += fuel.moles + if(scorch) + total_fuel += scorch.amount + 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) @@ -323,6 +395,4 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue apply_damage(0.6*mx*legs_exposure, BURN, "l_leg", 0, 0, "Fire") 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() + apply_damage(0.4*mx*arms_exposure, BURN, "r_arm", 0, 0, "Fire") \ No newline at end of file diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 661f4c43b3..116136bfaf 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -80,7 +80,17 @@ var/name = t.fields["name"] var/rank = t.fields["rank"] var/real_rank = t.fields["real_rank"] - isactive[name] = t.fields["p_stat"] + + var/active = 0 + for(var/mob/M in player_list) if(M.name == name) + // For dead ones, have a chance to get their status wrong + if(M.stat == 2) + active = M.x % 2 // Should be good enough, avoids their status flipping constantly + break + else if(M.client && M.client.inactivity <= 10 * 60 * 10) + active = 1 + break + isactive[name] = active ? "Active" : "SSD" //world << "[name]: [rank]" diff --git a/code/game/objects/effects/decals/Cleanable/scorchmark.dm b/code/game/objects/effects/decals/Cleanable/scorchmark.dm new file mode 100644 index 0000000000..9274708d6e --- /dev/null +++ b/code/game/objects/effects/decals/Cleanable/scorchmark.dm @@ -0,0 +1,15 @@ +obj/effect/decal/cleanable/scorchmark + //this is used as an additional visual result of fire and as a reagent holder for fuel created by burning of turfs and items. + icon = 'icons/effects/scorchmark.dmi' + name = "Soot" + icon_state = "1" + layer = TURF_LAYER+0.1 + anchored = 1 + var/amount = 0 //starts always empty and is filled by procs called by fire + + New(newLoc,start_amount=0) + ..() + + icon_state = pick("1","2","3","4","5","6","7","8","9") + dir = pick(cardinal) + amount = start_amount \ No newline at end of file diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index d3e7144297..309d667553 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -39,25 +39,25 @@ would spawn and follow the beaker, even if it is carried or thrown. /obj/effect/effect/water/New() ..() - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX + var/turf/simulated/floor/T = src.loc + if (istype(T, /turf/simulated/floor)) + T.fire_protection = world.time spawn( 70 ) delete() return return /obj/effect/effect/water/Del() - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX + var/turf/simulated/floor/T = src.loc + if (istype(T, /turf/simulated/floor)) + T.fire_protection = world.time ..() return /obj/effect/effect/water/Move(turf/newloc) - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX + var/turf/simulated/floor/T = src.loc + if (istype(T, /turf/simulated/floor)) + T.fire_protection = world.time if (--src.life < 1) //SN src = null delete() diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 3671b6ce08..7718ea2c11 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -103,6 +103,9 @@ var/global/list/datum/stack_recipe/uranium_recipes = list ( \ origin_tech = "plasmatech=2;materials=2" perunit = 2000 sheettype = "plasma" + fire_min_burn_temp = 500 + fire_burn_multiplier = 3 //made of burnium + fire_fuel_worth = 0 var/global/list/datum/stack_recipe/plasma_recipes = list ( \ new/datum/stack_recipe("plasma door", /obj/structure/mineral_door/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \ @@ -114,6 +117,18 @@ var/global/list/datum/stack_recipe/plasma_recipes = list ( \ pixel_y = rand(0,4)-4 ..() +/obj/item/stack/sheet/mineral/plasma/fire_burn() + //get location and check if it is in a proper ZAS zone + var/turf/simulated/floor/S = loc + if(S.zone) + var/datum/gas_mixture/air_contents = S.return_air() + if(air_contents) + air_contents.toxins += 20 + air_contents.update_values() + amount -= 1 + if(amount <= 0) + del src + /obj/item/stack/sheet/mineral/plastic name = "Plastic" icon_state = "sheet-plastic" @@ -124,6 +139,7 @@ var/global/list/datum/stack_recipe/plasma_recipes = list ( \ throw_range = 3 origin_tech = "materials=3" perunit = 2000 + sheettype = "plastic" var/global/list/datum/stack_recipe/plastic_recipes = list ( \ new/datum/stack_recipe("plastic crate", /obj/structure/closet/pcrate, 10, one_per_turf = 1, on_floor = 1), \ diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index 472e28852f..89078970f3 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -20,6 +20,10 @@ var/construction_cost = list("metal"=750,"glass"=75) var/construction_time=100 + fire_min_burn_temp = 1000 + fire_burn_multiplier = 0.75 + fire_fuel_worth = 0 + suicide_act(mob/user) viewers(user) << "\red [user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide." return (FIRELOSS) @@ -111,4 +115,12 @@ maxcharge = 10000 maxcharge = 10000 m_amt = 0 - g_amt = 0 \ No newline at end of file + g_amt = 0 + +/obj/item/weapon/cell/fire_burn() + viewers(src) << "\red Charge: [src.charge]" + var/radius = round( (sqrt(charge)/30)+0.5, 1 ) + viewers(src) << "\red Radius: [radius]" + if (radius >= 1) + explosion(src.loc,0,0,radius) + ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 143ff13a04..ea3f42247d 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -16,6 +16,11 @@ var/integrity = 3 var/volume = 70 + m_amt = 3750 + fire_min_burn_temp = 800 + fire_burn_multiplier = 0.75 + fire_fuel_worth = 0 + /obj/item/weapon/tank/New() ..() @@ -261,4 +266,11 @@ integrity-- else if(integrity < 3) - integrity++ \ No newline at end of file + integrity++ + +/obj/item/weapon/tank/fire_burn() + //get location and check if it is in a proper ZAS zone + var/turf/simulated/floor/S = loc + if(S.zone) + S.assume_air(air_contents) + ..() \ No newline at end of file diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 762888a4b4..6e421c9443 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -76,11 +76,19 @@ icon_state = "wooden_chair" name = "wooden chair" desc = "Old is never too old to not be in fashion." + fire_min_burn_temp = 500 + fire_burn_multiplier = 1.25 + fire_fuel_worth = 5 + m_amt = 0 /obj/structure/stool/bed/chair/wood/wings icon_state = "wooden_chair_wings" name = "wooden chair" desc = "Old is never too old to not be in fashion." + fire_min_burn_temp = 500 + fire_burn_multiplier = 1.25 + fire_fuel_worth = 5 + m_amt = 0 /obj/structure/stool/bed/chair/wood/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/wrench)) @@ -93,6 +101,9 @@ /obj/structure/stool/bed/chair/comfy name = "comfy chair" desc = "It looks comfy." + fire_min_burn_temp = 500 + fire_burn_multiplier = 1.25 + fire_fuel_worth = 4 /obj/structure/stool/bed/chair/comfy/brown icon_state = "comfychair_brown" diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm index ab7a55e1da..fcd404f165 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -6,6 +6,10 @@ anchored = 1.0 flags = FPRINT pressure_resistance = 15 + m_amt = 3750 + fire_min_burn_temp = 600 + fire_burn_multiplier = 1 + fire_fuel_worth = 2 /obj/structure/stool/ex_act(severity) switch(severity) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 2879122972..55a00acfdc 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -373,8 +373,9 @@ return /obj/structure/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 800) - hit(round(exposed_volume / 100), 0) + //Since glasslocks are the only thing you can do to prevent spreading atmos issues, this was disabled for the time being + //if(exposed_temperature > T0C + 800) + // hit(round(exposed_volume / 100), 0) ..() diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 93cb235649..4762b3212f 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -1,5 +1,3 @@ - - /obj/structure/reagent_dispensers name = "Dispenser" desc = "..." @@ -66,12 +64,6 @@ new /obj/effect/effect/water(src.loc) del(src) - - - - - - //Dispensers /obj/structure/reagent_dispensers/watertank name = "watertank" @@ -79,10 +71,39 @@ icon = 'icons/obj/objects.dmi' icon_state = "watertank" amount_per_transfer_from_this = 10 + + m_amt = 7500 + g_amt = 3750 + fire_min_burn_temp = 800 + fire_burn_multiplier = 0.75 + fire_fuel_worth = 0 + New() ..() reagents.add_reagent("water",1000) +/obj/structure/reagent_dispensers/watertank/fire_burn() + src.reagents.update_total() + var/number_of_gusts = src.reagents.total_volume / 50 + for(var/a=0, a < number_of_gusts , a++) + var/obj/effect/effect/water/W = new /obj/effect/effect/water( get_turf(src) ) + var/turf/my_target = get_step(get_step(get_step(get_step(get_step(get_turf(src),pick(cardinal)),pick(cardinal)),pick(cardinal)),pick(cardinal)),pick(cardinal)) + var/datum/reagents/R = new/datum/reagents(50) + if(!W) return + W.reagents = R + R.my_atom = W + if(!W || !src) return + src.reagents.trans_to(W,50) + for(var/b=0, b<5, b++) + step_towards(W,my_target) + if(!W) return + W.reagents.reaction(get_turf(W)) + for(var/atom/atm in get_turf(W)) + if(!W) return + W.reagents.reaction(atm) + if(W.loc == my_target) break + ..() + /obj/structure/reagent_dispensers/fueltank name = "fueltank" desc = "A fueltank" @@ -91,6 +112,13 @@ amount_per_transfer_from_this = 10 var/modded = 0 var/obj/item/device/assembly_holder/rig = null + + m_amt = 7500 + g_amt = 3750 + fire_min_burn_temp = 800 + fire_burn_multiplier = 1 + fire_fuel_worth = 0 + New() ..() reagents.add_reagent("fuel",1000) @@ -164,6 +192,11 @@ if(src) del(src) +/obj/structure/reagent_dispensers/fueltank/fire_burn() + src.reagents.update_total() + new/obj/effect/decal/cleanable/liquid_fuel(src.loc, src.reagents.total_volume) + ..() + /obj/structure/reagent_dispensers/peppertank name = "Pepper Spray Refiller" desc = "Refill pepper spray canisters." @@ -214,4 +247,4 @@ New() ..() - reagents.add_reagent("virusfood", 1000) + reagents.add_reagent("virusfood", 1000) diff --git a/html/changelog.html b/html/changelog.html index 4fdd862029..9e59bcd6e9 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -40,7 +40,7 @@ Header Section