|
| 1 | +/// How many joules of energy from reactions required to cause 1 damage |
| 2 | +#define JOULES_PER_DAMAGE 100000 |
| 3 | + |
1 | 4 | /obj/item/flamethrower |
2 | 5 | name = "flamethrower" |
3 | 6 | desc = "You are a firestarter!" |
|
54 | 57 | if(M.is_holding(src)) |
55 | 58 | location = M.loc |
56 | 59 | if(isturf(location)) //start a fire if possible |
57 | | - igniter.flamethrower_process(location) |
| 60 | + open_flame(igniter.heat) |
58 | 61 |
|
59 | 62 |
|
60 | 63 | /obj/item/flamethrower/update_overlays() |
|
199 | 202 | if(!istype(target)) |
200 | 203 | return FALSE |
201 | 204 |
|
202 | | - var/ratio_removed = 1 |
203 | | - if(!release_all) |
204 | | - ratio_removed = min(ptank.distribute_pressure, ptank.air_contents.return_pressure()) / ptank.air_contents.return_pressure() |
| 205 | + var/ratio_removed = min(ptank.distribute_pressure, ptank.air_contents.return_pressure()) / ptank.air_contents.return_pressure() |
| 206 | + |
205 | 207 | var/datum/gas_mixture/fuel_mix = ptank.air_contents.remove_ratio(ratio_removed) |
| 208 | + var/datum/gas_mixture/turf_mix = target.return_air() |
| 209 | + |
| 210 | + fuel_mix.merge(turf_mix.copy()) // copy air from the turf to do reactions with |
| 211 | + fuel_mix.set_temperature(igniter.heat) // heat the contents |
| 212 | + |
| 213 | + var/old_thermal_energy = fuel_mix.thermal_energy() |
| 214 | + for(var/i in 1 to 10) // react a bunch of times on the target turf |
| 215 | + if(!fuel_mix.react(target)) |
| 216 | + break // break the loop if it stops reacting |
206 | 217 |
|
207 | | - // Return of the stimball flamethrower, wear radiation protection when using this or you're just as likely to die as your target |
208 | | - if(fuel_mix.get_moles(GAS_PLASMA) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(GAS_NITRIUM) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(GAS_PLUOXIUM) >= NITRO_BALL_MOLES_REQUIRED) |
209 | | - var/balls_shot = round(min(fuel_mix.get_moles(GAS_NITRIUM), fuel_mix.get_moles(GAS_PLUOXIUM), NITRO_BALL_MAX_REACT_RATE / NITRO_BALL_MOLES_REQUIRED)) |
210 | | - var/angular_increment = 360/balls_shot |
211 | | - var/random_starting_angle = rand(0,360) |
212 | | - for(var/i in 1 to balls_shot) |
213 | | - target.fire_nuclear_particle((i*angular_increment+random_starting_angle)) |
214 | | - fuel_mix.adjust_moles(GAS_PLASMA, -balls_shot * NITRO_BALL_MOLES_REQUIRED) // No free extra damage for you, conservation of mass go brrrrr |
215 | | - |
216 | | - // Funny rad flamethrower go brrr |
217 | | - if(fuel_mix.get_moles(GAS_TRITIUM)) // Tritium fires cause a bit of radiation |
218 | | - radiation_pulse(target, min(fuel_mix.get_moles(GAS_TRITIUM), fuel_mix.get_moles(GAS_O2)/2) * FIRE_HYDROGEN_ENERGY_RELEASED / TRITIUM_BURN_RADIOACTIVITY_FACTOR) |
219 | | - |
220 | | - // 8 damage at 0.5 mole transfer or ~17 kPa release pressure |
221 | | - // 16 damage at 1 mole transfer or ~35 kPa release pressure |
222 | | - var/damage = fuel_mix.get_moles(GAS_PLASMA) * 16 |
223 | | - // harder to achieve than plasma |
224 | | - damage += fuel_mix.get_moles(GAS_TRITIUM) * 24 // Lower damage than hydrogen, causes minor radiation |
225 | | - damage += fuel_mix.get_moles(GAS_H2) * 32 |
226 | | - // Maximum damage restricted by the available oxygen, with a hard cap at 16 |
227 | | - var/datum/gas_mixture/turf_air = target.return_air() |
228 | | - damage = min(damage, turf_air.get_moles(GAS_O2) + fuel_mix.get_moles(GAS_O2), max_damage) // capped by combined oxygen in the fuel mix and enviroment |
| 218 | + // damage is based on the positive or negative energy of the reaction, with a cap |
| 219 | + var/damage = min(abs(fuel_mix.thermal_energy() - old_thermal_energy) / JOULES_PER_DAMAGE, max_damage) |
229 | 220 |
|
230 | 221 | // If there's not enough fuel and/or oxygen to do more than 1 damage, shut itself off |
231 | 222 | if(damage < 1) |
|
251 | 242 | for(var/turf/T in turflist) |
252 | 243 | if(T == previousturf) |
253 | 244 | continue //so we don't burn the tile we be standin on |
254 | | - for(var/obj/structure/blob/B in T) |
| 245 | + var/cached_damage = 0 |
| 246 | + |
| 247 | + for(var/obj/structure/blob/blob in T) |
255 | 248 | // This is run before atmos checks because blob can be atmos blocking but we still want to hit them |
256 | 249 | // See /proc/default_ignite |
257 | | - var/damage = process_fuel(T) |
258 | | - if(!damage) |
259 | | - break // Out of gas, stop running pointlessly |
260 | | - B.take_damage(damage * 2, BURN, FIRE) // strong against blobs |
| 250 | + if(!cached_damage) |
| 251 | + cached_damage = process_fuel(T) |
| 252 | + if(!lit) |
| 253 | + break // stopped running, don't continue |
| 254 | + if(QDELETED(blob)) |
| 255 | + continue |
| 256 | + blob.take_damage(cached_damage * 2, BURN, FIRE) // strong against blobs |
| 257 | + |
| 258 | + for(var/obj/structure/spacevine/vine in T) |
| 259 | + // This is run before atmos checks because vines can be on top of a window or some other atmos-blocking structure |
| 260 | + if(!cached_damage) |
| 261 | + cached_damage = process_fuel(T) |
| 262 | + if(!lit) |
| 263 | + break // stopped running, don't continue |
| 264 | + if(QDELETED(vine)) |
| 265 | + continue |
| 266 | + vine.take_damage(cached_damage * 3, BURN, FIRE, TRUE) // very strong against vines |
| 267 | + |
261 | 268 | var/list/turfs_sharing_with_prev = previousturf.GetAtmosAdjacentTurfs(alldir=1) |
262 | 269 | if(!(T in turfs_sharing_with_prev)) |
263 | 270 | break // Hit something that blocks atmos |
264 | | - if(igniter) |
265 | | - if(!igniter.ignite_turf(src,T)) |
266 | | - break // Out of gas, stop running pointlessly |
267 | | - else |
268 | | - if(!default_ignite(T)) |
269 | | - break // Out of gas, stop running pointlessly |
| 271 | + |
| 272 | + if(!cached_damage) |
| 273 | + cached_damage = process_fuel(T) |
| 274 | + if(!lit) |
| 275 | + break // stopped running, don't continue |
| 276 | + if(!burn_atoms_on_turf(T, cached_damage)) |
| 277 | + break // Out of gas, stop running pointlessly |
| 278 | + |
270 | 279 | if(!sound_played) // play the sound once if we successfully ignite at least one thing |
271 | 280 | sound_played = TRUE |
272 | 281 | playsound(loc, pick(flame_sounds), 50, TRUE) |
|
281 | 290 | // /obj/structure/blob/normal |
282 | 291 |
|
283 | 292 | // Return value tells the parent whether to continue calculating the line |
284 | | -/obj/item/flamethrower/proc/default_ignite(turf/target, release_all = FALSE) |
285 | | - // do the fuel stuff |
286 | | - var/damage = process_fuel(target, release_all) |
287 | | - if(!damage) |
| 293 | +/obj/item/flamethrower/proc/burn_atoms_on_turf(turf/target, damage) |
| 294 | + // no damage? don't continue |
| 295 | + if(damage <= 0) |
288 | 296 | return FALSE |
289 | 297 |
|
290 | 298 | //Burn it |
|
333 | 341 | var/obj/projectile/P = hitby |
334 | 342 | if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(5)) |
335 | 343 | owner.visible_message(span_danger("\The [attack_text] hits the fueltank on [owner]'s [name], rupturing it! What a shot!")) |
336 | | - var/target_turf = get_turf(owner) |
337 | | - igniter.ignite_turf(src,target_turf, release_all = TRUE) |
338 | | - qdel(ptank) |
339 | | - return 1 //It hit the flamethrower, not them |
340 | | - |
341 | | - |
342 | | -/obj/item/assembly/igniter/proc/flamethrower_process(turf/open/location) |
343 | | - location.hotspot_expose(700,2) |
344 | | - |
345 | | -/obj/item/assembly/igniter/proc/ignite_turf(obj/item/flamethrower/F, turf/open/location, release_all = FALSE) |
346 | | - return F.default_ignite(location, release_all) |
| 344 | + var/turf/target_turf = get_turf(owner) |
| 345 | + burn_atoms_on_turf(target_turf, process_fuel(target_turf)) |
| 346 | + return TRUE //It hit the flamethrower, not them |
| 347 | + return ..() |
347 | 348 |
|
348 | 349 | ///////////////////// Flamethrower as an energy weapon ///////////////////// |
349 | 350 | // Currently used exclusively in /obj/item/gun/energy/printer/flamethrower |
350 | 351 | /obj/item/ammo_casing/energy/flamethrower |
351 | 352 | projectile_type = /obj/projectile/bullet/incendiary/flamethrower |
352 | 353 | select_name = "fire" |
353 | | - fire_sound = null |
| 354 | + fire_sound = 'sound/weapons/flamethrower1.ogg' |
354 | 355 | firing_effect_type = null |
355 | 356 | e_cost = 50 |
356 | 357 |
|
|
361 | 362 | sharpness = SHARP_NONE |
362 | 363 | range = 6 |
363 | 364 | penetration_flags = PENETRATE_OBJECTS | PENETRATE_MOBS |
| 365 | + |
| 366 | +#undef JOULES_PER_DAMAGE |
0 commit comments