mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-16 12:22:42 +00:00
Refactored the projectile code, mostly in line with TG's now. Refactored various procs that are used or depends on it. Projectiles can now ricochet if enabled to. Damage falloffs with distance. Homing projectiles can now have accuracy falloff with distance. Projectiles have a maximum range. Muzzle flash is configurable per projectile. Impact effect of the projectile is configurable per projectile. Accuracy decreases with distance. Projectiles work with signals and emits them, for easy hooking up from other parts of the code. Meatshielding is now less effective . Impact sound is now configurable per projectile. High risk.
397 lines
12 KiB
Plaintext
397 lines
12 KiB
Plaintext
#define MAX_ACTIVE_BONFIRE_LIMIT 15
|
|
|
|
GLOBAL_LIST_EMPTY(total_active_bonfires)
|
|
|
|
/obj/structure/bonfire
|
|
name = "bonfire"
|
|
desc = "A large pile of wood, ready to be burned."
|
|
icon = 'icons/obj/bonfire.dmi'
|
|
icon_state = "bonfire"
|
|
anchored = TRUE
|
|
density = FALSE
|
|
light_color = LIGHT_COLOR_FIRE
|
|
build_amt = 20
|
|
pass_flags_self = PASSTABLE | LETPASSTHROW
|
|
var/fuel = 2000
|
|
var/max_fuel = 2000
|
|
var/on_fire = FALSE
|
|
var/safe = FALSE
|
|
var/list/burnable_materials = list(MATERIAL_WOOD = 200, MATERIAL_WOOD_LOG = 400, MATERIAL_WOOD_BRANCH = 40, MATERIAL_COTTON = 20, MATERIAL_CLOTH = 50, MATERIAL_CARPET = 20, MATERIAL_CARDBOARD = 35)
|
|
var/list/burnable_other = list(/obj/item/ore/coal = 750, /obj/item/torch = 20) //For items without material/default material
|
|
var/heat_range = 5 //Range in which it will heat other people
|
|
var/heating_power
|
|
var/last_ambient_message
|
|
var/burn_out = TRUE //Whether or not it deletes itself when fuel is depleted
|
|
|
|
/obj/structure/bonfire/Initialize()
|
|
. = ..()
|
|
fuel = rand(1000, 2000)
|
|
create_reagents(120)
|
|
|
|
var/static/list/loc_connections = list(
|
|
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
|
)
|
|
|
|
AddElement(/datum/element/connect_loc, loc_connections)
|
|
|
|
/obj/structure/bonfire/Destroy()
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
GLOB.total_active_bonfires -= src
|
|
. = ..()
|
|
|
|
/obj/structure/bonfire/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
|
|
. = ..()
|
|
if(distance > 2)
|
|
return
|
|
if(on_fire)
|
|
switch(fuel)
|
|
if(0 to 200)
|
|
. += "\The [src] is burning weakly."
|
|
if(200 to 600)
|
|
. += "\The [src] is gently burning."
|
|
if(600 to 900)
|
|
. += "\The [src] is burning steadily."
|
|
if(900 to 1300)
|
|
. += "The flames are dancing wildly!"
|
|
if(1300 to 2000)
|
|
. += "The fire is roaring!"
|
|
|
|
/obj/structure/bonfire/update_icon()
|
|
if(on_fire)
|
|
if(fuel < 200)
|
|
icon_state = "[initial(icon_state)]_warm"
|
|
else
|
|
icon_state = "[initial(icon_state)]_fire"
|
|
else
|
|
icon_state = initial(icon_state)
|
|
|
|
|
|
/obj/structure/bonfire/AltClick(mob/user)
|
|
if(!ishuman(user))
|
|
return
|
|
var/mob/living/carbon/human/H = user
|
|
if(use_check_and_message(H))
|
|
return
|
|
if(fuel >= max(max_fuel * 0.1, 50) && on_fire)
|
|
to_chat(H, SPAN_NOTICE("You grab a burning stick from the fire."))
|
|
fuel -= 40
|
|
var/obj/item/device/flashlight/flare/torch/stick/torch = new(get_turf(user))
|
|
H.put_in_active_hand(torch)
|
|
|
|
/obj/structure/bonfire/attackby(obj/item/attacking_item, mob/user)
|
|
if(attacking_item.isFlameSource() && !on_fire) // needs to go last or else nothing else will work
|
|
light(user)
|
|
return
|
|
if(on_fire && (istype(attacking_item, /obj/item/flame) || istype(attacking_item, /obj/item/device/flashlight/flare/torch) || istype(attacking_item, /obj/item/clothing/mask/smokable))) //light unlit stuff
|
|
attacking_item.attackby(src, user)
|
|
return
|
|
if(fuel < max_fuel)
|
|
if(istype(attacking_item, /obj/item/stack/material))
|
|
var/obj/item/stack/material/I = attacking_item
|
|
if(I.default_type in burnable_materials)
|
|
I.use(1)
|
|
fuel = min(fuel + burnable_materials[I.default_type], max_fuel)
|
|
user.visible_message(SPAN_NOTICE("\The [user] adds some of \the [I] to \the [src]."))
|
|
return
|
|
if(is_type_in_list(attacking_item, burnable_other))
|
|
var/fuel_add = burnable_other[attacking_item]
|
|
fuel = min(fuel + fuel_add, max_fuel)
|
|
user.visible_message(SPAN_NOTICE("\The [user] tosses \the [attacking_item] into \the [src]."))
|
|
user.drop_from_inventory(attacking_item)
|
|
qdel(attacking_item)
|
|
return
|
|
else if(istype(attacking_item, /obj/item/material))
|
|
var/obj/item/material/M = attacking_item
|
|
if(M.material.name in burnable_materials)
|
|
var/fuel_add = burnable_materials[M.material] * (M.w_class / 5) //if you crafted a small item, it's not worth as much fuel
|
|
fuel = min(fuel + fuel_add, max_fuel)
|
|
user.visible_message(SPAN_NOTICE("\The [user] tosses \the [M] into \the [src]."))
|
|
user.drop_from_inventory(attacking_item)
|
|
attacking_item.forceMove(get_turf(src))
|
|
qdel(attacking_item)
|
|
return
|
|
else
|
|
var/obj/item/reagent_containers/RC = attacking_item
|
|
if(RC.is_open_container())
|
|
RC.reagents.trans_to(src, RC.amount_per_transfer_from_this)
|
|
handle_reagents()
|
|
|
|
/obj/structure/bonfire/proc/light(mob/user)
|
|
if(!fuel)
|
|
to_chat(user, SPAN_WARNING("There is not enough fuel to start a fire."))
|
|
return
|
|
if(GLOB.total_active_bonfires.len >= MAX_ACTIVE_BONFIRE_LIMIT)
|
|
to_chat(user, SPAN_WARNING("\The [src] refuses to light, despite all your efforts."))
|
|
return
|
|
if(!on_fire)
|
|
on_fire = TRUE
|
|
check_light()
|
|
update_icon()
|
|
START_PROCESSING(SSprocessing, src)
|
|
GLOB.total_active_bonfires += src
|
|
|
|
/obj/structure/bonfire/proc/check_light()
|
|
if(on_fire)
|
|
switch(fuel)
|
|
if(0 to 200)
|
|
set_light(2)
|
|
if(200 to 600)
|
|
set_light(3)
|
|
if(600 to 900)
|
|
set_light(4)
|
|
if(900 to 1300)
|
|
set_light(5)
|
|
if(1300 to 2000)
|
|
set_light(6)
|
|
else
|
|
set_light(0)
|
|
|
|
/obj/structure/bonfire/proc/check_heat_range()
|
|
if(on_fire)
|
|
switch(fuel)
|
|
if(0 to 200)
|
|
heat_range = 2
|
|
if(200 to 600)
|
|
heat_range = 3
|
|
if(600 to 900)
|
|
heat_range = 4
|
|
if(900 to 1300)
|
|
heat_range = 5
|
|
if(1300 to 2000)
|
|
heat_range = 6
|
|
else
|
|
heat_range = 0
|
|
return heat_range
|
|
|
|
/obj/structure/bonfire/proc/handle_reagents()
|
|
var/singleton/reagent/R
|
|
var/reagent_level
|
|
if(reagents.total_volume > 0 && on_fire)
|
|
if(reagents.has_reagent(/singleton/reagent/woodpulp))
|
|
R = GET_SINGLETON(/singleton/reagent/woodpulp)
|
|
reagent_level = reagents.reagent_volumes[R.type]
|
|
fuel = min(max_fuel, fuel + reagent_level * 5)
|
|
if(reagents.has_reagent(/singleton/reagent/fuel))
|
|
R = GET_SINGLETON(/singleton/reagent/fuel)
|
|
reagent_level = reagents.reagent_volumes[R.type]
|
|
fuel = min(max_fuel, fuel + reagent_level * 10)
|
|
if(reagents.has_reagent(/singleton/reagent/water))
|
|
R = GET_SINGLETON(/singleton/reagent/water)
|
|
reagent_level = reagents.reagent_volumes[R.type]
|
|
fuel = max(0, fuel - reagent_level * 10)
|
|
if(reagents.has_reagent(/singleton/reagent/toxin/fertilizer/monoammoniumphosphate))
|
|
R = GET_SINGLETON(/singleton/reagent/toxin/fertilizer/monoammoniumphosphate)
|
|
reagent_level = reagents.reagent_volumes[R.type]
|
|
fuel = max(0, fuel - reagent_level * 20)
|
|
if(reagents.has_reagent(/singleton/reagent/toxin/phoron))
|
|
R = GET_SINGLETON(/singleton/reagent/toxin/phoron)
|
|
reagent_level = reagents.reagent_volumes[R.type]
|
|
fuel = min(max_fuel, fuel + (reagent_level * 25))
|
|
|
|
if(reagents.has_reagent(/singleton/reagent/alcohol/ethanol))
|
|
R = GET_SINGLETON(/singleton/reagent/alcohol/ethanol)
|
|
var/singleton/reagent/alcohol/ethanol/A = R
|
|
reagent_level = reagents.reagent_volumes[A.type]
|
|
fuel = min(max_fuel, fuel + (reagent_level * (A.strength/20)))
|
|
|
|
R.remove_self(reagent_level, reagents)
|
|
|
|
/obj/structure/bonfire/process()
|
|
if(!on_fire)
|
|
return
|
|
|
|
handle_reagents()
|
|
|
|
fuel -= rand(1, 2)
|
|
|
|
if(fuel <= 0)
|
|
extinguish()
|
|
playsound()
|
|
|
|
update_icon()
|
|
|
|
if(isturf(loc))
|
|
var/turf/T = loc
|
|
T.hotspot_expose(700, 5)
|
|
|
|
if(locate(/mob/living, src.loc))
|
|
var/mob/living/M = locate(/mob/living, src.loc)
|
|
burn(M)
|
|
|
|
check_light()
|
|
heat()
|
|
warm_person()
|
|
if(prob(2))
|
|
ambient_message()
|
|
playsound(get_turf(src), 'sound/effects/fireplace.ogg', 30, 1, -3)
|
|
|
|
/obj/structure/bonfire/proc/extinguish()
|
|
on_fire = FALSE
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
check_light()
|
|
update_icon()
|
|
GLOB.total_active_bonfires -= src
|
|
if(burn_out)
|
|
visible_message(SPAN_NOTICE("\The [src] burns out, turning to a pile of ash and burnt wood."))
|
|
new /obj/effect/decal/cleanable/ash(get_turf(src))
|
|
qdel(src)
|
|
|
|
/obj/structure/bonfire/proc/heat()
|
|
if(!on_fire)
|
|
return
|
|
heating_power = 32000 * (fuel / max_fuel) //Less fuel, less heat
|
|
var/turf/simulated/L = get_turf(src)
|
|
if(istype(L))
|
|
var/datum/gas_mixture/env = L.return_air()
|
|
if(env && abs(env.temperature - (T20C + 5)) > 0.1)
|
|
var/transfer_moles = 0.35 * env.total_moles
|
|
var/datum/gas_mixture/removed = env.remove(transfer_moles)
|
|
|
|
if(removed)
|
|
var/heat_transfer = removed.get_thermal_energy_change(T20C + 5)
|
|
if(heat_transfer > 0) //heating air
|
|
heat_transfer = min(heat_transfer, heating_power)
|
|
removed.add_thermal_energy(heat_transfer)
|
|
env.merge(removed)
|
|
//fire_act stuff inside. Mobs handled in burn()
|
|
for(var/obj/O in get_turf(src))
|
|
if(O == src)
|
|
continue
|
|
heat_object(O)
|
|
|
|
/obj/structure/bonfire/proc/heat_object(obj/O)
|
|
if(istype(O, /obj/item/reagent_containers))
|
|
var/obj/item/reagent_containers/RC = O
|
|
var/current_temperature = RC.reagents.get_temperature()
|
|
if(current_temperature <= 310)
|
|
var/thermal_energy_limit = RC.reagents.get_thermal_energy_change(current_temperature, 310)
|
|
RC.reagents.add_thermal_energy(min(1750, thermal_energy_limit))
|
|
RC.reagents.handle_reactions()
|
|
|
|
if(istype(O, /obj/item/stack/material))
|
|
var/obj/item/stack/material/I = O
|
|
if(I.default_type in burnable_materials)
|
|
if(max_fuel - fuel >= burnable_materials[I.default_type])
|
|
I.use(1)
|
|
fuel += burnable_materials[I.default_type] * 0.75
|
|
O.fire_act()
|
|
|
|
/obj/structure/bonfire/proc/warm_person()
|
|
if(!on_fire)
|
|
return
|
|
heat_range = check_heat_range()
|
|
var/turf/simulated/L = get_turf(src)
|
|
if(!istype(L))
|
|
return
|
|
|
|
for(var/mob/living/carbon/human/H in oview(src, heat_range))
|
|
var/turf/simulated/T = get_turf(H)
|
|
var/datum/gas_mixture/mob_env
|
|
if(!istype(T))
|
|
continue
|
|
mob_env = T.return_air()
|
|
|
|
var/temp_adj = max(min(T20C, mob_env.temperature) - H.bodytemperature, -8)
|
|
if(temp_adj > -1) //only heats, not precise
|
|
continue
|
|
var/distance = get_dist(src, H)
|
|
var/heating_div = distance > 2 ? distance - 1 : 1 //Heat drops off if you're 3 or more tiles away
|
|
var/heat_eff = fuel / max_fuel //Less fuel, less heat provided
|
|
H.bodytemperature = min(H.bodytemperature + (abs((temp_adj * heat_eff)) / heating_div), 311)
|
|
|
|
/obj/structure/bonfire/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
|
SIGNAL_HANDLER
|
|
|
|
if(on_fire)
|
|
burn(arrived, TRUE)
|
|
|
|
/obj/structure/bonfire/proc/burn(var/mob/living/M, var/entered = FALSE)
|
|
if(safe)
|
|
return
|
|
if(istype(M) && prob((fuel / max_fuel) * 100))
|
|
if(entered)
|
|
to_chat(M, SPAN_WARNING("You are covered by fire and heat from entering \the [src]!"))
|
|
if(isanimal(M))
|
|
var/mob/living/simple_animal/H = M
|
|
if(H.flying) // Flying mobs will ignore the fire.
|
|
return
|
|
else
|
|
M.bodytemperature = min(M.bodytemperature + 150, 1000)
|
|
else
|
|
if(prob(50))
|
|
M.adjust_fire_stacks(5)
|
|
M.IgniteMob()
|
|
return
|
|
|
|
/obj/structure/bonfire/proc/ambient_message()
|
|
if(on_fire && world.time >= last_ambient_message + 600)
|
|
var/list/message_picks = list("The wood crackles in the heat.", "The flames of the fire dance vibrantly.", "Some wood crackles, sending harmless sparks dancing in the air",
|
|
"The light of the fire pulses calmly.", "Dozens of sparks dance upward before burning out.")
|
|
if(fuel / max_fuel >= 0.5)
|
|
message_picks += list("The fire roars steadily.", "The flames flare up briefly, before relaxing once more.", "Light smoke twirls upward before fading away.")
|
|
if(fuel / max_fuel <= 0.25)
|
|
message_picks += list("The embers shift as a piece of wood falls into them.", "The glow of the fire pulses weakly.", "Ash dances upward with a few sparks.")
|
|
var/message = "<I>[pick(message_picks)]</I>"
|
|
visible_message(SPAN_NOTICE(message))
|
|
last_ambient_message = world.time
|
|
|
|
/obj/structure/bonfire/light_up/Initialize()
|
|
. = ..()
|
|
on_fire = TRUE
|
|
check_light()
|
|
update_icon()
|
|
START_PROCESSING(SSprocessing, src)
|
|
GLOB.total_active_bonfires += src
|
|
|
|
/obj/structure/bonfire/fireplace
|
|
name = "fireplace"
|
|
desc = "A large stone brick fireplace."
|
|
icon = 'icons/obj/fireplace.dmi'
|
|
icon_state = "fireplace"
|
|
pixel_x = -16
|
|
safe = TRUE
|
|
density = TRUE
|
|
burn_out = FALSE
|
|
pass_flags_self = PASSTABLE
|
|
|
|
/obj/structure/bonfire/fireplace/New(var/newloc, var/material_name)
|
|
..()
|
|
fuel = 0 //don't start with fuel
|
|
if(!material_name)
|
|
material_name = MATERIAL_MARBLE
|
|
material = SSmaterials.get_material_by_name(material_name)
|
|
if(!material)
|
|
qdel(src)
|
|
return
|
|
name = "[material.display_name] fireplace"
|
|
|
|
/obj/structure/bonfire/fireplace/update_icon()
|
|
ClearOverlays()
|
|
if(on_fire)
|
|
switch(fuel)
|
|
if(0 to 250)
|
|
AddOverlays("fireplace_fire0")
|
|
if(251 to 750)
|
|
AddOverlays("fireplace_fire1")
|
|
if(751 to 1200)
|
|
AddOverlays("fireplace_fire2")
|
|
if(1201 to 1700)
|
|
AddOverlays("fireplace_fire3")
|
|
if(1700 to 2000)
|
|
AddOverlays("fireplace_fire4")
|
|
AddOverlays("fireplace_glow")
|
|
|
|
/obj/structure/bonfire/fireplace/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
|
if(mover?.movement_type & PHASING)
|
|
return TRUE
|
|
if(get_dir(loc, target) == NORTH)
|
|
return !density
|
|
return TRUE
|
|
|
|
/obj/structure/bonfire/fireplace/CheckExit(atom/movable/O, turf/target)
|
|
if(get_dir(loc, target) == NORTH)
|
|
return !density
|
|
return TRUE
|
|
|
|
#undef MAX_ACTIVE_BONFIRE_LIMIT
|