mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-27 06:54:18 +01:00
Adds an universal object health system. (#21266)
https://www.youtube.com/watch?v=ZpUYjpKg9KY As per title. The goal is to add health to most objects in the game and thus allow them to be dynamically destructible, while also avoiding shitcode like each structure having its own snowflake health update proc. --------- Signed-off-by: Matt Atlas <mattiathebest2000@hotmail.it> Co-authored-by: Matt Atlas <liermattia@gmail.com> Co-authored-by: SleepyGemmy <99297919+SleepyGemmy@users.noreply.github.com>
This commit is contained in:
co-authored by
Matt Atlas
SleepyGemmy
parent
1d2871729f
commit
d5931c5ffe
@@ -17,11 +17,11 @@
|
||||
anchored = TRUE
|
||||
atom_flags = ATOM_FLAG_CHECKS_BORDER
|
||||
obj_flags = OBJ_FLAG_ROTATABLE|OBJ_FLAG_MOVES_UNSUPPORTED
|
||||
var/hitsound = 'sound/effects/glass_hit.ogg'
|
||||
var/maxhealth = 14
|
||||
maxhealth = OBJECT_HEALTH_FRAGILE
|
||||
hitsound = 'sound/effects/glass_hit.ogg'
|
||||
|
||||
var/maximal_heat = T0C + 100 // Maximal heat before this window begins taking damage from fire
|
||||
var/damage_per_fire_tick = 2 // Amount of damage per fire tick. Regular windows are not fireproof so they might as well break quickly.
|
||||
var/health
|
||||
var/ini_dir = null
|
||||
var/state = 2
|
||||
var/reinf = FALSE
|
||||
@@ -34,27 +34,26 @@
|
||||
|
||||
atmos_canpass = CANPASS_PROC
|
||||
|
||||
/obj/structure/window/condition_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
/obj/structure/window/get_damage_condition_hints(mob/user, distance, is_adjacent)
|
||||
if(health == maxhealth)
|
||||
. += SPAN_NOTICE("It looks fully intact.")
|
||||
. = SPAN_NOTICE("It looks fully intact.")
|
||||
else
|
||||
var/perc = health / maxhealth
|
||||
if(perc > 0.75)
|
||||
. += SPAN_NOTICE("It has a few cracks.")
|
||||
. = SPAN_NOTICE("It has a few cracks.")
|
||||
else if(perc > 0.5)
|
||||
. += SPAN_WARNING("It looks slightly damaged.")
|
||||
. = SPAN_WARNING("It looks slightly damaged.")
|
||||
else if(perc > 0.25)
|
||||
. += SPAN_WARNING("It looks moderately damaged.")
|
||||
. = SPAN_WARNING("It looks moderately damaged.")
|
||||
else
|
||||
. += SPAN_DANGER("It looks heavily damaged.")
|
||||
. = SPAN_DANGER("It looks heavily damaged.")
|
||||
if(silicate)
|
||||
if (silicate < 30)
|
||||
. += SPAN_NOTICE("It has a thin layer of silicate.")
|
||||
. = SPAN_NOTICE("It has a thin layer of silicate.")
|
||||
else if (silicate < 70)
|
||||
. += SPAN_NOTICE("It is covered in silicate.")
|
||||
. = SPAN_NOTICE("It is covered in silicate.")
|
||||
else
|
||||
. += SPAN_NOTICE("There is a thick layer of silicate covering it.")
|
||||
. = SPAN_NOTICE("There is a thick layer of silicate covering it.")
|
||||
|
||||
/obj/structure/window/proc/update_nearby_icons()
|
||||
QUEUE_SMOOTH_NEIGHBORS(src)
|
||||
@@ -65,38 +64,14 @@
|
||||
layer = ABOVE_HUMAN_LAYER
|
||||
QUEUE_SMOOTH(src)
|
||||
|
||||
/obj/structure/window/proc/take_damage(var/damage = 0, var/sound_effect = 1, message = TRUE)
|
||||
var/initialhealth = health
|
||||
|
||||
if(silicate)
|
||||
damage = damage * (1 - silicate / 200)
|
||||
|
||||
health = max(0, health - damage)
|
||||
|
||||
if(health <= 0)
|
||||
shatter(message)
|
||||
else
|
||||
if(sound_effect)
|
||||
playsound(loc, 'sound/effects/glass_hit.ogg', 100, 1)
|
||||
if(health < maxhealth / 4 && initialhealth >= maxhealth / 4)
|
||||
if(message)
|
||||
visible_message(SPAN_DANGER("[src] looks like it's about to shatter!"))
|
||||
playsound(loc, SFX_GLASS_CRACK, 100, 1)
|
||||
else if(health < maxhealth / 2 && initialhealth >= maxhealth / 2)
|
||||
if(message)
|
||||
visible_message(SPAN_WARNING("[src] looks seriously damaged!"))
|
||||
playsound(loc, SFX_GLASS_CRACK, 100, 1)
|
||||
else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4)
|
||||
if(message)
|
||||
visible_message(SPAN_WARNING("Cracks begin to appear in [src]!"))
|
||||
playsound(loc, SFX_GLASS_CRACK, 100, 1)
|
||||
return
|
||||
/obj/structure/window/on_death(damage, damage_flags, damage_type, armor_penetration, obj/weapon, message)
|
||||
shatter(message)
|
||||
|
||||
/obj/structure/window/proc/apply_silicate(var/amount)
|
||||
if(health < maxhealth) // Mend the damage.
|
||||
health = min(health + amount * 3, maxhealth)
|
||||
add_health(amount * 3)
|
||||
if(health == maxhealth)
|
||||
visible_message("[src] looks fully repaired." )
|
||||
visible_message(SPAN_NOTICE("The silicate fully mends the damage on \the [src]."))
|
||||
else // Reinforce.
|
||||
silicate = min(silicate + amount, 100)
|
||||
updateSilicate()
|
||||
@@ -145,23 +120,19 @@
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
take_damage(proj_damage)
|
||||
return
|
||||
add_damage(proj_damage)
|
||||
|
||||
/obj/structure/window/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1)
|
||||
qdel(src)
|
||||
return
|
||||
if(2)
|
||||
shatter(0)
|
||||
return
|
||||
if(3)
|
||||
if(prob(50))
|
||||
shatter(0)
|
||||
return
|
||||
else
|
||||
take_damage(rand(10,30), TRUE, FALSE)
|
||||
add_damage(rand(10,30), TRUE, FALSE)
|
||||
|
||||
// This and relevant verbs/procs can probably be removed since full windows are a thing now. -Gem
|
||||
/obj/structure/window/proc/is_full_window()
|
||||
@@ -210,7 +181,7 @@
|
||||
anchored = 0
|
||||
update_nearby_icons()
|
||||
step(src, get_dir(hitting_atom, src))
|
||||
take_damage(tforce)
|
||||
add_damage(tforce)
|
||||
|
||||
/obj/structure/window/attack_hand(var/mob/living/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
@@ -243,7 +214,7 @@
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
if(damage >= 10)
|
||||
visible_message(SPAN_DANGER("[user] smashes into [src]!"))
|
||||
take_damage(damage)
|
||||
add_damage(damage)
|
||||
else
|
||||
visible_message(SPAN_NOTICE("\The [user] bonks \the [src] harmlessly."))
|
||||
playsound(src.loc, 'sound/effects/glass_hit.ogg', 10, 1, -2)
|
||||
@@ -347,8 +318,7 @@
|
||||
/obj/structure/window/proc/hit(var/damage, var/sound_effect = 1)
|
||||
if(reinf)
|
||||
damage *= 0.5
|
||||
take_damage(damage)
|
||||
return
|
||||
add_damage(damage)
|
||||
|
||||
/obj/structure/window/proc/dismantle_window()
|
||||
if(dir == SOUTHWEST)
|
||||
@@ -369,8 +339,6 @@
|
||||
if (start_dir)
|
||||
set_dir(start_dir)
|
||||
|
||||
health = maxhealth
|
||||
|
||||
ini_dir = dir
|
||||
|
||||
update_nearby_tiles(need_rebuild=1)
|
||||
@@ -429,7 +397,7 @@
|
||||
glasstype = /obj/item/stack/material/glass
|
||||
maximal_heat = T0C + 100
|
||||
damage_per_fire_tick = 2
|
||||
maxhealth = 12
|
||||
maxhealth = OBJECT_HEALTH_FRAGILE
|
||||
|
||||
/obj/structure/window/basic/full
|
||||
name = "glass"
|
||||
@@ -441,7 +409,7 @@
|
||||
desc = "It looks rather strong. Might take a few good hits to shatter it."
|
||||
icon_state = "rwindow"
|
||||
basestate = "rwindow"
|
||||
maxhealth = 40
|
||||
maxhealth = OBJECT_HEALTH_LOW
|
||||
reinf = TRUE
|
||||
maximal_heat = T0C + 750
|
||||
damage_per_fire_tick = 2
|
||||
@@ -462,7 +430,7 @@
|
||||
/obj/structure/window/reinforced/tinted/frosted
|
||||
name = "reinforced frosted glass pane"
|
||||
desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window."
|
||||
maxhealth = 30
|
||||
maxhealth = OBJECT_HEALTH_EXTREMELY_LOW
|
||||
|
||||
/obj/structure/window/reinforced/polarized
|
||||
name = "reinforced electrochromic glass pane"
|
||||
@@ -489,9 +457,6 @@
|
||||
/obj/structure/window/reinforced/crescent/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return
|
||||
|
||||
/obj/structure/window/reinforced/crescent/take_damage()
|
||||
return
|
||||
|
||||
/obj/structure/window/reinforced/crescent/shatter()
|
||||
return
|
||||
|
||||
@@ -536,7 +501,7 @@
|
||||
glasstype = /obj/item/stack/material/glass/phoronglass
|
||||
maximal_heat = T0C + 2000
|
||||
damage_per_fire_tick = 1 // This should last for 80 fire ticks if the window is not damaged at all. The idea is that borosilicate windows have something like ablative layer that protects them for a while.
|
||||
maxhealth = 40
|
||||
maxhealth = OBJECT_HEALTH_VERY_LOW
|
||||
/// Phoron-infused silicate
|
||||
rad_resistance_modifier = 4
|
||||
|
||||
@@ -547,13 +512,13 @@
|
||||
glasstype = /obj/item/stack/material/glass/phoronrglass
|
||||
reinf = TRUE
|
||||
maximal_heat = T0C + 4000
|
||||
maxhealth = 80
|
||||
maxhealth = OBJECT_HEALTH_LOW
|
||||
|
||||
/obj/structure/window/borosilicate/reinforced/skrell
|
||||
name = "advanced borosilicate alloy window"
|
||||
desc = "A window made out of a higly advanced borosilicate alloy. It seems to be extremely strong."
|
||||
color = GLASS_COLOR_PHORON
|
||||
maxhealth = 250
|
||||
maxhealth = OBJECT_HEALTH_HIGH
|
||||
|
||||
/********** Shuttle Windows **********/
|
||||
/obj/structure/window/shuttle
|
||||
@@ -564,7 +529,7 @@
|
||||
basestate = "w"
|
||||
atom_flags = 0
|
||||
obj_flags = null
|
||||
maxhealth = 40
|
||||
maxhealth = OBJECT_HEALTH_VERY_LOW
|
||||
reinf = TRUE
|
||||
dir = 5
|
||||
smoothing_flags = SMOOTH_TRUE
|
||||
@@ -579,8 +544,7 @@
|
||||
/obj/structure/window/shuttle/legion
|
||||
name = "reinforced cockpit window"
|
||||
icon = 'icons/obj/smooth/shuttle_window_legion.dmi'
|
||||
health = 160
|
||||
maxhealth = 160
|
||||
maxhealth = OBJECT_HEALTH_HIGH
|
||||
|
||||
/obj/structure/window/shuttle/palepurple
|
||||
icon = 'icons/obj/smooth/shuttle_window_palepurple.dmi'
|
||||
@@ -589,8 +553,7 @@
|
||||
name = "advanced borosilicate alloy window"
|
||||
desc = "It looks extremely strong. Might take many good hits to crack it."
|
||||
icon = 'icons/obj/smooth/skrell_window_purple.dmi'
|
||||
health = 500
|
||||
maxhealth = 500
|
||||
maxhealth = OBJECT_HEALTH_VERY_HIGH
|
||||
smoothing_flags = SMOOTH_MORE | SMOOTH_DIAGONAL
|
||||
canSmoothWith = list(
|
||||
/turf/simulated/wall/shuttle/skrell,
|
||||
@@ -602,8 +565,7 @@
|
||||
desc = "It looks extremely strong. Might take many good hits to crack it."
|
||||
icon = 'icons/turf/smooth/scc_ship/scc_ship_windows.dmi'
|
||||
icon_state = "map_window"
|
||||
health = 500
|
||||
maxhealth = 500
|
||||
maxhealth = OBJECT_HEALTH_VERY_HIGH
|
||||
alpha = 255
|
||||
smoothing_flags = SMOOTH_MORE
|
||||
canSmoothWith = list(
|
||||
@@ -629,15 +591,11 @@
|
||||
|
||||
/obj/structure/window/shuttle/scc
|
||||
icon = 'icons/obj/smooth/scc_shuttle_window.dmi'
|
||||
health = 160
|
||||
maxhealth = 160
|
||||
maxhealth = OBJECT_HEALTH_HIGH
|
||||
|
||||
/obj/structure/window/shuttle/crescent
|
||||
desc = "It looks rather strong."
|
||||
|
||||
/obj/structure/window/shuttle/crescent/take_damage()
|
||||
return
|
||||
|
||||
//
|
||||
// Full Windows
|
||||
//
|
||||
@@ -647,7 +605,7 @@
|
||||
atom_flags = 0
|
||||
obj_flags = null
|
||||
dir = 5
|
||||
maxhealth = 28 // Two glass panes worth of health, since that's the minimum you need to break through to get to the other side.
|
||||
maxhealth = OBJECT_HEALTH_EXTREMELY_LOW
|
||||
glasstype = /obj/item/stack/material/glass
|
||||
shardtype = /obj/item/material/shard
|
||||
full = TRUE
|
||||
@@ -757,14 +715,12 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/structure/window/full/take_damage(var/damage = 0, var/sound_effect = 1)
|
||||
/obj/structure/window/full/add_damage(damage, damage_flags, damage_type, armor_penetration, obj/weapon, sound_effect = TRUE)
|
||||
var/initialhealth = health
|
||||
|
||||
if(silicate)
|
||||
damage = damage * (1 - silicate / 200)
|
||||
|
||||
health = max(0, health - damage)
|
||||
|
||||
if(health <= 0)
|
||||
shatter()
|
||||
else
|
||||
@@ -779,7 +735,6 @@
|
||||
else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4)
|
||||
visible_message(SPAN_WARNING("Cracks begin to appear in [src]!"))
|
||||
playsound(loc, SFX_GLASS_CRACK, 100, 1)
|
||||
return
|
||||
|
||||
/obj/structure/window/full/dismantle_window()
|
||||
var/obj/item/stack/material/mats = new glasstype(loc)
|
||||
@@ -803,7 +758,7 @@
|
||||
icon = 'icons/obj/smooth/window/full_window.dmi'
|
||||
icon_state = "window_glass"
|
||||
basestate = "window_glass"
|
||||
maxhealth = 80 // Two reinforced panes worth of health, since that's the minimum you need to break through to get to the other side.
|
||||
maxhealth = OBJECT_HEALTH_LOW
|
||||
reinf = TRUE
|
||||
maximal_heat = T0C + 750
|
||||
glasstype = /obj/item/stack/material/glass/reinforced
|
||||
@@ -834,9 +789,6 @@
|
||||
/obj/structure/window/full/reinforced/indestructible/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return
|
||||
|
||||
/obj/structure/window/full/reinforced/indestructible/take_damage()
|
||||
return
|
||||
|
||||
/obj/structure/window/full/reinforced/indestructible/shatter()
|
||||
return
|
||||
|
||||
@@ -867,9 +819,6 @@
|
||||
/obj/structure/window/full/reinforced/polarized/indestructible/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return
|
||||
|
||||
/obj/structure/window/full/reinforced/polarized/indestructible/take_damage()
|
||||
return
|
||||
|
||||
/obj/structure/window/full/reinforced/polarized/indestructible/shatter()
|
||||
return
|
||||
|
||||
@@ -898,7 +847,7 @@
|
||||
basestate = "window_glass"
|
||||
glasstype = /obj/item/stack/material/glass/phoronglass
|
||||
shardtype = /obj/item/material/shard/phoron
|
||||
maxhealth = 80 // Two borosilicate glass panes worth of health, since that's the minimum you need to break through to get to the other side.
|
||||
maxhealth = OBJECT_HEALTH_LOW
|
||||
maximal_heat = T0C + 2000
|
||||
damage_per_fire_tick = 1
|
||||
|
||||
@@ -907,7 +856,7 @@
|
||||
name = "reinforced borosilicate window"
|
||||
desc = "A borosilicate alloy window, with rods supporting it. It seems to be very strong."
|
||||
glasstype = /obj/item/stack/material/glass/phoronrglass
|
||||
maxhealth = 160 // Two reinforced borosilicate glass panes worth of health, since that's the minimum you need to break through to get to the other side.
|
||||
maxhealth = OBJECT_HEALTH_MEDIUM
|
||||
reinf = TRUE
|
||||
maximal_heat = T0C + 4000
|
||||
rad_resistance_modifier = 4
|
||||
|
||||
Reference in New Issue
Block a user