#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" /// 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" /// Hidden from Psi-Search. #define TRAIT_PSIONIC_SUPPRESSION "psionic_suppression" /// 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"