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

The Melberting #400

Merged
merged 9 commits into from
Aug 4, 2023
64 changes: 64 additions & 0 deletions code/__DEFINES/status_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,67 @@

#define STASIS_ASCENSION_EFFECT "heretic_ascension"

// Status effect application helpers.
// These are macros for easier use of adjust_timed_status_effect and set_timed_status_effect.
//
// adjust_x:
// - Adds duration to a status effect
// - Removes duration if a negative duration is passed.
// - Ex: adjust_stutter(10 SECONDS) adds ten seconds of stuttering.
// - Ex: adjust_jitter(-5 SECONDS) removes five seconds of jittering, or just removes jittering if less than five seconds exist.
//
// adjust_x_up_to:
// - Will only add (or remove) duration of a status effect up to the second parameter
// - If the duration will result in going beyond the second parameter, it will stop exactly at that parameter
// - The second parameter cannot be negative.
// - Ex: adjust_stutter_up_to(20 SECONDS, 10 SECONDS) adds ten seconds of stuttering.
//
// set_x:
// - Set the duration of a status effect to the exact number.
// - Setting duration to zero seconds is effectively the same as just using remove_status_effect, or qdelling the effect.
// - Ex: set_stutter(10 SECONDS) sets the stuttering to ten seconds, regardless of whether they had more or less existing stutter.
//
// set_x_if_lower:
// - Will only set the duration of that effect IF any existing duration is lower than what was passed.
// - Ex: set_stutter_if_lower(10 SECONDS) will set stuttering to ten seconds if no stuttering or less than ten seconds of stuttering exists
// - Ex: set_jitter_if_lower(20 SECONDS) will do nothing if more than twenty seconds of jittering already exists

#define adjust_stutter(duration) adjust_timed_status_effect(duration, /datum/status_effect/speech/stutter)
#define adjust_stutter_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/speech/stutter, up_to)
#define set_stutter(duration) set_timed_status_effect(duration, /datum/status_effect/speech/stutter)
#define set_stutter_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/speech/stutter, TRUE)

#define adjust_derpspeech(duration) adjust_timed_status_effect(duration, /datum/status_effect/speech/stutter/derpspeech)
#define adjust_derpspeech_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/speech/stutter/derpspeech, up_to)
#define set_derpspeech(duration) set_timed_status_effect(duration, /datum/status_effect/speech/stutter/derpspeech)
#define set_derpspeech_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/speech/stutter/derpspeech, TRUE)

#define adjust_slurring(duration) adjust_timed_status_effect(duration, /datum/status_effect/speech/slurring/generic)
#define adjust_slurring_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/speech/slurring/generic, up_to)
#define set_slurring(duration) set_timed_status_effect(duration, /datum/status_effect/speech/slurring/generic)
#define set_slurring_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/speech/slurring/generic, TRUE)

#define adjust_dizzy(duration) adjust_timed_status_effect(duration, /datum/status_effect/dizziness)
#define adjust_dizzy_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/dizziness, up_to)
#define set_dizzy(duration) set_timed_status_effect(duration, /datum/status_effect/dizziness)
#define set_dizzy_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/dizziness, TRUE)

#define adjust_jitter(duration) adjust_timed_status_effect(duration, /datum/status_effect/jitter)
#define adjust_jitter_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/jitter, up_to)
#define set_jitter(duration) set_timed_status_effect(duration, /datum/status_effect/jitter)
#define set_jitter_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/jitter, TRUE)

#define adjust_confusion(duration) adjust_timed_status_effect(duration, /datum/status_effect/confusion)
#define adjust_confusion_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/confusion, up_to)
#define set_confusion(duration) set_timed_status_effect(duration, /datum/status_effect/confusion)
#define set_confusion_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/confusion, TRUE)

#define adjust_drugginess(duration) adjust_timed_status_effect(duration, /datum/status_effect/drugginess)
#define adjust_drugginess_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/drugginess, up_to)
#define set_drugginess(duration) set_timed_status_effect(duration, /datum/status_effect/drugginess)
#define set_drugginess_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/drugginess, TRUE)

