mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-25 08:34:23 +00:00
In cases where you're creating an image to use as an overlay, it makes more sense to use a mutable_appearance if you can. The image will create a static appearance for not just the image but also each intermediate step if you change vars along the way. The mutable appearance avoids this unnecessary and expensive process. The only situation that requires an image instead of a mutable_appearance is if the overlay is supposed to be directional. MA's ignore direction while images don't. I dunno why, probably another BYOND-ism. I added a convenience function, mutable_appearance(), designed to emulate image(). Also went ahead and set the default plane of /mutable_appearance to FLOAT_PLANE because it's fucking 0 by default. Several overlays that were image() calls were changed to just text strings when I could. overlays += "string" has the same result as overlays += image(icon, "string") and saves a proc call.
259 lines
8.3 KiB
Plaintext
259 lines
8.3 KiB
Plaintext
|
|
//the essential proc to call when an obj must receive damage of any kind.
|
|
/obj/proc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
|
if(sound_effect)
|
|
play_attack_sound(damage_amount, damage_type, damage_flag)
|
|
if(!(resistance_flags & INDESTRUCTIBLE) && obj_integrity > 0)
|
|
damage_amount = run_obj_armor(damage_amount, damage_type, damage_flag, attack_dir)
|
|
if(damage_amount >= 1)
|
|
. = damage_amount
|
|
obj_integrity = max(obj_integrity - damage_amount, 0)
|
|
if(obj_integrity <= 0)
|
|
obj_destruction(damage_flag)
|
|
else if(integrity_failure)
|
|
if(obj_integrity <= integrity_failure)
|
|
obj_break(damage_flag)
|
|
|
|
//returns the damage value of the attack after processing the obj's various armor protections
|
|
/obj/proc/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
|
switch(damage_type)
|
|
if(BRUTE)
|
|
if(BURN)
|
|
else
|
|
return 0
|
|
var/armor_protection = 0
|
|
if(damage_flag)
|
|
armor_protection = armor[damage_flag]
|
|
return round(damage_amount * (100 - armor_protection)*0.01, 0.1)
|
|
|
|
//the sound played when the obj is damaged.
|
|
/obj/proc/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
|
switch(damage_type)
|
|
if(BRUTE)
|
|
if(damage_amount)
|
|
playsound(src, 'sound/weapons/smash.ogg', 50, 1)
|
|
else
|
|
playsound(src, 'sound/weapons/tap.ogg', 50, 1)
|
|
if(BURN)
|
|
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
|
|
|
|
/obj/hitby(atom/movable/AM)
|
|
..()
|
|
var/tforce = 0
|
|
if(ismob(AM))
|
|
tforce = 10
|
|
else if(isobj(AM))
|
|
var/obj/O = AM
|
|
tforce = O.throwforce
|
|
take_damage(tforce, BRUTE, "melee", 1, get_dir(src, AM))
|
|
|
|
/obj/ex_act(severity, target)
|
|
..() //contents explosion
|
|
if(target == src)
|
|
qdel(src)
|
|
return
|
|
switch(severity)
|
|
if(1)
|
|
qdel(src)
|
|
if(2)
|
|
take_damage(rand(100, 250), BRUTE, "bomb", 0)
|
|
if(3)
|
|
take_damage(rand(10, 90), BRUTE, "bomb", 0)
|
|
|
|
/obj/bullet_act(obj/item/projectile/P)
|
|
. = ..()
|
|
playsound(src, P.hitsound, 50, 1)
|
|
visible_message("<span class='danger'>[src] is hit by \a [P]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
|
take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180))
|
|
|
|
/obj/proc/hulk_damage()
|
|
return 150 //the damage hulks do on punches to this object, is affected by melee armor
|
|
|
|
/obj/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
|
if(user.a_intent == INTENT_HARM)
|
|
..(user, 1)
|
|
visible_message("<span class='danger'>[user] smashes [src]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
|
if(density)
|
|
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
|
|
user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
|
|
else
|
|
playsound(src, 'sound/effects/bang.ogg', 50, 1)
|
|
take_damage(hulk_damage(), BRUTE, "melee", 0, get_dir(src, user))
|
|
return 1
|
|
return 0
|
|
|
|
/obj/blob_act(obj/structure/blob/B)
|
|
if(isturf(loc))
|
|
var/turf/T = loc
|
|
if(T.intact && level == 1) //the blob doesn't destroy thing below the floor
|
|
return
|
|
take_damage(400, BRUTE, "melee", 0, get_dir(src, B))
|
|
|
|
/obj/proc/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) //used by attack_alien, attack_animal, and attack_slime
|
|
user.do_attack_animation(src)
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
return take_damage(damage_amount, damage_type, damage_flag, sound_effect, get_dir(src, user))
|
|
|
|
/obj/attack_alien(mob/living/carbon/alien/humanoid/user)
|
|
if(attack_generic(user, 60, BRUTE, "melee", 0))
|
|
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
|
|
|
|
/obj/attack_animal(mob/living/simple_animal/M)
|
|
if(!M.melee_damage_upper && !M.obj_damage)
|
|
M.emote("custom", message = "[M.friendly] [src].")
|
|
return 0
|
|
else
|
|
var/play_soundeffect = 1
|
|
if(M.environment_smash)
|
|
play_soundeffect = 0
|
|
if(M.obj_damage)
|
|
. = attack_generic(M, M.obj_damage, M.melee_damage_type, "melee", play_soundeffect)
|
|
else
|
|
. = attack_generic(M, rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, "melee", play_soundeffect)
|
|
if(. && !play_soundeffect)
|
|
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
|
|
|
|
/obj/attack_slime(mob/living/simple_animal/slime/user)
|
|
if(!user.is_adult)
|
|
return
|
|
attack_generic(user, rand(10, 15), "melee", 1)
|
|
|
|
/obj/mech_melee_attack(obj/mecha/M)
|
|
M.do_attack_animation(src)
|
|
var/play_soundeffect = 0
|
|
var/mech_damtype = M.damtype
|
|
if(M.selected)
|
|
mech_damtype = M.selected.damtype
|
|
play_soundeffect = 1
|
|
else
|
|
switch(M.damtype)
|
|
if(BRUTE)
|
|
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
|
|
if(BURN)
|
|
playsound(src, 'sound/items/Welder.ogg', 50, 1)
|
|
if(TOX)
|
|
playsound(src, 'sound/effects/spray2.ogg', 50, 1)
|
|
return 0
|
|
else
|
|
return 0
|
|
visible_message("<span class='danger'>[M.name] has hit [src].</span>", null, null, COMBAT_MESSAGE_RANGE)
|
|
return take_damage(M.force*3, mech_damtype, "melee", play_soundeffect, get_dir(src, M)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
|
|
|
|
/obj/singularity_act()
|
|
ex_act(1)
|
|
if(src && !QDELETED(src))
|
|
qdel(src)
|
|
return 2
|
|
|
|
|
|
///// ACID
|
|
|
|
GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "acid"))
|
|
|
|
//the obj's reaction when touched by acid
|
|
/obj/acid_act(acidpwr, acid_volume)
|
|
if(!(resistance_flags & UNACIDABLE) && acid_volume)
|
|
|
|
if(!acid_level)
|
|
SSacid.processing[src] = src
|
|
add_overlay(GLOB.acid_overlay, TRUE)
|
|
var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids.
|
|
if(acid_level < acid_cap)
|
|
acid_level = min(acid_level + acidpwr * acid_volume, acid_cap)
|
|
return 1
|
|
|
|
//the proc called by the acid subsystem to process the acid that's on the obj
|
|
/obj/proc/acid_processing()
|
|
. = 1
|
|
if(!(resistance_flags & ACID_PROOF))
|
|
for(var/armour_value in armor)
|
|
if(armour_value != "acid" && armour_value != "fire")
|
|
armor[armour_value] = max(armor[armour_value] - round(sqrt(acid_level)*0.1), 0)
|
|
if(prob(33))
|
|
playsound(loc, 'sound/items/Welder.ogg', 150, 1)
|
|
take_damage(min(1 + round(sqrt(acid_level)*0.3), 300), BURN, "acid", 0)
|
|
|
|
acid_level = max(acid_level - (5 + 3*round(sqrt(acid_level))), 0)
|
|
if(!acid_level)
|
|
return 0
|
|
|
|
//called when the obj is destroyed by acid.
|
|
/obj/proc/acid_melt()
|
|
SSacid.processing -= src
|
|
deconstruct(FALSE)
|
|
|
|
//// FIRE
|
|
|
|
/obj/fire_act(exposed_temperature, exposed_volume)
|
|
if(isturf(loc))
|
|
var/turf/T = loc
|
|
if(T.intact && level == 1) //fire can't damage things hidden below the floor.
|
|
return
|
|
if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
|
|
take_damage(Clamp(0.02 * exposed_temperature, 0, 20), BURN, "fire", 0)
|
|
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE))
|
|
resistance_flags |= ON_FIRE
|
|
SSfire_burning.processing[src] = src
|
|
add_overlay(GLOB.fire_overlay, TRUE)
|
|
return 1
|
|
|
|
//called when the obj is destroyed by fire
|
|
/obj/proc/burn()
|
|
if(resistance_flags & ON_FIRE)
|
|
SSfire_burning.processing -= src
|
|
deconstruct(FALSE)
|
|
|
|
/obj/proc/extinguish()
|
|
if(resistance_flags & ON_FIRE)
|
|
resistance_flags &= ~ON_FIRE
|
|
cut_overlay(GLOB.fire_overlay, TRUE)
|
|
SSfire_burning.processing -= src
|
|
|
|
|
|
|
|
/obj/proc/tesla_act(var/power)
|
|
being_shocked = 1
|
|
var/power_bounced = power / 2
|
|
tesla_zap(src, 3, power_bounced)
|
|
addtimer(CALLBACK(src, .proc/reset_shocked), 10)
|
|
|
|
/obj/proc/reset_shocked()
|
|
being_shocked = 0
|
|
|
|
//the obj is deconstructed into pieces, whether through careful disassembly or when destroyed.
|
|
/obj/proc/deconstruct(disassembled = TRUE)
|
|
qdel(src)
|
|
|
|
//what happens when the obj's health is below integrity_failure level.
|
|
/obj/proc/obj_break(damage_flag)
|
|
return
|
|
|
|
//what happens when the obj's integrity reaches zero.
|
|
/obj/proc/obj_destruction(damage_flag)
|
|
if(damage_flag == "acid")
|
|
acid_melt()
|
|
else if(damage_flag == "fire")
|
|
burn()
|
|
else
|
|
deconstruct(FALSE)
|
|
|
|
//changes max_integrity while retaining current health percentage
|
|
//returns TRUE if the obj broke, FALSE otherwise
|
|
/obj/proc/modify_max_integrity(new_max, can_break = TRUE, damage_type = BRUTE, new_failure_integrity = null)
|
|
var/current_integrity = obj_integrity
|
|
var/current_max = max_integrity
|
|
|
|
if(current_integrity != 0 && current_max != 0)
|
|
var/percentage = current_integrity / current_max
|
|
current_integrity = max(1, round(percentage * new_max)) //don't destroy it as a result
|
|
obj_integrity = current_integrity
|
|
|
|
max_integrity = new_max
|
|
|
|
if(new_failure_integrity != null)
|
|
integrity_failure = new_failure_integrity
|
|
|
|
if(can_break && integrity_failure && current_integrity <= integrity_failure)
|
|
obj_break(damage_type)
|
|
return TRUE
|
|
return FALSE |