mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-28 02:21:53 +00:00
Refactors Temporal Scarring, changes how it works, removes longtimer quirk (#52688)
* changes temporal scarring * hhh why is there no ckey * note * oops * fixed
This commit is contained in:
@@ -1,20 +1,27 @@
|
|||||||
|
|
||||||
|
// ~wound damage/rolling defines
|
||||||
|
/// the cornerstone of the wound threshold system, your base wound roll for any attack is rand(1, damage^this), after armor reduces said damage. See [/obj/item/bodypart/proc/check_wounding]
|
||||||
#define WOUND_DAMAGE_EXPONENT 1.4
|
#define WOUND_DAMAGE_EXPONENT 1.4
|
||||||
|
/// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145, for reference)
|
||||||
/// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply)
|
#define WOUND_MAX_CONSIDERED_DAMAGE 35
|
||||||
|
/// an attack must do this much damage after armor in order to roll for being a wound (so pressure damage/being on fire doesn't proc it)
|
||||||
#define WOUND_MINIMUM_DAMAGE 5
|
#define WOUND_MINIMUM_DAMAGE 5
|
||||||
/// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart
|
/// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart
|
||||||
#define DISMEMBER_MINIMUM_DAMAGE 10
|
#define DISMEMBER_MINIMUM_DAMAGE 10
|
||||||
/// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145)
|
/// set wound_bonus on an item or attack to this to disable checking wounding for the attack
|
||||||
#define WOUND_MAX_CONSIDERED_DAMAGE 35
|
#define CANT_WOUND -100
|
||||||
|
|
||||||
|
// ~wound severities
|
||||||
#define WOUND_SEVERITY_TRIVIAL 0 // for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds
|
/// for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds
|
||||||
|
#define WOUND_SEVERITY_TRIVIAL 0
|
||||||
#define WOUND_SEVERITY_MODERATE 1
|
#define WOUND_SEVERITY_MODERATE 1
|
||||||
#define WOUND_SEVERITY_SEVERE 2
|
#define WOUND_SEVERITY_SEVERE 2
|
||||||
#define WOUND_SEVERITY_CRITICAL 3
|
#define WOUND_SEVERITY_CRITICAL 3
|
||||||
#define WOUND_SEVERITY_LOSS 4 // theoretical total limb loss, like dismemberment for cuts
|
/// outright dismemberment of limb
|
||||||
|
#define WOUND_SEVERITY_LOSS 4
|
||||||
|
|
||||||
|
|
||||||
|
// ~wound categories
|
||||||
/// any brute weapon/attack that doesn't have sharpness. rolls for blunt bone wounds
|
/// any brute weapon/attack that doesn't have sharpness. rolls for blunt bone wounds
|
||||||
#define WOUND_BLUNT 1
|
#define WOUND_BLUNT 1
|
||||||
/// any brute weapon/attack with sharpness = SHARP_EDGED. rolls for slash wounds
|
/// any brute weapon/attack with sharpness = SHARP_EDGED. rolls for slash wounds
|
||||||
@@ -24,18 +31,18 @@
|
|||||||
/// any concentrated burn attack (lasers really). rolls for burning wounds
|
/// any concentrated burn attack (lasers really). rolls for burning wounds
|
||||||
#define WOUND_BURN 4
|
#define WOUND_BURN 4
|
||||||
|
|
||||||
// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind()]
|
|
||||||
|
// ~determination second wind defines
|
||||||
|
// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind]
|
||||||
#define WOUND_DETERMINATION_MODERATE 1
|
#define WOUND_DETERMINATION_MODERATE 1
|
||||||
#define WOUND_DETERMINATION_SEVERE 2.5
|
#define WOUND_DETERMINATION_SEVERE 2.5
|
||||||
#define WOUND_DETERMINATION_CRITICAL 5
|
#define WOUND_DETERMINATION_CRITICAL 5
|
||||||
#define WOUND_DETERMINATION_LOSS 7.5
|
#define WOUND_DETERMINATION_LOSS 7.5
|
||||||
|
|
||||||
/// the max amount of determination you can have
|
/// the max amount of determination you can have
|
||||||
#define WOUND_DETERMINATION_MAX 10
|
#define WOUND_DETERMINATION_MAX 10
|
||||||
|
|
||||||
/// set wound_bonus on an item or attack to this to disable checking wounding for the attack
|
|
||||||
#define CANT_WOUND -100
|
|
||||||
|
|
||||||
|
// ~wound global lists
|
||||||
// list in order of highest severity to lowest
|
// list in order of highest severity to lowest
|
||||||
GLOBAL_LIST_INIT(global_wound_types, list(WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate),
|
GLOBAL_LIST_INIT(global_wound_types, list(WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate),
|
||||||
WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate),
|
WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate),
|
||||||
@@ -43,11 +50,14 @@ GLOBAL_LIST_INIT(global_wound_types, list(WOUND_BLUNT = list(/datum/wound/blunt/
|
|||||||
WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)
|
WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
// every single type of wound that can be rolled naturally, in case you need to pull a random one
|
||||||
GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate,
|
GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate,
|
||||||
/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate,
|
/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate,
|
||||||
/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate,
|
/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate,
|
||||||
/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate))
|
/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate))
|
||||||
|
|
||||||
|
|
||||||
|
// ~burn wound infection defines
|
||||||
// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse
|
// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse
|
||||||
/// below this has no ill effects from infection
|
/// below this has no ill effects from infection
|
||||||
#define WOUND_INFECTION_MODERATE 4
|
#define WOUND_INFECTION_MODERATE 4
|
||||||
@@ -60,6 +70,7 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datu
|
|||||||
// above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed
|
// above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed
|
||||||
|
|
||||||
|
|
||||||
|
// ~random wound balance defines
|
||||||
/// how quickly sanitization removes infestation and decays per tick
|
/// how quickly sanitization removes infestation and decays per tick
|
||||||
#define WOUND_BURN_SANITIZATION_RATE 0.15
|
#define WOUND_BURN_SANITIZATION_RATE 0.15
|
||||||
/// how much blood you can lose per tick per slash max. 8 is a LOT of blood for one cut so don't worry about hitting it easily
|
/// how much blood you can lose per tick per slash max. 8 is a LOT of blood for one cut so don't worry about hitting it easily
|
||||||
@@ -69,25 +80,9 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datu
|
|||||||
/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
|
/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
|
||||||
#define WOUND_BONE_HEAD_TIME_VARIANCE 20
|
#define WOUND_BONE_HEAD_TIME_VARIANCE 20
|
||||||
|
|
||||||
// The following are for persistent scar save formats
|
|
||||||
/// The version number of the scar we're saving
|
|
||||||
#define SCAR_SAVE_VERS 1
|
|
||||||
/// The body_zone we're applying to on granting
|
|
||||||
#define SCAR_SAVE_ZONE 2
|
|
||||||
/// The description we're loading
|
|
||||||
#define SCAR_SAVE_DESC 3
|
|
||||||
/// The precise location we're loading
|
|
||||||
#define SCAR_SAVE_PRECISE_LOCATION 4
|
|
||||||
/// The severity the scar had
|
|
||||||
#define SCAR_SAVE_SEVERITY 5
|
|
||||||
///how many fields there are above (NOT INCLUDING THIS OBVIOUSLY)
|
|
||||||
#define SCAR_SAVE_LENGTH 5
|
|
||||||
|
|
||||||
// increment this number when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc)
|
|
||||||
/// saved scars with a version lower than this will be discarded
|
|
||||||
#define SCAR_CURRENT_VERSION 1
|
|
||||||
|
|
||||||
|
|
||||||
|
// ~mangling defines
|
||||||
// With the wounds pt. 2 update, general dismemberment now requires 2 things for a limb to be dismemberable (bone only creatures just need the second):
|
// With the wounds pt. 2 update, general dismemberment now requires 2 things for a limb to be dismemberable (bone only creatures just need the second):
|
||||||
// 1. Skin is mangled: A critical slash or pierce wound on that limb
|
// 1. Skin is mangled: A critical slash or pierce wound on that limb
|
||||||
// 2. Bone is mangled: At least a severe bone wound on that limb
|
// 2. Bone is mangled: At least a severe bone wound on that limb
|
||||||
@@ -97,6 +92,8 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datu
|
|||||||
#define BODYPART_MANGLED_FLESH 2
|
#define BODYPART_MANGLED_FLESH 2
|
||||||
#define BODYPART_MANGLED_BOTH 3
|
#define BODYPART_MANGLED_BOTH 3
|
||||||
|
|
||||||
|
|
||||||
|
// ~biology defines
|
||||||
// What kind of biology we have, and what wounds we can suffer, mostly relies on the HAS_FLESH and HAS_BONE species traits on human species
|
// What kind of biology we have, and what wounds we can suffer, mostly relies on the HAS_FLESH and HAS_BONE species traits on human species
|
||||||
/// golems and androids, cannot suffer any wounds
|
/// golems and androids, cannot suffer any wounds
|
||||||
#define BIO_INORGANIC 0
|
#define BIO_INORGANIC 0
|
||||||
@@ -104,9 +101,11 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datu
|
|||||||
#define BIO_JUST_BONE 1
|
#define BIO_JUST_BONE 1
|
||||||
/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds
|
/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds
|
||||||
#define BIO_JUST_FLESH 2
|
#define BIO_JUST_FLESH 2
|
||||||
/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember
|
/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember. conveniently, what you get when you combine BIO_JUST_BONE and BIO_JUST_FLESH
|
||||||
#define BIO_FLESH_BONE 3
|
#define BIO_FLESH_BONE 3
|
||||||
|
|
||||||
|
|
||||||
|
// ~wound flag defines
|
||||||
/// If this wound requires having the HAS_FLESH flag for humanoids
|
/// If this wound requires having the HAS_FLESH flag for humanoids
|
||||||
#define FLESH_WOUND (1<<0)
|
#define FLESH_WOUND (1<<0)
|
||||||
/// If this wound requires having the HAS_BONE flag for humanaoids
|
/// If this wound requires having the HAS_BONE flag for humanaoids
|
||||||
@@ -118,3 +117,25 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datu
|
|||||||
/// If this wound marks the limb as being allowed to have gauze applied
|
/// If this wound marks the limb as being allowed to have gauze applied
|
||||||
#define ACCEPTS_GAUZE (1<<4)
|
#define ACCEPTS_GAUZE (1<<4)
|
||||||
|
|
||||||
|
|
||||||
|
// ~scar persistence defines
|
||||||
|
// The following are the order placements for persistent scar save formats
|
||||||
|
/// The version number of the scar we're saving, any scars being loaded below this number will be discarded, see SCAR_CURRENT_VERSION below
|
||||||
|
#define SCAR_SAVE_VERS 1
|
||||||
|
/// The body_zone we're applying to on granting
|
||||||
|
#define SCAR_SAVE_ZONE 2
|
||||||
|
/// The description we're loading
|
||||||
|
#define SCAR_SAVE_DESC 3
|
||||||
|
/// The precise location we're loading
|
||||||
|
#define SCAR_SAVE_PRECISE_LOCATION 4
|
||||||
|
/// The severity the scar had
|
||||||
|
#define SCAR_SAVE_SEVERITY 5
|
||||||
|
/// Whether this is a BIO_JUST_BONE scar, a BIO_JUST_FLESH scar, or a BIO_FLESH_BONE scar (so you can't load fleshy human scars on a plasmaman character)
|
||||||
|
#define SCAR_SAVE_BIOLOGY 6
|
||||||
|
///how many fields we save for each scar (so the number of above fields)
|
||||||
|
#define SCAR_SAVE_LENGTH 6
|
||||||
|
|
||||||
|
/// saved scars with a version lower than this will be discarded, increment when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc)
|
||||||
|
#define SCAR_CURRENT_VERSION 2
|
||||||
|
/// how many scar slots we have to cycle through for persistent scarring, if enabled in character prefs
|
||||||
|
#define PERSISTENT_SCAR_SLOTS 3
|
||||||
|
|||||||
@@ -402,15 +402,6 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
|
|
||||||
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
|
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
|
||||||
if(!original_human || original_human.stat == DEAD || !original_human.all_scars || !(original_human == ending_human))
|
if(!original_human || original_human.stat == DEAD || !original_human.all_scars || !(original_human == ending_human))
|
||||||
if(ending_human.client) // i was told if i don't check this every step of the way byond might decide a client ceases to exist mid proc so here we go
|
original_human.save_persistent_scars(TRUE)
|
||||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ""
|
|
||||||
else
|
else
|
||||||
for(var/k in ending_human.all_wounds)
|
original_human.save_persistent_scars()
|
||||||
var/datum/wound/iter_wound = k
|
|
||||||
iter_wound.remove_wound() // so we can get the scars for open wounds
|
|
||||||
if(!ending_human.client)
|
|
||||||
return
|
|
||||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars()
|
|
||||||
if(!ending_human.client)
|
|
||||||
return
|
|
||||||
ending_human.client.prefs.save_character()
|
|
||||||
|
|||||||
@@ -325,15 +325,20 @@ SUBSYSTEM_DEF(ticker)
|
|||||||
else
|
else
|
||||||
stack_trace("[S] [S.type] found in start landmarks list, which isn't a start landmark!")
|
stack_trace("[S] [S.type] found in start landmarks list, which isn't a start landmark!")
|
||||||
|
|
||||||
|
// handle persistence stuff that requires ckeys, in this case hardcore mode and temporal scarring
|
||||||
for(var/i in GLOB.player_list)
|
for(var/i in GLOB.player_list)
|
||||||
if(!ishuman(i))
|
if(!ishuman(i))
|
||||||
continue
|
continue
|
||||||
var/mob/living/carbon/human/hardcore_player = i
|
var/mob/living/carbon/human/iter_human = i
|
||||||
if(!hardcore_player.hardcore_survival_score)
|
|
||||||
|
iter_human.increment_scar_slot()
|
||||||
|
iter_human.load_persistent_scars()
|
||||||
|
|
||||||
|
if(!iter_human.hardcore_survival_score)
|
||||||
continue
|
continue
|
||||||
if(hardcore_player.mind?.special_role)
|
if(iter_human.mind?.special_role)
|
||||||
hardcore_player.hardcore_survival_score *= 2 //Double for antags
|
iter_human.hardcore_survival_score *= 2 //Double for antags
|
||||||
to_chat(hardcore_player, "<span class='notice'>You will gain [round(hardcore_player.hardcore_survival_score)] hardcore random points if you survive this round!</span>")
|
to_chat(iter_human, "<span class='notice'>You will gain [round(iter_human.hardcore_survival_score)] hardcore random points if you survive this round!</span>")
|
||||||
|
|
||||||
//These callbacks will fire after roundstart key transfer
|
//These callbacks will fire after roundstart key transfer
|
||||||
/datum/controller/subsystem/ticker/proc/OnRoundstart(datum/callback/cb)
|
/datum/controller/subsystem/ticker/proc/OnRoundstart(datum/callback/cb)
|
||||||
|
|||||||
@@ -73,6 +73,8 @@
|
|||||||
var/list/known_skills = list()
|
var/list/known_skills = list()
|
||||||
///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not
|
///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not
|
||||||
var/mob/original_character
|
var/mob/original_character
|
||||||
|
/// What scar slot we have loaded, so we don't have to constantly check the savefile
|
||||||
|
var/current_scar_slot
|
||||||
///Skill multiplier, adjusts how much xp you get/loose from adjust_xp. Dont override it directly, add your reason to experience_multiplier_reasons and use that as a key to put your value in there.
|
///Skill multiplier, adjusts how much xp you get/loose from adjust_xp. Dont override it directly, add your reason to experience_multiplier_reasons and use that as a key to put your value in there.
|
||||||
var/experience_multiplier = 1
|
var/experience_multiplier = 1
|
||||||
///Skill multiplier list, just slap your multiplier change onto this with the type it is coming from as key.
|
///Skill multiplier list, just slap your multiplier change onto this with the type it is coming from as key.
|
||||||
|
|||||||
@@ -240,19 +240,3 @@
|
|||||||
///Applies a bad moodlet for having an uncovered head
|
///Applies a bad moodlet for having an uncovered head
|
||||||
/datum/quirk/bald/proc/unequip_hat(mob/user, obj/item/clothing, force, newloc, no_move, invdrop, silent)
|
/datum/quirk/bald/proc/unequip_hat(mob/user, obj/item/clothing, force, newloc, no_move, invdrop, silent)
|
||||||
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_hair_day", /datum/mood_event/bald)
|
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_hair_day", /datum/mood_event/bald)
|
||||||
|
|
||||||
/datum/quirk/longtimer
|
|
||||||
name = "Longtimer"
|
|
||||||
desc = "You've been around for a long time and seen more than your fair share of action, suffering some pretty nasty scars along the way. For whatever reason, you've declined to get them removed or augmented."
|
|
||||||
value = 0
|
|
||||||
gain_text = "<span class='notice'>Your body has seen better days.</span>"
|
|
||||||
lose_text = "<span class='notice'>Your sins may wash away, but those scars are here to stay...</span>"
|
|
||||||
medical_record_text = "Patient has withstood significant physical trauma and declined plastic surgery procedures to heal scarring."
|
|
||||||
/// the minimum amount of scars we can generate
|
|
||||||
var/min_scars = 3
|
|
||||||
/// the maximum amount of scars we can generate
|
|
||||||
var/max_scars = 7
|
|
||||||
|
|
||||||
/datum/quirk/longtimer/on_spawn()
|
|
||||||
var/mob/living/carbon/C = quirk_holder
|
|
||||||
C.generate_fake_scars(rand(min_scars, max_scars))
|
|
||||||
|
|||||||
@@ -9,19 +9,21 @@
|
|||||||
/datum/scar
|
/datum/scar
|
||||||
var/obj/item/bodypart/limb
|
var/obj/item/bodypart/limb
|
||||||
var/mob/living/carbon/victim
|
var/mob/living/carbon/victim
|
||||||
|
/// The severity of the scar, derived from the worst severity a wound was at before it was healed (see: slashes), determines how visible/bold the scar description is
|
||||||
var/severity
|
var/severity
|
||||||
|
/// The description of the scar for examining
|
||||||
var/description
|
var/description
|
||||||
|
/// A string detailing the specific part of the bodypart the scar is on, for fluff purposes. See [/datum/scar/proc/generate]
|
||||||
var/precise_location
|
var/precise_location
|
||||||
|
|
||||||
/// Scars from the longtimer quirk are "fake" and won't be saved with persistent scarring, since it makes you spawn with a lot by default
|
/// In case we ever want to make scars that won't be saved for persistent scarring (formerly used by the now-removed longtimer quirk)
|
||||||
var/fake=FALSE
|
var/fake=FALSE
|
||||||
|
|
||||||
/// How many tiles away someone can see this scar, goes up with severity. Clothes covering this limb will decrease visibility by 1 each, except for the head/face which is a binary "is mask obscuring face" check
|
/// How many tiles away someone can see this scar, goes up with severity. Clothes covering this limb will decrease visibility by 1 each, except for the head/face which is a binary "is mask obscuring face" check
|
||||||
var/visibility = 2
|
var/visibility = 2
|
||||||
/// Whether this scar can actually be covered up by clothing
|
/// Whether this scar can actually be covered up by clothing
|
||||||
var/coverable = TRUE
|
var/coverable = TRUE
|
||||||
/// What zones this scar can be applied to
|
/// Obviously, scars that describe damaged flesh wouldn't apply to a skeleton (in some cases like bone wounds, there can be different descriptions for skeletons and fleshy humanoids)
|
||||||
var/list/applicable_zones = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG)
|
var/biology = BIO_FLESH_BONE
|
||||||
|
|
||||||
/datum/scar/Destroy(force, ...)
|
/datum/scar/Destroy(force, ...)
|
||||||
if(limb)
|
if(limb)
|
||||||
@@ -41,9 +43,6 @@
|
|||||||
* * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate)
|
* * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate)
|
||||||
*/
|
*/
|
||||||
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
|
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
|
||||||
if(!(BP.body_zone in applicable_zones))
|
|
||||||
qdel(src)
|
|
||||||
return
|
|
||||||
limb = BP
|
limb = BP
|
||||||
severity = W.severity
|
severity = W.severity
|
||||||
if(limb.owner)
|
if(limb.owner)
|
||||||
@@ -53,9 +52,11 @@
|
|||||||
if(victim)
|
if(victim)
|
||||||
LAZYADD(victim.all_scars, src)
|
LAZYADD(victim.all_scars, src)
|
||||||
|
|
||||||
if(victim && victim.get_biological_state() == BIO_JUST_BONE)
|
biology = victim?.get_biological_state() || BIO_FLESH_BONE
|
||||||
|
|
||||||
|
if(biology == BIO_JUST_BONE)
|
||||||
description = pick(strings(BONE_SCAR_FILE, W.scar_keyword)) || "general disfigurement"
|
description = pick(strings(BONE_SCAR_FILE, W.scar_keyword)) || "general disfigurement"
|
||||||
else
|
else // no specific support for flesh w/o bone scars since it's not really useful
|
||||||
description = pick(strings(FLESH_SCAR_FILE, W.scar_keyword)) || "general disfigurement"
|
description = pick(strings(FLESH_SCAR_FILE, W.scar_keyword)) || "general disfigurement"
|
||||||
|
|
||||||
precise_location = pick(strings(SCAR_LOC_FILE, limb.body_zone))
|
precise_location = pick(strings(SCAR_LOC_FILE, limb.body_zone))
|
||||||
@@ -78,17 +79,23 @@
|
|||||||
LAZYADD(victim.all_scars, src)
|
LAZYADD(victim.all_scars, src)
|
||||||
|
|
||||||
/// Used to "load" a persistent scar
|
/// Used to "load" a persistent scar
|
||||||
/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE)
|
/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE, biology=BIO_FLESH_BONE)
|
||||||
if(!(BP.body_zone in applicable_zones) || !BP.is_organic_limb())
|
if(!BP.is_organic_limb())
|
||||||
qdel(src)
|
qdel(src)
|
||||||
return
|
return
|
||||||
|
|
||||||
limb = BP
|
limb = BP
|
||||||
src.severity = severity
|
if(limb.owner)
|
||||||
LAZYADD(limb.scars, src)
|
victim = limb.owner
|
||||||
if(BP.owner)
|
if(victim.get_biological_state() != biology)
|
||||||
victim = BP.owner
|
qdel(src)
|
||||||
|
return
|
||||||
LAZYADD(victim.all_scars, src)
|
LAZYADD(victim.all_scars, src)
|
||||||
|
|
||||||
|
src.severity = severity
|
||||||
|
src.biology = biology
|
||||||
|
LAZYADD(limb.scars, src)
|
||||||
|
|
||||||
src.description = description
|
src.description = description
|
||||||
precise_location = specific_location
|
precise_location = specific_location
|
||||||
switch(severity)
|
switch(severity)
|
||||||
@@ -143,10 +150,9 @@
|
|||||||
|
|
||||||
/// Used to format a scar to safe in preferences for persistent scars
|
/// Used to format a scar to safe in preferences for persistent scars
|
||||||
/datum/scar/proc/format()
|
/datum/scar/proc/format()
|
||||||
if(!fake)
|
return fake ? null : "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]|[biology]"
|
||||||
return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]"
|
|
||||||
|
|
||||||
/// Used to format a scar to safe in preferences for persistent scars
|
/// Used to format a scar to safe in preferences for persistent scars
|
||||||
/datum/scar/proc/format_amputated(body_zone)
|
/datum/scar/proc/format_amputated(body_zone)
|
||||||
description = pick(list("is several skintone shades paler than the rest of the body", "is a gruesome patchwork of artificial flesh", "has a large series of attachment scars at the articulation points"))
|
description = pick(list("is several skintone shades paler than the rest of the body", "is a gruesome patchwork of artificial flesh", "has a large series of attachment scars at the articulation points"))
|
||||||
return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]"
|
return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]|[BIO_FLESH_BONE]"
|
||||||
|
|||||||
@@ -133,13 +133,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
|||||||
var/hearted_until
|
var/hearted_until
|
||||||
/// Agendered spessmen can choose whether to have a male or female bodytype
|
/// Agendered spessmen can choose whether to have a male or female bodytype
|
||||||
var/body_type
|
var/body_type
|
||||||
|
|
||||||
/// If we have persistent scars enabled
|
/// If we have persistent scars enabled
|
||||||
var/persistent_scars = TRUE
|
var/persistent_scars = TRUE
|
||||||
/// We have 5 slots for persistent scars, if enabled we pick a random one to load (empty by default) and scars at the end of the shift if we survived as our original person
|
|
||||||
var/list/scars_list = list("1" = "", "2" = "", "3" = "", "4" = "", "5" = "")
|
|
||||||
/// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)]
|
|
||||||
var/scars_index = 1
|
|
||||||
|
|
||||||
/datum/preferences/New(client/C)
|
/datum/preferences/New(client/C)
|
||||||
parent = C
|
parent = C
|
||||||
@@ -1721,12 +1716,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
|||||||
persistent_scars = !persistent_scars
|
persistent_scars = !persistent_scars
|
||||||
|
|
||||||
if("clear_scars")
|
if("clear_scars")
|
||||||
to_chat(user, "<span class='notice'>All scar slots cleared. Please save character to confirm.</span>")
|
var/path = "data/player_saves/[user.ckey[1]]/[user.ckey]/scars.sav"
|
||||||
scars_list["1"] = ""
|
fdel(path)
|
||||||
scars_list["2"] = ""
|
to_chat(user, "<span class='notice'>All scar slots cleared.</span>")
|
||||||
scars_list["3"] = ""
|
|
||||||
scars_list["4"] = ""
|
|
||||||
scars_list["5"] = ""
|
|
||||||
|
|
||||||
if("hear_midis")
|
if("hear_midis")
|
||||||
toggles ^= SOUND_MIDI
|
toggles ^= SOUND_MIDI
|
||||||
|
|||||||
@@ -291,7 +291,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
|||||||
if(newtype)
|
if(newtype)
|
||||||
pref_species = new newtype
|
pref_species = new newtype
|
||||||
|
|
||||||
scars_index = rand(1,5)
|
|
||||||
|
|
||||||
//Character
|
//Character
|
||||||
READ_FILE(S["real_name"], real_name)
|
READ_FILE(S["real_name"], real_name)
|
||||||
@@ -326,11 +325,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
|||||||
READ_FILE(S["feature_moth_wings"], features["moth_wings"])
|
READ_FILE(S["feature_moth_wings"], features["moth_wings"])
|
||||||
READ_FILE(S["feature_moth_markings"], features["moth_markings"])
|
READ_FILE(S["feature_moth_markings"], features["moth_markings"])
|
||||||
READ_FILE(S["persistent_scars"] , persistent_scars)
|
READ_FILE(S["persistent_scars"] , persistent_scars)
|
||||||
READ_FILE(S["scars1"], scars_list["1"])
|
|
||||||
READ_FILE(S["scars2"], scars_list["2"])
|
|
||||||
READ_FILE(S["scars3"], scars_list["3"])
|
|
||||||
READ_FILE(S["scars4"], scars_list["4"])
|
|
||||||
READ_FILE(S["scars5"], scars_list["5"])
|
|
||||||
if(!CONFIG_GET(flag/join_with_mutant_humans))
|
if(!CONFIG_GET(flag/join_with_mutant_humans))
|
||||||
features["tail_human"] = "none"
|
features["tail_human"] = "none"
|
||||||
features["ears"] = "none"
|
features["ears"] = "none"
|
||||||
@@ -422,11 +416,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
|||||||
features["moth_markings"] = sanitize_inlist(features["moth_markings"], GLOB.moth_markings_list, "None")
|
features["moth_markings"] = sanitize_inlist(features["moth_markings"], GLOB.moth_markings_list, "None")
|
||||||
|
|
||||||
persistent_scars = sanitize_integer(persistent_scars)
|
persistent_scars = sanitize_integer(persistent_scars)
|
||||||
scars_list["1"] = sanitize_text(scars_list["1"])
|
|
||||||
scars_list["2"] = sanitize_text(scars_list["2"])
|
|
||||||
scars_list["3"] = sanitize_text(scars_list["3"])
|
|
||||||
scars_list["4"] = sanitize_text(scars_list["4"])
|
|
||||||
scars_list["5"] = sanitize_text(scars_list["5"])
|
|
||||||
|
|
||||||
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
|
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
|
||||||
//Validate job prefs
|
//Validate job prefs
|
||||||
@@ -484,12 +473,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
|||||||
WRITE_FILE(S["feature_moth_wings"] , features["moth_wings"])
|
WRITE_FILE(S["feature_moth_wings"] , features["moth_wings"])
|
||||||
WRITE_FILE(S["feature_moth_markings"] , features["moth_markings"])
|
WRITE_FILE(S["feature_moth_markings"] , features["moth_markings"])
|
||||||
WRITE_FILE(S["persistent_scars"] , persistent_scars)
|
WRITE_FILE(S["persistent_scars"] , persistent_scars)
|
||||||
WRITE_FILE(S["scars1"] , scars_list["1"])
|
|
||||||
WRITE_FILE(S["scars2"] , scars_list["2"])
|
|
||||||
WRITE_FILE(S["scars3"] , scars_list["3"])
|
|
||||||
WRITE_FILE(S["scars4"] , scars_list["4"])
|
|
||||||
WRITE_FILE(S["scars5"] , scars_list["5"])
|
|
||||||
|
|
||||||
|
|
||||||
//Custom names
|
//Custom names
|
||||||
for(var/custom_name_id in GLOB.preferences_custom_names)
|
for(var/custom_name_id in GLOB.preferences_custom_names)
|
||||||
|
|||||||
@@ -331,6 +331,9 @@
|
|||||||
to_chat(humanc, "<span class='userdanger'><i>THERE CAN BE ONLY ONE!!!</i></span>")
|
to_chat(humanc, "<span class='userdanger'><i>THERE CAN BE ONLY ONE!!!</i></span>")
|
||||||
humanc.make_scottish()
|
humanc.make_scottish()
|
||||||
|
|
||||||
|
humanc.increment_scar_slot()
|
||||||
|
humanc.load_persistent_scars()
|
||||||
|
|
||||||
if(GLOB.summon_guns_triggered)
|
if(GLOB.summon_guns_triggered)
|
||||||
give_guns(humanc)
|
give_guns(humanc)
|
||||||
if(GLOB.summon_magic_triggered)
|
if(GLOB.summon_magic_triggered)
|
||||||
@@ -432,16 +435,6 @@
|
|||||||
is_antag = TRUE
|
is_antag = TRUE
|
||||||
|
|
||||||
client.prefs.copy_to(H, antagonist = is_antag, is_latejoiner = transfer_after)
|
client.prefs.copy_to(H, antagonist = is_antag, is_latejoiner = transfer_after)
|
||||||
var/cur_scar_index = client.prefs.scars_index
|
|
||||||
if(client.prefs.persistent_scars && client.prefs.scars_list["[cur_scar_index]"])
|
|
||||||
var/scar_string = client.prefs.scars_list["[cur_scar_index]"]
|
|
||||||
var/valid_scars = ""
|
|
||||||
for(var/scar_line in splittext(scar_string, ";"))
|
|
||||||
if(H.load_scar(scar_line))
|
|
||||||
valid_scars += "[scar_line];"
|
|
||||||
|
|
||||||
client.prefs.scars_list["[cur_scar_index]"] = valid_scars
|
|
||||||
client.prefs.save_character()
|
|
||||||
|
|
||||||
client.prefs.copy_to(H, antagonist = is_antag)
|
client.prefs.copy_to(H, antagonist = is_antag)
|
||||||
H.dna.update_dna_identity()
|
H.dna.update_dna_identity()
|
||||||
|
|||||||
@@ -176,7 +176,24 @@
|
|||||||
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
|
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/// For use formatting all of the scars this human has for saving for persistent scarring
|
/// When we're joining the game in [/mob/dead/new_player/proc/create_character], we increment our scar slot then store the slot in our mind datum.
|
||||||
|
/mob/living/carbon/human/proc/increment_scar_slot()
|
||||||
|
var/check_ckey = ckey || client?.ckey
|
||||||
|
if(!check_ckey || !mind || !client?.prefs.persistent_scars)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/path = "data/player_saves/[check_ckey[1]]/[check_ckey]/scars.sav"
|
||||||
|
var/index = mind.current_scar_slot
|
||||||
|
if (!index)
|
||||||
|
if(fexists(path))
|
||||||
|
var/savefile/F = new /savefile(path)
|
||||||
|
index = F["current_index"] || 1
|
||||||
|
else
|
||||||
|
index = 1
|
||||||
|
|
||||||
|
mind.current_scar_slot = (index % PERSISTENT_SCAR_SLOTS) + 1 || 1
|
||||||
|
|
||||||
|
/// For use formatting all of the scars this human has for saving for persistent scarring, returns a string with all current scars/missing limb amputation scars for saving or loading purposes
|
||||||
/mob/living/carbon/human/proc/format_scars()
|
/mob/living/carbon/human/proc/format_scars()
|
||||||
var/list/missing_bodyparts = get_missing_limbs()
|
var/list/missing_bodyparts = get_missing_limbs()
|
||||||
if(!all_scars && !length(missing_bodyparts))
|
if(!all_scars && !length(missing_bodyparts))
|
||||||
@@ -200,7 +217,50 @@
|
|||||||
return
|
return
|
||||||
var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
|
var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
|
||||||
var/datum/scar/scaries = new
|
var/datum/scar/scaries = new
|
||||||
return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
|
return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]), text2num(scar_data[SCAR_SAVE_BIOLOGY]))
|
||||||
|
|
||||||
|
/// Read all the scars we have at the designated slot, verify they're good (or dump them if they're old/wrong format), create them on the user, and write the scars that passed muster back to the file
|
||||||
|
/mob/living/carbon/human/proc/load_persistent_scars()
|
||||||
|
if(!ckey || !mind || !client?.prefs.persistent_scars)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/path = "data/player_saves/[ckey[1]]/[ckey]/scars.sav"
|
||||||
|
if (!fexists(path))
|
||||||
|
return FALSE
|
||||||
|
var/savefile/F = new /savefile(path)
|
||||||
|
if(!F)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/index = mind.current_scar_slot || F["current_index"] || 1
|
||||||
|
|
||||||
|
var/scar_string = F["scar[index]"]
|
||||||
|
var/valid_scars = ""
|
||||||
|
for(var/scar_line in splittext(sanitize_text(scar_string), ";"))
|
||||||
|
if(load_scar(scar_line))
|
||||||
|
valid_scars += "[scar_line];"
|
||||||
|
|
||||||
|
WRITE_FILE(F["scar[index]"], sanitize_text(valid_scars))
|
||||||
|
|
||||||
|
/// Save any scars we have to our designated slot, then write our current slot so that the next time we call [/mob/living/carbon/human/proc/increment_scar_slot] (the next round we join), we'll be there
|
||||||
|
/mob/living/carbon/human/proc/save_persistent_scars(nuke=FALSE)
|
||||||
|
if(!ckey || !mind || !client?.prefs.persistent_scars)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/path = "data/player_saves/[ckey[1]]/[ckey]/scars.sav"
|
||||||
|
var/savefile/F = new /savefile(path)
|
||||||
|
var/index = mind.current_scar_slot || F["current_index"] || 1
|
||||||
|
|
||||||
|
if(nuke)
|
||||||
|
WRITE_FILE(F["scar[index]"], "")
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/k in all_wounds)
|
||||||
|
var/datum/wound/iter_wound = k
|
||||||
|
iter_wound.remove_wound() // so we can get the scars for open wounds
|
||||||
|
|
||||||
|
var/valid_scars = format_scars()
|
||||||
|
WRITE_FILE(F["scar[index]"], sanitize_text(valid_scars))
|
||||||
|
WRITE_FILE(F["current_index"], sanitize_integer(index))
|
||||||
|
|
||||||
/mob/living/carbon/human/get_biological_state()
|
/mob/living/carbon/human/get_biological_state()
|
||||||
return dna.species.get_biological_state()
|
return dna.species.get_biological_state()
|
||||||
|
|||||||
Reference in New Issue
Block a user