mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-13 08:56:49 +01:00
acdbcad005
This PR adds new Cross-Skill Interactions for both Cooking and Xenobiology, the latter of which now provides a new Situational Skill Modifier. Cooking Skill now causes animals butchered by the character to drop additional meat. A pretty simple small interaction that doesn't change much in the grand scheme of things. Xenobiology has gained two new interactions, aimed at making it a skill "potentially useful" for players who think their character might be fighting Space Fauna. The first is that it provides a melee damage modifier (which can offset the penalties from low melee skill), but only when attacking Space Fauna (that aren't player controlled). Normally direct damage modifiers are very hard to balance as a consequence of brainmed, but since this applies exclusively to a PVE interaction, the balance concerns are significantly lessened. Its second new interaction is to situationally modify the amount of butchering products gained from Space Fauna (and only Space Fauna). Particularly in the case of Xenobiology, this helps position the skill in such a way that it provides Opportunity Cost for characters in Cooking, Mining, and Security (to a much lesser extent, given they almost never engage carp in melee). If points spent in Xenobiology helps a miner fight off space fauna, then points spent in Surgery are not points they're spending on being better at fighting carp. Almost all of the skills in general should have care put into making sure that they can provide viable Opportunity Cost against other skills in their same category. Cross-Skill Interactions like this are an incredibly effective method of doing so. --------- Signed-off-by: VMSolidus <evilexecutive@gmail.com>
232 lines
7.4 KiB
Plaintext
232 lines
7.4 KiB
Plaintext
#define SIGNAL_ADDTRAIT(trait_ref) "addtrait [trait_ref]"
|
|
#define SIGNAL_REMOVETRAIT(trait_ref) "removetrait [trait_ref]"
|
|
// trait accessor defines
|
|
#define ADD_TRAIT(target, trait, source) \
|
|
do { \
|
|
var/list/_L; \
|
|
if (!target.status_traits) { \
|
|
target.status_traits = list(); \
|
|
_L = target.status_traits; \
|
|
_L[trait] = list(source); \
|
|
SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \
|
|
} else { \
|
|
_L = target.status_traits; \
|
|
if (_L[trait]) { \
|
|
_L[trait] |= list(source); \
|
|
} else { \
|
|
_L[trait] = list(source); \
|
|
SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
#define REMOVE_TRAIT(target, trait, sources) \
|
|
do { \
|
|
var/list/_L = target.status_traits; \
|
|
var/list/_S; \
|
|
if (sources && !islist(sources)) { \
|
|
_S = list(sources); \
|
|
} else { \
|
|
_S = sources\
|
|
}; \
|
|
if (_L && _L[trait]) { \
|
|
for (var/_T in _L[trait]) { \
|
|
if ((!_S && (_T != ROUNDSTART_TRAIT)) || (_T in _S)) { \
|
|
_L[trait] -= _T \
|
|
} \
|
|
};\
|
|
if (!length(_L[trait])) { \
|
|
_L -= trait; \
|
|
SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \
|
|
}; \
|
|
if (!length(_L)) { \
|
|
target.status_traits = null \
|
|
}; \
|
|
} \
|
|
} while (0)
|
|
#define REMOVE_TRAIT_NOT_FROM(target, trait, sources) \
|
|
do { \
|
|
var/list/_traits_list = target.status_traits; \
|
|
var/list/_sources_list; \
|
|
if (sources && !islist(sources)) { \
|
|
_sources_list = list(sources); \
|
|
} else { \
|
|
_sources_list = sources\
|
|
}; \
|
|
if (_traits_list && _traits_list[trait]) { \
|
|
for (var/_trait_source in _traits_list[trait]) { \
|
|
if (!(_trait_source in _sources_list)) { \
|
|
_traits_list[trait] -= _trait_source \
|
|
} \
|
|
};\
|
|
if (!length(_traits_list[trait])) { \
|
|
_traits_list -= trait; \
|
|
SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \
|
|
}; \
|
|
if (!length(_traits_list)) { \
|
|
target.status_traits = null \
|
|
}; \
|
|
} \
|
|
} while (0)
|
|
#define REMOVE_TRAITS_NOT_IN(target, sources) \
|
|
do { \
|
|
var/list/_L = target.status_traits; \
|
|
var/list/_S = sources; \
|
|
if (_L) { \
|
|
for (var/_T in _L) { \
|
|
_L[_T] &= _S;\
|
|
if (!length(_L[_T])) { \
|
|
_L -= _T; \
|
|
SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T), _T); \
|
|
}; \
|
|
};\
|
|
if (!length(_L)) { \
|
|
target.status_traits = null\
|
|
};\
|
|
}\
|
|
} while (0)
|
|
#define REMOVE_TRAITS_IN(target, sources) \
|
|
do { \
|
|
var/list/_L = target.status_traits; \
|
|
var/list/_S = sources; \
|
|
if (sources && !islist(sources)) { \
|
|
_S = list(sources); \
|
|
} else { \
|
|
_S = sources\
|
|
}; \
|
|
if (_L) { \
|
|
for (var/_T in _L) { \
|
|
_L[_T] -= _S;\
|
|
if (!length(_L[_T])) { \
|
|
_L -= _T; \
|
|
SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T)); \
|
|
}; \
|
|
};\
|
|
if (!length(_L)) { \
|
|
target.status_traits = null\
|
|
};\
|
|
}\
|
|
} while (0)
|
|
#define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE)
|
|
#define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE)
|
|
#define HAS_TRAIT_FROM_ONLY(target, trait, source) (\
|
|
target.status_traits ?\
|
|
(target.status_traits[trait] ?\
|
|
((source in target.status_traits[trait]) && (length(target.status_traits) == 1))\
|
|
: FALSE)\
|
|
: FALSE)
|
|
#define HAS_TRAIT_NOT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (length(target.status_traits[trait] - source) > 0) : FALSE) : FALSE)
|
|
|
|
// common trait sources
|
|
#define TRAIT_GENERIC "generic"
|
|
#define GENERIC_ITEM_TRAIT "generic_item"
|
|
#define DISABILITY_TRAIT "disability"
|
|
|
|
#define TRAIT_SOURCE_INHERENT "t_s_inherent"
|
|
/// cannot be removed without admin intervention
|
|
#define ROUNDSTART_TRAIT "roundstart"
|
|
#define CULTURE_TRAIT "culture"
|
|
|
|
#define INNATE_TRAIT "innate"
|
|
|
|
//important_recursive_contents traits
|
|
/*
|
|
* Used for movables that need to be updated, via COMSIG_ENTER_AREA and COMSIG_EXIT_AREA, when transitioning areas.
|
|
* Use [/atom/movable/proc/become_area_sensitive(trait_source)] to properly enable it. How you remove it isn't as important.
|
|
*/
|
|
#define TRAIT_AREA_SENSITIVE "area-sensitive"
|
|
|
|
// every hearing sensitive atom has this trait
|
|
#define TRAIT_HEARING_SENSITIVE "hearing_sensitive"
|
|
|
|
/// forces the mob to speak gibberish, like highly damaged borgs
|
|
#define TRAIT_SPEAKING_GIBBERISH "speaking_gibberish"
|
|
|
|
/// Mob does not need to breathe.
|
|
#define TRAIT_NO_BREATHE "no_breathe"
|
|
|
|
/// Mob has pressure immunity.
|
|
#define TRAIT_PRESSURE_IMMUNITY "pressure_immunity"
|
|
|
|
/// Trait sourced from changeling abilities.
|
|
#define TRAIT_SOURCE_CHANGELING "changeling"
|
|
|
|
/// Mob is psionically deaf.
|
|
#define TRAIT_PSIONICALLY_DEAF "psionically_deaf"
|
|
|
|
/// Zona bovinae absorbed, used by Loner to track a mob that has had its ZB consumed. Doesn't make them psi-deaf.
|
|
#define TRAIT_ZONA_BOVINAE_ABSORBED "bovinae_absorbed"
|
|
|
|
/// lets mobs that traditionally don't hallucinate, hallucinate
|
|
#define TRAIT_BYPASS_HALLUCINATION_RESTRICTION "bypassing_hallucination_restriction"
|
|
|
|
/// This mob should never close UI even if it doesn't have a client
|
|
#define TRAIT_PRESERVE_UI_WITHOUT_CLIENT "preserve_ui_without_client"
|
|
|
|
/// when mobs are viewing something via a computer, currently used for the helm computer
|
|
#define TRAIT_COMPUTER_VIEW "computer_view"
|
|
|
|
// IPC OVERLOADER OVERDOSE STATES
|
|
#define TRAIT_SOURCE_OVERLOADER "overloader"
|
|
#define TRAIT_OVERLOADER_OD_INITIAL "overloader_od_initial"
|
|
#define TRAIT_OVERLOADER_OD_MEDIUM "overloader_od_medium"
|
|
#define TRAIT_OVERLOADER_OD_EFFECT "overloader_od_effect"
|
|
|
|
/// Traits given by psionics.
|
|
#define TRAIT_SOURCE_PSIONICS "psionics"
|
|
|
|
/// Traits given by augments
|
|
#define TRAIT_SOURCE_AUGMENT "augment"
|
|
|
|
/// This trait makes Check_Shoegrip return TRUE. Used for magboot-like behaviour.
|
|
#define TRAIT_SHOE_GRIP "shoe_grip"
|
|
|
|
/// Trait is added from a species verb.
|
|
#define TRAIT_SOURCE_SPECIES_VERB "species_verb"
|
|
|
|
// DISABILITY TRAITS
|
|
|
|
/// Causes the mob to take twice as long to clot their wounds
|
|
#define TRAIT_DISABILITY_HEMOPHILIA "disability_hemophilia"
|
|
|
|
/// Causes the mob to never clot their wounds
|
|
#define TRAIT_DISABILITY_HEMOPHILIA_MAJOR "disability_hemophilia_major"
|
|
|
|
/// hnnnnnnnggggg..... you're pretty good....
|
|
#define TRAIT_NICE_SHOT "nice_shot"
|
|
/// Mobs with this trait cannot be hit by projectiles, meaning the projectiles will just go through.
|
|
#define TRAIT_UNHITTABLE_BY_PROJECTILES "unhittable_by_projectiles"
|
|
///This mob is currently blocking a projectile.
|
|
#define TRAIT_BLOCKING_PROJECTILES "blocking_projectiles"
|
|
|
|
/// This trait is used for double shuttle seats in a single tile, used in handling occupant density.
|
|
#define TRAIT_DOUBLE_SEATS "double_seats"
|
|
|
|
/// Apply this to make a mob passable by other mobs.
|
|
#define TRAIT_UNDENSE "undense"
|
|
|
|
/// Trait comes from leaning on a wall.
|
|
#define TRAIT_SOURCE_WALL_LEANING "wall_leaning"
|
|
|
|
/// Phoron worm burrow.
|
|
#define TRAIT_SOURCE_WORM_BURROW "worm_burrow"
|
|
|
|
/// Trait given on mob death.
|
|
#define TRAIT_SOURCE_MOB_DEATH "mob_death"
|
|
|
|
/// Trait given when the mob lies down.
|
|
#define TRAIT_SOURCE_LYING_DOWN "lying_down"
|
|
|
|
/// A trait gained by leaning against something
|
|
#define TRAIT_LEANING "leaning"
|
|
|
|
/// traits transparent turf
|
|
#define TURF_Z_TRANSPARENT_TRAIT "turf_z_transparent"
|
|
|
|
/// Unlinks gliding from movement speed, meaning that there will be a delay between movements rather than a single move movement between tiles
|
|
#define TRAIT_NO_GLIDE "no_glide"
|
|
|
|
// MOB CATEGORY traits used for pattern matching certain subtypes of mobs
|
|
#define TRAIT_SOURCE_MOB_CATEGORY "mob_category"
|
|
/// All "Space Fauna" EG: Space Carp
|
|
#define TRAIT_MC_SPACE_FAUNA "space_fauna"
|