Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

/tg/ Status Effects Prelude A - Updated Trait Backend #4869

Merged
merged 3 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions code/__DEFINES/assert.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#undef ASSERT

/// Override BYOND's native ASSERT to optionally specify a message
#define ASSERT(condition, message...) \
if (!(condition)) { \
CRASH(assertion_message(__FILE__, __LINE__, #condition, ##message)) \
}

/proc/assertion_message(file, line, condition, message)
if (!isnull(message))
message = " - [message]"

return "[file]:[line]:Assertion failed: [condition][message]"
5 changes: 5 additions & 0 deletions code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
///from base of mob/set_stat(): (new_stat, old_stat)
#define COMSIG_MOB_STATCHANGE "mob_statchange"
/// From /obj/structure/machinery/door/airlock/proc/take_damage
#define COMSIG_MOB_DESTROY_AIRLOCK "mob_destroy_airlock"

Expand Down Expand Up @@ -128,3 +130,6 @@

/// From /obj/item/proc/pickup() : (obj/item/picked_up)
#define COMSIG_MOB_PICKUP_ITEM "mob_pickup_item"

/// Cancels all running cloaking effects on target
#define COMSIG_MOB_EFFECT_CLOAK_CANCEL "mob_effect_cloak_cancel"
105 changes: 51 additions & 54 deletions code/__DEFINES/traits.dm
Original file line number Diff line number Diff line change
@@ -1,84 +1,94 @@
//shamelessly ripped from TG
#define SIGNAL_ADDTRAIT(trait_ref) "addtrait [trait_ref]"
#define SIGNAL_REMOVETRAIT(trait_ref) "removetrait [trait_ref]"

// trait accessor defines
//here be dragons
#define ADD_TRAIT(target, trait, source) \
do { \
var/list/_L; \
if (!target.status_traits) { \
target.status_traits = list(); \
_L = target.status_traits; \
if (!target._status_traits) { \
target._status_traits = list(); \
_L = target._status_traits; \
_L[trait] = list(source); \
SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \
if(trait in GLOB.traits_with_elements){ \
target.AddElement(GLOB.traits_with_elements[trait]); \
} \
} else { \
_L = target.status_traits; \
_L = target._status_traits; \
if (_L[trait]) { \
_L[trait] |= list(source); \
} else { \
_L[trait] = list(source); \
SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \
if(trait in GLOB.traits_with_elements){ \
target.AddElement(GLOB.traits_with_elements[trait]); \
} \
} \
} \
} while (0)
#define REMOVE_TRAIT(target, trait, sources) \
do { \
var/list/_L = target.status_traits; \
var/list/_L = target._status_traits; \
var/list/_S; \
if (sources && !islist(sources)) { \
_S = list(sources); \
} else { \
_S = sources\
}; \
if (_L && _L[trait]) { \
if (_L?[trait]) { \
for (var/_T in _L[trait]) { \
if ((!_S && (_T != TRAIT_SOURCE_QUIRK)) || (_T in _S)) { \
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(trait in GLOB.traits_with_elements) { \
target.RemoveElement(GLOB.traits_with_elements[trait]); \
} \
}; \
if (!length(_L)) { \
target.status_traits = null \
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?[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/_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(_T in GLOB.traits_with_elements) { \
target.RemoveElement(GLOB.traits_with_elements[_T]); \
}; \
};\
};\
if (!length(_L)) { \
target.status_traits = null\
target._status_traits = null\
};\
}\
} while (0)

#define REMOVE_TRAITS_IN(target, sources) \
do { \
var/list/_L = target.status_traits; \
var/list/_L = target._status_traits; \
var/list/_S = sources; \
if (sources && !islist(sources)) { \
_S = list(sources); \
Expand All @@ -91,45 +101,32 @@
if (!length(_L[_T])) { \
_L -= _T; \
SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T)); \
if(_T in GLOB.traits_with_elements) { \
target.RemoveElement(GLOB.traits_with_elements[_T]); \
}; \
};\
};\
if (!length(_L)) { \
target.status_traits = null\
target._status_traits = null\
};\
}\
} while (0)

/// Will 100% nuke a trait regardless of source. Preferably use this as little as possible
#define REMOVE_TRAIT_ALLSOURCES(target, trait) \
do { \
var/list/_L = target.status_traits; \
if (_L?[trait]) { \
if (length(_L)) { \
_L -= trait; \
SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \
}; \
else { \
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)

#define HAS_TRAIT(target, trait) (target._status_traits?[trait] ? TRUE : FALSE)
#define HAS_TRAIT_FROM(target, trait, source) (HAS_TRAIT(target, trait) && (source in target._status_traits[trait]))
#define HAS_TRAIT_FROM_ONLY(target, trait, source) (HAS_TRAIT(target, trait) && (source in target._status_traits[trait]) && (length(target._status_traits[trait]) == 1))
#define HAS_TRAIT_NOT_FROM(target, trait, source) (HAS_TRAIT(target, trait) && (length(target._status_traits[trait] - source) > 0))
/// Returns a list of trait sources for this trait. Only useful for wacko cases and internal futzing
/// You should not be using this
#define GET_TRAIT_SOURCES(target, trait) (target._status_traits?[trait] || list())
/// Returns the amount of sources for a trait. useful if you don't want to have a "thing counter" stuck around all the time
#define COUNT_TRAIT_SOURCES(target, trait) length(GET_TRAIT_SOURCES(target, trait))
/// A simple helper for checking traits in a mob's mind
#define HAS_MIND_TRAIT(target, trait) (HAS_TRAIT(target, trait) || (target.mind ? HAS_TRAIT(target.mind, trait) : FALSE))

/// Example trait
// #define TRAIT_X "t_x"

/// cannot be removed without admin intervention
#define ROUNDSTART_TRAIT "roundstart"

//-- mob traits --
// SPECIES TRAITS
/// Knowledge of Yautja technology
Expand Down
7 changes: 0 additions & 7 deletions code/__HELPERS/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@
if(I.assignment in GLOB.joblist) return I.assignment
return "Unknown"

/proc/FindNameFromID(mob/living/carbon/human/H)
ASSERT(istype(H))
var/obj/item/card/id/I = H.wear_id
if(istype(I)) return I.registered_name
I = H.get_active_hand()
if(istype(I)) return I.registered_name

/proc/get_all_job_icons() return GLOB.joblist + list("Prisoner")//For all existing HUD icons

/obj/proc/GetJobName() //Used in secHUD icon generation
Expand Down
43 changes: 43 additions & 0 deletions code/__HELPERS/traits.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#define TRAIT_CALLBACK_ADD(target, trait, source) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___TraitAdd), ##target, ##trait, ##source)
#define TRAIT_CALLBACK_REMOVE(target, trait, source) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___TraitRemove), ##target, ##trait, ##source)

///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback.
/proc/___TraitAdd(target,trait,source)
if(!target || !trait || !source)
return
if(islist(target))
for(var/i in target)
if(!isatom(i))
continue
var/atom/the_atom = i
ADD_TRAIT(the_atom,trait,source)
else if(isatom(target))
var/atom/the_atom2 = target
ADD_TRAIT(the_atom2,trait,source)

///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback.
/proc/___TraitRemove(target,trait,source)
if(!target || !trait || !source)
return
if(islist(target))
for(var/i in target)
if(!isatom(i))
continue
var/atom/the_atom = i
REMOVE_TRAIT(the_atom,trait,source)
else if(isatom(target))
var/atom/the_atom2 = target
REMOVE_TRAIT(the_atom2,trait,source)


/// Proc that handles adding multiple traits to a target via a list. Must have a common source and target.
/datum/proc/add_traits(list/list_of_traits, source)
ASSERT(islist(list_of_traits), "Invalid arguments passed to add_traits! Invoked on [src] with [list_of_traits], source being [source].")
for(var/trait in list_of_traits)
ADD_TRAIT(src, trait, source)

/// Proc that handles removing multiple traits from a target via a list. Must have a common source and target.
/datum/proc/remove_traits(list/list_of_traits, source)
ASSERT(islist(list_of_traits), "Invalid arguments passed to remove_traits! Invoked on [src] with [list_of_traits], source being [source].")
for(var/trait in list_of_traits)
REMOVE_TRAIT(src, trait, source)
4 changes: 2 additions & 2 deletions code/datums/datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

/// Active timers with this datum as the target
var/list/active_timers
/// Status traits attached.
var/list/status_traits
/// Status traits attached to this datum. associative list of the form: list(trait name (string) = list(source1, source2, source3,...))
var/list/_status_traits

/**
* Components attached to this datum
Expand Down
14 changes: 0 additions & 14 deletions code/game/objects/items/handcuffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,6 @@
if(!C.handcuffed)
place_handcuffs(C, user)

/obj/item/handcuffs/obj/structure/MouseDrop(mob/living/carbon/human/H)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cursed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, that's why i'm getting rid of it on the spot

var/mob/living/carbon/human/user = usr
if (!istype(user))
return
if (user.stat || get_dist(user, src) > 1 || get_dist(user, H) > 1 || H.lying)
return
if (!istype(H))
return

if(!do_after(user, cuff_delay, INTERRUPT_ALL, BUSY_ICON_HOSTILE, H, INTERRUPT_MOVED, BUSY_ICON_GENERIC))
return

// TODO: apply handcuffs

/obj/item/handcuffs/get_mob_overlay(mob/user_mob, slot)
var/image/ret = ..()

Expand Down
5 changes: 4 additions & 1 deletion code/game/objects/items/storage/backpack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r

RegisterSignal(H, COMSIG_GRENADE_PRE_PRIME, PROC_REF(cloak_grenade_callback))
RegisterSignal(H, COMSIG_HUMAN_EXTINGUISH, PROC_REF(wrapper_fizzle_camouflage))
RegisterSignal(H, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(deactivate_camouflage))

camo_active = TRUE
ADD_TRAIT(H, TRAIT_CLOAKED, TRAIT_SOURCE_EQUIPMENT(WEAR_BACK))
Expand Down Expand Up @@ -774,12 +775,14 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r
deactivate_camouflage(wearer, TRUE, TRUE)

/obj/item/storage/backpack/marine/satchel/scout_cloak/proc/deactivate_camouflage(mob/living/carbon/human/H, anim = TRUE, forced)
SIGNAL_HANDLER
if(!istype(H))
return FALSE

UnregisterSignal(H, list(
COMSIG_GRENADE_PRE_PRIME,
COMSIG_HUMAN_EXTINGUISH
COMSIG_HUMAN_EXTINGUISH,
COMSIG_MOB_EFFECT_CLOAK_CANCEL,
))

if(forced)
Expand Down
4 changes: 2 additions & 2 deletions code/modules/admin/admin.dm
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
if("Remove")
if(!GLOB.trait_name_map)
GLOB.trait_name_map = generate_trait_name_map()
for(var/trait in D.status_traits)
for(var/trait in D._status_traits)
var/name = GLOB.trait_name_map[trait] || trait
available_traits[name] = trait

Expand All @@ -282,7 +282,7 @@
if("All")
source = null
if("Specific")
source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D.status_traits[chosen_trait])
source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D._status_traits[chosen_trait])
if(!source)
return
REMOVE_TRAIT(D,chosen_trait,source)
2 changes: 2 additions & 0 deletions code/modules/cm_preds/yaut_bracers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@

RegisterSignal(M, COMSIG_HUMAN_EXTINGUISH, PROC_REF(wrapper_fizzle_camouflage))
RegisterSignal(M, COMSIG_HUMAN_PRE_BULLET_ACT, PROC_REF(bullet_hit))
RegisterSignal(M, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(decloak))

cloak_timer = world.time + 1.5 SECONDS
if(true_cloak)
Expand Down Expand Up @@ -614,6 +615,7 @@

UnregisterSignal(user, COMSIG_HUMAN_EXTINGUISH)
UnregisterSignal(user, COMSIG_HUMAN_PRE_BULLET_ACT)
UnregisterSignal(user, COMSIG_MOB_EFFECT_CLOAK_CANCEL)

var/decloak_timer = (DECLOAK_STANDARD * force_multipler)
if(forced)
Expand Down
4 changes: 2 additions & 2 deletions code/modules/cm_preds/yaut_items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -430,12 +430,12 @@

if(do_after(user, 10 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC))
// Display fancy animation for you and the person you might be pulling (Legacy)
REMOVE_TRAIT_ALLSOURCES(user, TRAIT_CLOAKED)
SEND_SIGNAL(user, COMSIG_MOB_EFFECT_CLOAK_CANCEL)
user.visible_message(SPAN_WARNING("[icon2html(user, viewers(src))][user] disappears!"))
var/tele_time = animation_teleport_quick_out(user)
var/mob/living/M = user.pulling
if(istype(M)) // Pulled person
REMOVE_TRAIT_ALLSOURCES(M, TRAIT_CLOAKED)
SEND_SIGNAL(M, COMSIG_MOB_EFFECT_CLOAK_CANCEL)
M.visible_message(SPAN_WARNING("[icon2html(M, viewers(src))][M] disappears!"))
animation_teleport_quick_out(M)

Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@
if(!new_hive)
return

for(var/T in status_traits)
for(var/T in _status_traits) // They can't keep getting away with this!!!
REMOVE_TRAIT(src, T, TRAIT_SOURCE_HIVE)

new_hive.add_xeno(src)
Expand Down
Loading