#define adjust_pacifism(duration) adjust_timed_status_effect(/datum/status_effect/pacify, duration)
#define set_pacifism(duration) set_timed_status_effect(/datum/status_effect/pacify, duration)


7 changes: 6 additions & 1 deletion code/_onclick/hud/alert.dm
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
var/mob/living/carbon/offerer
var/obj/item/receiving

/atom/movable/screen/alert/give/Destroy()
offerer = null
receiving = null
return ..()

/**
* Handles assigning most of the variables for the alert that pops up when an item is offered
*
Expand Down Expand Up @@ -876,8 +881,8 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
return TRUE

/atom/movable/screen/alert/Destroy()
. = ..()
severity = 0
master = null
owner = null
screen_loc = ""
return ..()
98 changes: 63 additions & 35 deletions code/datums/components/knockoff.dm
Original file line number Diff line number Diff line change
@@ -1,71 +1,99 @@
///Items with these will have a chance to get knocked off when disarming or being knocked down
/// Items with this component will have a chance to get knocked off
/// (unequipped and sent to the ground) when the wearer is disarmed or knocked down.
/datum/component/knockoff
///Chance to knockoff
/// Chance to knockoff when a knockoff action occurs.
var/knockoff_chance = 100
///Aiming for these zones will cause the knockoff, null means all zones allowed
/// Used in being disarmed.
/// If set, we will only roll the knockoff chance if the disarmer is targeting one of these zones.
/// If unset, any disarm act will cause the knock-off chance to be rolled, no matter the zone targeted.
var/list/target_zones
///Can be only knocked off from these slots, null means all slots allowed
var/list/slots_knockoffable
/// Bitflag used in equip to determine what slots we need to be in to be knocked off.
/// If set, we must be equipped in one of the slots to have a chance of our item being knocked off.
/// If unset / NONE, a disarm or knockdown will have a chance of our item being knocked off regardless of slot, INCLUDING hand slots.
var/slots_knockoffable = NONE

/datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable)
/datum/component/knockoff/Initialize(knockoff_chance = 100, target_zones, slots_knockoffable = NONE)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED,PROC_REF(OnEquipped))
RegisterSignal(parent, COMSIG_ITEM_DROPPED,PROC_REF(OnDropped))

src.knockoff_chance = knockoff_chance
src.target_zones = target_zones
src.slots_knockoffable = slots_knockoffable

if(zone_override)
target_zones = zone_override
/datum/component/knockoff/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped))
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped))

if(slots_knockoffable)
src.slots_knockoffable = slots_knockoffable
/datum/component/knockoff/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))

///Tries to knockoff the item when disarmed
/datum/component/knockoff/proc/Knockoff(mob/living/carbon/human/wearer,mob/living/attacker,zone)
var/obj/item/item_parent = parent
if(ismob(item_parent.loc))
UnregisterSignal(item_parent.loc, list(COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))

/// Signal proc for [COMSIG_HUMAN_DISARM_HIT] on the mob who's equipped our parent
/// Rolls a chance for knockoff whenever we're disarmed
/datum/component/knockoff/proc/on_equipped_mob_disarm(mob/living/carbon/human/source, mob/living/attacker, zone)
SIGNAL_HANDLER

var/obj/item/item = parent
if(!istype(wearer))
if(!istype(source))
return

if(target_zones && !(zone in target_zones))
return
if(!prob(knockoff_chance))
return
if(!wearer.dropItemToGround(item))

var/obj/item/item_parent = parent
if(!source.dropItemToGround(item_parent))
return
wearer.visible_message(span_warning("[attacker] knocks off [wearer]'s [item.name]!"),span_userdanger("[attacker] knocks off your [item.name]!"))

///Tries to knockoff the item when user is knocked down
/datum/component/knockoff/proc/Knockoff_knockdown(mob/living/carbon/human/wearer,amount)
source.visible_message(
span_warning("[attacker] knocks off [source]'s [item_parent.name]!"),
span_userdanger("[attacker] knocks off your [item_parent.name]!"),
)

/// Signal proc for [COMSIG_LIVING_STATUS_KNOCKDOWN] on the mob who's equipped our parent
/// Rolls a chance for knockoff whenever we're knocked down
/datum/component/knockoff/proc/on_equipped_mob_knockdown(mob/living/carbon/human/source, amount)
SIGNAL_HANDLER

if(amount <= 0)
if(!istype(source))
return

var/obj/item/item = parent
if(!istype(wearer))
// Healing knockdown or setting knockdown to zero or something? Don't knock off.
if(amount <= 0)
return
if(!prob(knockoff_chance))
return
if(!wearer.dropItemToGround(item))

var/obj/item/item_parent = parent
if(!source.dropItemToGround(item_parent))
return
wearer.visible_message(span_warning("[wearer]'s [item.name] get[item.p_s()] knocked off!"),span_userdanger("Your [item.name] [item.p_were()] knocked off!"))

source.visible_message(
span_warning("[source]'s [item_parent.name] get[item_parent.p_s()] knocked off!"),
span_userdanger("Your [item_parent.name] [item_parent.p_were()] knocked off!"),
)

/datum/component/knockoff/proc/OnEquipped(datum/source, mob/living/carbon/human/H,slot)
/// Signal proc for [COMSIG_ITEM_EQUIPPED]
/// Registers our signals which can cause a knockdown whenever we're equipped correctly
/datum/component/knockoff/proc/on_equipped(datum/source, mob/living/carbon/human/equipper, slot)
SIGNAL_HANDLER
if(!istype(H))

if(!istype(equipper))
return
if(slots_knockoffable && !(slot in slots_knockoffable))
UnregisterSignal(H, COMSIG_HUMAN_DISARM_HIT)
UnregisterSignal(H, COMSIG_LIVING_STATUS_KNOCKDOWN)

if(slots_knockoffable && !(slot & slots_knockoffable))
UnregisterSignal(equipper, list(COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))
return
RegisterSignal(H, COMSIG_HUMAN_DISARM_HIT, PROC_REF(Knockoff), TRUE)
RegisterSignal(H, COMSIG_LIVING_STATUS_KNOCKDOWN, PROC_REF(Knockoff_knockdown), TRUE)

/datum/component/knockoff/proc/OnDropped(datum/source, mob/living/M)
RegisterSignal(equipper, COMSIG_HUMAN_DISARM_HIT, PROC_REF(on_equipped_mob_disarm), TRUE)
RegisterSignal(equipper, COMSIG_LIVING_STATUS_KNOCKDOWN, PROC_REF(on_equipped_mob_knockdown), TRUE)

/// Signal proc for [COMSIG_ITEM_DROPPED]
/// Unregisters our signals which can cause a knockdown when we're unequipped (dropped)
/datum/component/knockoff/proc/on_dropped(datum/source, mob/living/dropper)
SIGNAL_HANDLER

UnregisterSignal(M, COMSIG_HUMAN_DISARM_HIT)
UnregisterSignal(M, COMSIG_LIVING_STATUS_KNOCKDOWN)
UnregisterSignal(dropper, list(COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))
5 changes: 5 additions & 0 deletions code/datums/elements/frozen.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
if(target_obj.obj_flags & FREEZE_PROOF)
return ELEMENT_INCOMPATIBLE

if(HAS_TRAIT(target_obj, TRAIT_FROZEN))
return ELEMENT_INCOMPATIBLE

ADD_TRAIT(target_obj, TRAIT_FROZEN, ELEMENT_TRAIT(type))
target_obj.name = "frozen [target_obj.name]"
target_obj.add_atom_colour(GLOB.freon_color_matrix, TEMPORARY_COLOUR_PRIORITY)
target_obj.alpha -= 25
Expand All @@ -23,6 +27,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0

/datum/element/frozen/Detach(datum/source, ...)
var/obj/obj_source = source
REMOVE_TRAIT(obj_source, TRAIT_FROZEN, ELEMENT_TRAIT(type))
obj_source.name = replacetext(obj_source.name, "frozen ", "")
obj_source.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, GLOB.freon_color_matrix)
obj_source.alpha += 25
Expand Down
2 changes: 1 addition & 1 deletion code/datums/quirks/negative.dm
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@
if(prob(max(5,(nearby_people*12.5*moodmod)))) //Minimum 1/20 chance of stutter
// Add a short stutter, THEN treat our word
quirker.adjust_timed_status_effect(0.5 SECONDS, /datum/status_effect/speech/stutter)
new_message += quirker.treat_message(word)
new_message += quirker.treat_message(word, capitalize_message = FALSE)

else
new_message += word
Expand Down
1 change: 1 addition & 0 deletions code/datums/status_effects/_status_effect.dm
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
/// or when a status effect with on_remove_on_mob_delete
/// set to FALSE has its mob deleted
/datum/status_effect/proc/be_replaced()
linked_alert = null
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
owner = null
Expand Down
2 changes: 1 addition & 1 deletion code/modules/clothing/glasses/_glasses.dm
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@

/obj/item/clothing/glasses/regular/Initialize(mapload)
. = ..()
AddComponent(/datum/component/knockoff,25,list(BODY_ZONE_PRECISE_EYES),list(ITEM_SLOT_EYES))
AddComponent(/datum/component/knockoff, 25, list(BODY_ZONE_PRECISE_EYES), slot_flags)
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
)
Expand Down
5 changes: 3 additions & 2 deletions code/modules/mob/living/brain/brain_say.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
else
return ..()

/mob/living/brain/treat_message(message)
message = capitalize(message)
/mob/living/brain/treat_message(message, capitalize_message = TRUE)
if(capitalize_message)
message = capitalize(message)
return message
12 changes: 9 additions & 3 deletions code/modules/mob/living/living_say.dm
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,20 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
return TRUE



/mob/living/proc/treat_message(message)
/**
* Treats the passed message with things that may modify speech (stuttering, slurring etc).
*
* message - The message to treat.
* capitalize_message - Whether we run capitalize() on the message after we're done.
*/
/mob/living/proc/treat_message(message, capitalize_message = TRUE)
if(HAS_TRAIT(src, TRAIT_UNINTELLIGIBLE_SPEECH))
message = unintelligize(message)

