Skip to content

Commit

Permalink
Move species trait logic to living-level
Browse files Browse the repository at this point in the history
  • Loading branch information
out-of-phaze authored and comma committed Sep 26, 2023
1 parent 68870a8 commit 578480a
Showing 1 changed file with 45 additions and 28 deletions.
73 changes: 45 additions & 28 deletions code/datums/traits/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,62 @@
/mob/living/proc/GetTraits()
SHOULD_NOT_SLEEP(TRUE)
RETURN_TYPE(/list)
return traits

/mob/living/carbon/human/GetTraits()
if(traits)
return traits
return species.traits
var/decl/species/our_species = get_species()
return traits || our_species?.traits

/mob/living/proc/SetTrait(trait_type, trait_level)
SHOULD_NOT_SLEEP(TRUE)
var/decl/species/our_species = get_species()
var/decl/trait/T = GET_DECL(trait_type)
if(!T.validate_level(trait_level))
return FALSE

LAZYSET(traits, trait_type, trait_level)
return TRUE

/mob/living/carbon/human/SetTrait(trait_type, trait_level)
var/decl/trait/T = GET_DECL(trait_type)
if(!T.validate_level(trait_level))
return FALSE

if(!traits) // If traits haven't been setup before, check if we need to do so now
var/species_level = species.traits[trait_type]
if(our_species && !traits) // If species traits haven't been setup before, check if we need to do so now
var/species_level = our_species.traits[trait_type]
if(species_level == trait_level) // Matched the default species trait level, ignore
return TRUE
traits = species.traits.Copy() // The setup is to simply copy the species list of traits
traits = our_species.traits.Copy() // The setup is to simply copy the species list of traits

return ..(trait_type, trait_level)

/mob/living/proc/RemoveTrait(trait_type)
LAZYREMOVE(traits, trait_type)

/mob/living/carbon/human/RemoveTrait(trait_type)
// If traits haven't been setup, but we're trying to remove a trait that exists on the species then setup traits
if(!traits && (trait_type in species.traits))
traits = species.traits.Copy()
LAZYSET(traits, trait_type, trait_level)
return TRUE

..(trait_type) // Could go through the trouble of nulling the traits list if it's again equal to the species list but eh
traits = traits || list() // But we do ensure that humans don't null their traits list, to avoid copying from species again
/mob/living/proc/RemoveTrait(trait_type, canonize = TRUE)
var/decl/species/our_species = get_species()
// If traits haven't been set up, but we're trying to remove a trait that exists on the species then set up traits
if(!traits && LAZYISIN(our_species?.traits, trait_type))
traits = our_species.traits.Copy()
if(LAZYLEN(traits))
LAZYREMOVE(traits, trait_type)
// Check if we can just default back to species traits.
if(canonize)
CanonizeTraits()

/// Removes a trait unless it exists on the species.
/// If it does exist on the species, we reset it to the species' trait level.
/mob/living/proc/RemoveExtrinsicTrait(trait_type)
var/decl/species/our_species = get_species()
if(!LAZYACCESS(our_species?.traits, trait_type))
RemoveTrait(trait_type)
else if(our_species?.traits[trait_type] != GetTraitLevel(trait_type))
SetTrait(trait_type, our_species?.traits[trait_type])

/// Sets the traits list to null if it's identical to the species list.
/// Returns TRUE if the list was reset and FALSE otherwise.
/mob/living/proc/CanonizeTraits()
if(!traits) // Already in canonical form.
return FALSE
var/decl/species/our_species = get_species()
if(!our_species) // Doesn't apply without a species.
return FALSE
var/list/missing_traits = traits ^ our_species?.traits
var/list/matched_traits = traits & our_species?.traits
if(LAZYLEN(missing_traits))
return FALSE
for(var/trait in matched_traits) // inside this loop we know our_species exists and has traits
if(traits[trait] != our_species.traits[trait])
return FALSE
traits = null
return TRUE

/decl/trait
abstract_type = /decl/trait
Expand Down

0 comments on commit 578480a

Please sign in to comment.