Files
Bubberstation/code/datums/armor/_armor.dm
SkyratBot 011fefdd81 [MIRROR] Refactors armor into dedicated subtypes [MDB IGNORE] (#18291)
* Refactors armor into dedicated subtypes

* start

* most tg things

* pain (#18584)

* shit

* non-mod changes

* compile

Co-authored-by: John Doe <gamingskeleton3@gmail.com>

* #18291

* compile fix

* ???

Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
Co-authored-by: John Doe <gamingskeleton3@gmail.com>
Co-authored-by: Zonespace <41448081+Zonespace27@users.noreply.github.com>
2023-01-07 20:06:16 -08:00

234 lines
6.7 KiB
Plaintext

/// Assosciative list of type -> armor. Used to ensure we always hold a reference to default armor datums
GLOBAL_LIST_INIT(armor_by_type, generate_armor_type_cache())
/proc/generate_armor_type_cache()
var/list/armor_cache = list()
for(var/datum/armor/armor_type as anything in subtypesof(/datum/armor))
armor_type = new armor_type
armor_cache[armor_type.type] = armor_type
armor_type.GenerateTag()
return armor_cache
/**
* Gets an armor type datum using the given type by formatting it into the expected datum tag
*/
/proc/get_armor_by_type(armor_type)
var/armor = locate(replacetext("[armor_type]", "/", "-"))
if(armor)
return armor
if(armor_type == /datum/armor)
CRASH("Attempted to get the base armor type, you probably meant to use /datum/armor/none")
CRASH("Attempted to get an armor type that did not exist! '[armor_type]'")
/**
* The armor datum holds information about different types of armor that an atom can have.
* It also contains logic and helpers for calculating damage and effective damage
*/
/datum/armor
VAR_PROTECTED/acid = 0
VAR_PROTECTED/bio = 0
VAR_PROTECTED/bomb = 0
VAR_PROTECTED/bullet = 0
VAR_PROTECTED/consume = 0
VAR_PROTECTED/energy = 0
VAR_PROTECTED/laser = 0
VAR_PROTECTED/fire = 0
VAR_PROTECTED/melee = 0
VAR_PROTECTED/wound = 0
/// A version of armor with no protections
/datum/armor/none
/// A version of armor that cannot be modified and will always return itself when attempted to be modified
/datum/armor/immune
/datum/armor/Destroy(force, ...)
if(!force && tag)
return QDEL_HINT_LETMELIVE
// something really wants us gone
datum_flags &= ~DF_USE_TAG
tag = null
return ..()
/datum/armor/GenerateTag()
..()
tag = replacetext("[type]", "/", "-")
/datum/armor/vv_edit_var(var_name, var_value)
return FALSE
/datum/armor/can_vv_mark()
return FALSE
/datum/armor/vv_get_dropdown()
return list("", "MUST MODIFY ARMOR VALUES ON THE PARENT ATOM")
/datum/armor/CanProcCall(procname)
return FALSE
/// Generate a brand new armor datum with the modifiers given, if ARMOR_ALL is specified only that modifier is used
/datum/armor/proc/generate_new_with_modifiers(list/modifiers)
var/datum/armor/new_armor = new
var/all_keys = ARMOR_LIST_ALL()
if(ARMOR_ALL in modifiers)
var/modifier_all = modifiers[ARMOR_ALL]
if(!modifier_all)
return src
for(var/mod in all_keys)
new_armor.vars[mod] = vars[mod] + modifier_all
return new_armor
for(var/modifier in modifiers)
if(modifier in all_keys)
new_armor.vars[modifier] = vars[modifier] + modifiers[modifier]
else
stack_trace("Attempt to call generate_new_with_modifiers with illegal modifier '[modifier]'! Ignoring it")
return new_armor
/datum/armor/immune/generate_new_with_modifiers(list/modifiers)
return src
/// Generate a brand new armor datum with the multiplier given, if ARMOR_ALL is specified only that modifer is used
/datum/armor/proc/generate_new_with_multipliers(list/multipliers)
var/datum/armor/new_armor = new
var/all_keys = ARMOR_LIST_ALL()
if(ARMOR_ALL in multipliers)
var/multiplier_all = multipliers[ARMOR_ALL]
if(!multiplier_all)
return src
for(var/multiplier in all_keys)
new_armor.vars[multiplier] = vars[multiplier] * multiplier_all
return new_armor
for(var/multiplier in multipliers)
if(multiplier in all_keys)
new_armor.vars[multiplier] = vars[multiplier] * multipliers[multiplier]
else
stack_trace("Attempt to call generate_new_with_multipliers with illegal multiplier '[multiplier]'! Ignoring it")
return new_armor
/datum/armor/immune/generate_new_with_multipliers(list/multipliers)
return src
/// Generate a brand new armor datum with the values given, if a value is not present it carries over
/datum/armor/proc/generate_new_with_specific(list/values)
var/datum/armor/new_armor = new
var/all_keys = ARMOR_LIST_ALL()
if(ARMOR_ALL in values)
var/value_all = values[ARMOR_ALL]
if(!value_all)
return src
for(var/mod in all_keys)
new_armor.vars[mod] = value_all
return new_armor
for(var/value in values)
if(value in all_keys)
new_armor.vars[value] = values[value]
else
stack_trace("Attempt to call generate_new_with_specific with illegal value '[value]'! Ignoring it")
return new_armor
/datum/armor/immune/generate_new_with_specific(list/values)
return src
/// Gets the rating of armor for the specified rating
/datum/armor/proc/get_rating(rating)
// its not that I dont trust coders, its just that I don't trust coders
if(!(rating in ARMOR_LIST_ALL()))
CRASH("Attempted to get a rating '[rating]' that doesnt exist")
return vars[rating]
/datum/armor/immune/get_rating(rating)
return 100
/// Converts all the ratings of the armor into a list, optionally inversed
/datum/armor/proc/get_rating_list(inverse = FALSE)
var/ratings = list()
for(var/rating in ARMOR_LIST_ALL())
var/value = vars[rating]
if(inverse)
value *= -1
ratings[rating] = value
return ratings
/datum/armor/immune/get_rating_list(inverse)
var/ratings = ..() // get all ratings
for(var/rating in ratings)
ratings[rating] = 100 // and set them to 100
return ratings
/// Returns a new armor datum with the given armor added onto this one
/datum/armor/proc/add_other_armor(datum/armor/other)
if(ispath(other))
other = get_armor_by_type(other)
return generate_new_with_modifiers(other.get_rating_list())
/datum/armor/immune/add_other_armor(datum/armor/other)
return src
/// Returns a new armor datum with the given armor removed from this one
/datum/armor/proc/subtract_other_armor(datum/armor/other)
if(ispath(other))
other = get_armor_by_type(other)
return generate_new_with_modifiers(other.get_rating_list(inverse = TRUE))
/datum/armor/immune/subtract_other_armor(datum/armor/other)
return src
/// Checks if any of the armor values are non-zero, so this technically also counts negative armor!
/datum/armor/proc/has_any_armor()
for(var/rating as anything in ARMOR_LIST_ALL())
if(vars[rating])
return TRUE
return FALSE
/datum/armor/immune/has_any_armor()
return TRUE
/**
* Rounds armor_value down to the nearest 10, divides it by 10 and then converts it to Roman numerals.
*
* Arguments:
* * armor_value - Number we're converting
*/
/proc/armor_to_protection_class(armor_value)
if (armor_value < 0)
. = "-"
. += "\Roman[round(abs(armor_value), 10) / 10]"
return .
/**
* Returns the client readable name of an armor type
*
* Arguments:
* * armor_type - The type to convert
*/
/proc/armor_to_protection_name(armor_type)
switch(armor_type)
if(ACID)
return "ACID"
if(BIO)
return "BIOHAZARD"
if(BOMB)
return "EXPLOSIVE"
if(BULLET)
return "BULLET"
if(CONSUME)
return "CONSUMING"
if(ENERGY)
return "ENERGY"
if(FIRE)
return "FIRE"
if(LASER)
return "LASER"
if(MELEE)
return "MELEE"
if(WOUND)
return "WOUNDING"
CRASH("Unknown armor type '[armor_type]'")