SEND_SIGNAL(src, COMSIG_LIVING_TREAT_MESSAGE, args)

message = capitalize(message)
if(capitalize_message)
message = capitalize(message)

return message

Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/status_procs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
return 0

/mob/living/proc/Knockdown(amount, ignore_canstun = FALSE) //Can't go below remaining duration
if(SEND_SIGNAL(src, /datum/status_effect/incapacitating/knockdown, amount, ignore_canstun) & COMPONENT_NO_STUN)
if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, ignore_canstun) & COMPONENT_NO_STUN)
return
if(IS_STUN_IMMUNE(src, ignore_canstun))
return
Expand Down
1 change: 1 addition & 0 deletions code/modules/projectiles/aiming.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

register_to_target(target)

RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(target_del))
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(target_del))
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_sight))
RegisterSignal(user, COMSIG_MOB_FIRED_GUN, PROC_REF(user_shot))
Expand Down
2 changes: 1 addition & 1 deletion code/modules/reagents/chemistry/reagents/drink_reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED

/datum/reagent/consumable/tonic/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjust_timed_status_effect(10 SECONDS * REM * delta_time, /datum/status_effect/dizziness)
M.adjust_timed_status_effect(-10 SECONDS * REM * delta_time, /datum/status_effect/dizziness)
M.adjust_drowsyness(-3 * REM * delta_time)
M.AdjustSleeping(-40 * REM * delta_time)
M.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * delta_time, M.get_body_temp_normal())
Expand Down
1 change: 1 addition & 0 deletions code/modules/unit_tests/_unit_tests.dm
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
#include "hydroponics_harvest.dm"
#include "hydroponics_self_mutations.dm"
#include "keybinding_init.dm"
#include "knockoff_component.dm"
#include "load_map_security.dm"
#include "machine_disassembly.dm"
#include "mapping.dm"
Expand Down
Loading
Loading