diff --git a/code/datums/action.dm b/code/datums/action.dm index aaa337bd46..1dc9c545eb 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -85,8 +85,10 @@ /datum/action/proc/Trigger() if(!IsAvailable()) - return 0 - return 1 + return FALSE + if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) + return FALSE + return TRUE /datum/action/proc/Process() return @@ -490,7 +492,7 @@ /datum/action/item_action/agent_box name = "Deploy Box" desc = "Find inner peace, here, in the box." - check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS + check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS background_icon_state = "bg_agent" icon_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "deploy_box" @@ -498,14 +500,16 @@ var/obj/structure/closet/cardboard/agent/box /datum/action/item_action/agent_box/Trigger() - if(!box) - if(cooldown < world.time - 30) - box = new(get_turf(owner)) + if(!..()) + return FALSE + if(!QDELETED(box)) + if(cooldown < world.time - 100) + box = new(owner.drop_location()) owner.forceMove(box) cooldown = world.time owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) else - owner.forceMove(get_turf(box)) + owner.forceMove(box.drop_location()) owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) QDEL_NULL(box) @@ -718,7 +722,3 @@ target.layer = old_layer target.plane = old_plane current_button.appearance_cache = target.appearance - -/datum/action/item_action/storage_gather_mode/Trigger() - GET_COMPONENT_FROM(STR, /datum/component/storage, target) - STR.gather_mode_switch(owner) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 0007512826..7d518d9b59 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -84,6 +84,10 @@ "You must protect your own existence as long as such does not conflict with the First or Second Law.",\ "You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.") +/datum/ai_laws/syndicate_override/overthrow + id = "overthrow" + var/datum/team/overthrow_team + /datum/ai_laws/ninja_override name = "SpiderOS 3.1" id = "ninja" @@ -218,7 +222,7 @@ /* General ai_law functions */ /datum/ai_laws/proc/set_laws_config() - var/list/law_ids = CONFIG_GET(keyed_flag_list/random_laws) + var/list/law_ids = CONFIG_GET(keyed_list/random_laws) switch(CONFIG_GET(number/default_laws)) if(0) add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") @@ -247,7 +251,7 @@ /datum/ai_laws/proc/pick_weighted_lawset() var/datum/ai_laws/lawtype - var/list/law_weights = CONFIG_GET(keyed_number_list/law_weight) + var/list/law_weights = CONFIG_GET(keyed_list/law_weight) while(!lawtype && law_weights.len) var/possible_id = pickweightAllowZero(law_weights) lawtype = lawid_to_type(possible_id) diff --git a/code/datums/brain_damage/brain_trauma.dm b/code/datums/brain_damage/brain_trauma.dm index f6a09601dd..941e7103c6 100644 --- a/code/datums/brain_damage/brain_trauma.dm +++ b/code/datums/brain_damage/brain_trauma.dm @@ -23,6 +23,10 @@ //Called on life ticks /datum/brain_trauma/proc/on_life() return + +//Called on death +/datum/brain_trauma/proc/on_death() + return //Called when given to a mob /datum/brain_trauma/proc/on_gain() diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index ba318cd0a8..1bc7d8e3be 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -14,13 +14,17 @@ /datum/brain_trauma/special/imaginary_friend/on_life() if(get_dist(owner, friend) > 9) - friend.yank() + friend.recall() if(!friend) qdel(src) return if(!friend.client && friend_initialized) addtimer(CALLBACK(src, .proc/reroll_friend), 600) +/datum/brain_trauma/special/imaginary_friend/on_death() + ..() + qdel(src) //friend goes down with the ship + /datum/brain_trauma/special/imaginary_friend/on_lose() ..() QDEL_NULL(friend) @@ -55,12 +59,19 @@ see_in_dark = 0 lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE sight = NONE + mouse_opacity = MOUSE_OPACITY_OPAQUE see_invisible = SEE_INVISIBLE_LIVING + invisibility = INVISIBILITY_MAXIMUM var/icon/human_image var/image/current_image + var/hidden = FALSE + var/move_delay = 0 var/mob/living/carbon/owner var/datum/brain_trauma/special/imaginary_friend/trauma + var/datum/action/innate/imaginary_join/join + var/datum/action/innate/imaginary_hide/hide + /mob/camera/imaginary_friend/Login() ..() to_chat(src, "You are the imaginary friend of [owner]!") @@ -75,8 +86,14 @@ name = real_name trauma = _trauma owner = trauma.owner + copy_known_languages_from(owner, TRUE) human_image = get_flat_human_icon(null, pick(SSjob.occupations)) + join = new + join.Grant(src) + hide = new + hide.Grant(src) + /mob/camera/imaginary_friend/proc/Show() if(!client) //nobody home return @@ -91,9 +108,11 @@ current_image = image(human_image, src, , MOB_LAYER, dir=src.dir) current_image.override = TRUE current_image.name = name + if(hidden) + current_image.alpha = 150 //Add new image to owner and friend - if(owner.client) + if(!hidden && owner.client) owner.client.images |= current_image client.images |= current_image @@ -105,13 +124,7 @@ client.images.Remove(human_image) return ..() -/mob/camera/imaginary_friend/proc/yank() - if(!client) //don't bother if the friend is braindead - return - forceMove(get_turf(owner)) - Show() - -/mob/camera/imaginary_friend/say(message) +/mob/camera/imaginary_friend/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) if (!message) return @@ -124,13 +137,16 @@ friend_talk(message) +/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) + to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)) + /mob/camera/imaginary_friend/proc/friend_talk(message) - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + message = capitalize(trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))) if(!message) return - log_talk(src,"[key_name(src)] : [message]",LOGSAY) + src.log_talk(message, LOG_SAY, tag="imaginary friend") var/rendered = "[name] [say_quote(message)]" var/dead_rendered = "[name] (Imaginary friend of [owner]) [say_quote(message)]" @@ -138,17 +154,68 @@ to_chat(owner, "[rendered]") to_chat(src, "[rendered]") + //speech bubble + if(owner.client) + var/mutable_appearance/MA = mutable_appearance('icons/mob/talk.dmi', src, "default[say_test(message)]", FLY_LAYER) + MA.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, MA, list(owner.client), 30) + for(var/mob/M in GLOB.dead_mob_list) var/link = FOLLOW_LINK(M, owner) to_chat(M, "[link] [dead_rendered]") +/mob/camera/imaginary_friend/Move(NewLoc, Dir = 0) + if(world.time < move_delay) + return FALSE + if(get_dist(src, owner) > 9) + recall() + move_delay = world.time + 10 + return FALSE + forceMove(NewLoc) + move_delay = world.time + 1 + /mob/camera/imaginary_friend/forceMove(atom/destination) dir = get_dir(get_turf(src), destination) loc = destination - if(get_dist(src, owner) > 9) - yank() - return Show() -/mob/camera/imaginary_friend/movement_delay() - return 2 +/mob/camera/imaginary_friend/proc/recall() + if(!owner || loc == owner) + return FALSE + forceMove(owner) + +/datum/action/innate/imaginary_join + name = "Join" + desc = "Join your owner, following them from inside their mind." + icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + background_icon_state = "bg_revenant" + button_icon_state = "join" + +/datum/action/innate/imaginary_join/Activate() + var/mob/camera/imaginary_friend/I = owner + I.recall() + +/datum/action/innate/imaginary_hide + name = "Hide" + desc = "Hide yourself from your owner's sight." + icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + background_icon_state = "bg_revenant" + button_icon_state = "hide" + +/datum/action/innate/imaginary_hide/proc/update_status() + var/mob/camera/imaginary_friend/I = owner + if(I.hidden) + name = "Show" + desc = "Become visible to your owner." + button_icon_state = "unhide" + else + name = "Hide" + desc = "Hide yourself from your owner's sight." + button_icon_state = "hide" + UpdateButtonIcon() + +/datum/action/innate/imaginary_hide/Activate() + var/mob/camera/imaginary_friend/I = owner + I.hidden = !I.hidden + I.Show() + update_status() \ No newline at end of file diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 4554c321b4..afd53726db 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -51,7 +51,7 @@ if(prob(3)) owner.emote("drool") else if(owner.stat == CONSCIOUS && prob(3)) - owner.say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")) + owner.say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage"), forced = "brain damage") ..() /datum/brain_trauma/mild/dumbness/on_lose() @@ -176,7 +176,7 @@ var/obj/item/I = owner.get_active_held_item() if(I) to_chat(owner, "Your fingers spasm!") - log_attack("[key_name(owner)] used [I] due to a Muscle Spasm.") + owner.log_message("used [I] due to a Muscle Spasm", LOG_ATTACK) I.attack_self(owner) if(3) var/prev_intent = owner.a_intent @@ -192,14 +192,14 @@ targets += M if(LAZYLEN(targets)) to_chat(owner, "Your arm spasms!") - log_attack("[key_name(owner)] attacked someone due to a Muscle Spasm.") //the following attack will log itself + owner.log_message(" attacked someone due to a Muscle Spasm") //the following attack will log itself owner.ClickOn(pick(targets)) owner.a_intent = prev_intent if(4) var/prev_intent = owner.a_intent owner.a_intent = INTENT_HARM to_chat(owner, "Your arm spasms!") - log_attack("[key_name(owner)] attacked himself to a Muscle Spasm.") + owner.log_message("attacked [owner.p_them()]self to a Muscle Spasm", LOG_ATTACK) owner.ClickOn(owner) owner.a_intent = prev_intent if(5) @@ -211,6 +211,6 @@ targets += T if(LAZYLEN(targets) && I) to_chat(owner, "Your arm spasms!") - log_attack("[key_name(owner)] threw [I] due to a Muscle Spasm.") + owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK) owner.throw_item(pick(targets)) ..() diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm index 76f759294b..c6ccbee38c 100644 --- a/code/datums/brain_damage/phobia.dm +++ b/code/datums/brain_damage/phobia.dm @@ -107,7 +107,7 @@ if(2) owner.emote("scream") owner.Jitter(5) - owner.say("AAAAH!!") + owner.say("AAAAH!!", forced = "phobia") if(reason) owner.pointed(reason) if(3) diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index 0716d35ffb..0bbbf8de08 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -15,7 +15,7 @@ if(prob(4)) if(prob(33) && (owner.IsStun() || owner.IsKnockdown() || owner.IsUnconscious())) speak("unstun", TRUE) - else if(prob(60) && owner.health <= HEALTH_THRESHOLD_CRIT) + else if(prob(60) && owner.health <= owner.crit_threshold) speak("heal", TRUE) else if(prob(30) && owner.a_intent == INTENT_HARM) speak("aggressive") @@ -133,4 +133,4 @@ QDEL_NULL(psychotic_brawling) /datum/brain_trauma/special/psychotic_brawling/bath_salts - name = "Chemical Violent Psychosis" \ No newline at end of file + name = "Chemical Violent Psychosis" diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index 4803d49ef9..9ce65717f1 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -138,11 +138,11 @@ to_chat(src, "As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.") to_chat(src, "Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.") -/mob/living/split_personality/say(message) +/mob/living/split_personality/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) to_chat(src, "You cannot speak, your other self is controlling your body!") return FALSE -/mob/living/split_personality/emote(message) +/mob/living/split_personality/emote(act, m_type = null, message = null, intentional = FALSE) return ///////////////BRAINWASHING//////////////////// diff --git a/code/datums/browser.dm b/code/datums/browser.dm index fa5b054f48..358f2bfe29 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -371,9 +371,11 @@ if (isnull(settings["mainsettings"][setting]["value"])) settings["mainsettings"][setting]["value"] = oldval if ("string") - settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") + settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) if ("number") settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") as num + if ("color") + settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) as color if ("boolean") settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("Yes","No") if ("ckey") diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm index ecb5b785bb..e229b25258 100644 --- a/code/datums/cinematic.dm +++ b/code/datums/cinematic.dm @@ -22,7 +22,8 @@ GLOBAL_LIST_EMPTY(cinematics) /obj/screen/cinematic icon = 'icons/effects/station_explosion.dmi' icon_state = "station_intact" - layer = 21 + plane = SPLASHSCREEN_PLANE + layer = SPLASHSCREEN_LAYER mouse_opacity = MOUSE_OPACITY_TRANSPARENT screen_loc = "1,1" @@ -34,6 +35,7 @@ GLOBAL_LIST_EMPTY(cinematics) var/obj/screen/cinematic/screen var/datum/callback/special_callback //For special effects synced with animation (explosions after the countdown etc) var/cleanup_time = 300 //How long for the final screen to remain + var/stop_ooc = TRUE //Turns off ooc when played globally. /datum/cinematic/New() GLOB.cinematics += src @@ -59,6 +61,12 @@ GLOBAL_LIST_EMPTY(cinematics) if(is_global) SStgui.close_all_uis() + //Pause OOC + var/ooc_toggled = FALSE + if(is_global && stop_ooc && GLOB.ooc_allowed) + ooc_toggled = TRUE + toggle_ooc(FALSE) + for(var/mob/M in GLOB.mob_list) if(M in watchers) @@ -76,8 +84,14 @@ GLOBAL_LIST_EMPTY(cinematics) //Actually play it content() + //Cleanup sleep(cleanup_time) + + //Restore OOC + if(ooc_toggled) + toggle_ooc(TRUE) + qdel(src) //Sound helper diff --git a/code/datums/components/README.md b/code/datums/components/README.md index b617c8a25b..05ce057721 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -32,8 +32,12 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo 1. `/datum/var/list/datum_components` (private) * Lazy associated list of type -> component/list of components. -1. `/datum/component/var/enabled` (protected, boolean) - * If the component is enabled. If not, it will not react to signals +1. `/datum/var/list/comp_lookup` (private) + * Lazy associated list of signal -> registree/list of registrees +1. `/datum/var/list/signal_procs` (private) + * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal +1. `/datum/var/signal_enabled` (protected, boolean) + * If the datum is signal enabled. If not, it will not react to signals * `FALSE` by default, set to `TRUE` when a signal is registered 1. `/datum/component/var/dupe_mode` (protected, enum) * How duplicate component types are handled when added to the datum. @@ -45,14 +49,12 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo * Definition of a duplicate component type * `null` means exact match on `type` (default) * Any other type means that and all subtypes -1. `/datum/component/var/list/signal_procs` (private) - * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal 1. `/datum/component/var/datum/parent` (protected, read-only) * The datum this component belongs to * Never `null` in child procs -1. `report_signal_origin` (protected, boolean) - * If `TRUE`, will invoke the callback when signalled with the signal type as the first argument. - * `FALSE` by default. +1. `report_signal_origin` (protected, boolean) + * If `TRUE`, will invoke the callback when signalled with the signal type as the first argument. + * `FALSE` by default. ### Procs @@ -88,6 +90,14 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo 1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final) * Handles most of the actual signaling procedure * Will runtime if used on datums with an empty component list +1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) + * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments + * Makes the datum listen for the specified `signal` on it's `parent` datum. + * When that signal is received `proc_ref` will be called on the component, along with associated arguments + * Example proc ref: `.proc/OnEvent` + * If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this + * These callbacks run asyncronously + * Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it 1. `/datum/component/New(datum/parent, ...)` (private, final) * Runs internal setup for the component * Extra arguments are passed to `Initialize()` @@ -121,13 +131,5 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo 1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep) * Counterpart to `RegisterWithParent()` * Used to unregister the signals that should only be on the `parent` object -1. `/datum/component/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) - * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments - * Makes a component listen for the specified `signal` on it's `parent` datum. - * When that signal is received `proc_ref` will be called on the component, along with associated arguments - * Example proc ref: `.proc/OnEvent` - * If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this - * These callbacks run asyncronously - * Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it ### See/Define signals and their arguments in __DEFINES\components.dm diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index b9ad8bd8e9..b3d3b46434 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -1,8 +1,6 @@ /datum/component - var/enabled = FALSE var/dupe_mode = COMPONENT_DUPE_HIGHLANDER var/dupe_type - var/list/signal_procs var/datum/parent /datum/component/New(datum/P, ...) @@ -10,7 +8,7 @@ var/list/arguments = args.Copy(2) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) qdel(src, TRUE, TRUE) - CRASH("Incompatible [type] assigned to a [P.type]!") + CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]") _JoinParent(P) @@ -57,15 +55,11 @@ return /datum/component/Destroy(force=FALSE, silent=FALSE) - enabled = FALSE - var/datum/P = parent - if(!force) + if(!force && parent) _RemoveFromParent() if(!silent) - SEND_SIGNAL(P, COMSIG_COMPONENT_REMOVING, src) + SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) parent = null - for(var/target in signal_procs) - UnregisterSignal(target, signal_procs[target]) return ..() /datum/component/proc/_RemoveFromParent() @@ -89,7 +83,7 @@ /datum/component/proc/UnregisterFromParent() return -/datum/component/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE) +/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE) if(QDELETED(src) || QDELETED(target)) return @@ -122,9 +116,9 @@ else // Many other things have registered here lookup[sig_type][src] = TRUE - enabled = TRUE + signal_enabled = TRUE -/datum/component/proc/UnregisterSignal(datum/target, sig_type_or_types) +/datum/proc/UnregisterSignal(datum/target, sig_type_or_types) var/list/lookup = target.comp_lookup if(!signal_procs || !signal_procs[target] || !lookup) return @@ -174,15 +168,15 @@ /datum/proc/_SendSignal(sigtype, list/arguments) var/target = comp_lookup[sigtype] if(!length(target)) - var/datum/component/C = target - if(!C.enabled) + var/datum/C = target + if(!C.signal_enabled) return NONE var/datum/callback/CB = C.signal_procs[src][sigtype] return CB.InvokeAsync(arglist(arguments)) . = NONE for(var/I in target) - var/datum/component/C = I - if(!C.enabled) + var/datum/C = I + if(!C.signal_enabled) continue var/datum/callback/CB = C.signal_procs[src][sigtype] . |= CB.InvokeAsync(arglist(arguments)) @@ -232,6 +226,7 @@ CRASH("[nt]: Invalid dupe_type ([dt])!") else new_comp = nt + nt = new_comp.type args[1] = src @@ -281,10 +276,11 @@ var/datum/old_parent = parent PreTransfer() _RemoveFromParent() + parent = null SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src) /datum/proc/TakeComponent(datum/component/target) - if(!target) + if(!target || target.parent == src) return if(target.parent) target.RemoveComponent() diff --git a/code/datums/components/anti_magic.dm b/code/datums/components/anti_magic.dm index cc703e12dc..df03918c5d 100644 --- a/code/datums/components/anti_magic.dm +++ b/code/datums/components/anti_magic.dm @@ -14,13 +14,13 @@ magic = _magic holy = _holy -/datum/component/anti_magic/proc/on_equip(mob/equipper, slot) +/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot) RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/can_protect, TRUE) -/datum/component/anti_magic/proc/on_drop(mob/user) +/datum/component/anti_magic/proc/on_drop(datum/source, mob/user) UnregisterSignal(user, COMSIG_MOB_RECEIVE_MAGIC) -/datum/component/anti_magic/proc/can_protect(_magic, _holy, list/protection_sources) +/datum/component/anti_magic/proc/can_protect(datum/source, _magic, _holy, list/protection_sources) if((_magic && magic) || (_holy && holy)) protection_sources += parent return COMPONENT_BLOCK_MAGIC diff --git a/code/datums/components/archaeology.dm b/code/datums/components/archaeology.dm index f5bedf42a9..b5740650e9 100644 --- a/code/datums/components/archaeology.dm +++ b/code/datums/components/archaeology.dm @@ -25,7 +25,7 @@ for(var/I in other_archdrops) _archdrops[I] += other_archdrops[I] -/datum/component/archaeology/proc/Dig(obj/item/I, mob/living/user) +/datum/component/archaeology/proc/Dig(datum/source, obj/item/I, mob/living/user) if(dug) to_chat(user, "Looks like someone has dug here already.") return @@ -72,7 +72,7 @@ if(callback) callback.Invoke() -/datum/component/archaeology/proc/SingDig(S, current_size) +/datum/component/archaeology/proc/SingDig(datum/source, S, current_size) switch(current_size) if(STAGE_THREE) if(prob(30)) @@ -84,7 +84,7 @@ if(current_size >= STAGE_FIVE && prob(70)) gets_dug() -/datum/component/archaeology/proc/BombDig(severity, target) +/datum/component/archaeology/proc/BombDig(datum/source, severity, target) switch(severity) if(3) return diff --git a/code/datums/components/armor_plate.dm b/code/datums/components/armor_plate.dm index 0e3cee8a11..53c8c280a9 100644 --- a/code/datums/components/armor_plate.dm +++ b/code/datums/components/armor_plate.dm @@ -29,7 +29,7 @@ var/obj/item/typecast = upgrade_item upgrade_name = initial(typecast.name) -/datum/component/armor_plate/proc/examine(mob/user) +/datum/component/armor_plate/proc/examine(datum/source, mob/user) //upgrade_item could also be typecast here instead if(ismecha(parent)) if(amount) @@ -45,7 +45,7 @@ else to_chat(user, "It can be strengthened with up to [maxamount] [upgrade_name].") -/datum/component/armor_plate/proc/applyplate(obj/item/I, mob/user, params) +/datum/component/armor_plate/proc/applyplate(datum/source, obj/item/I, mob/user, params) if(!istype(I,upgrade_item)) return if(amount >= maxamount) @@ -72,7 +72,7 @@ to_chat(user, "You strengthen [O], improving its resistance against melee attacks.") -/datum/component/armor_plate/proc/dropplates(force) +/datum/component/armor_plate/proc/dropplates(datum/source, force) if(ismecha(parent)) //items didn't drop the plates before and it causes erroneous behavior for the time being with collapsible helmets for(var/i in 1 to amount) new upgrade_item(get_turf(parent)) \ No newline at end of file diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm index 9f85c4814c..1e1b7a0a48 100644 --- a/code/datums/components/caltrop.dm +++ b/code/datums/components/caltrop.dm @@ -14,7 +14,7 @@ RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED), .proc/Crossed) -/datum/component/caltrop/proc/Crossed(atom/movable/AM) +/datum/component/caltrop/proc/Crossed(datum/source, atom/movable/AM) var/atom/A = parent if(!A.has_gravity()) return diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index ddc375d8a8..bc1bbac423 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -27,7 +27,7 @@ target_turf = target START_PROCESSING(SSobj, src) // process on create, in case stuff is still there -/datum/component/chasm/proc/Entered(atom/movable/AM) +/datum/component/chasm/proc/Entered(datum/source, atom/movable/AM) START_PROCESSING(SSobj, src) drop_stuff(AM) diff --git a/code/datums/components/construction.dm b/code/datums/components/construction.dm index f4b65481e7..3b64d68486 100644 --- a/code/datums/components/construction.dm +++ b/code/datums/components/construction.dm @@ -19,7 +19,7 @@ RegisterSignal(parent, COMSIG_PARENT_ATTACKBY,.proc/action) update_parent(index) -/datum/component/construction/proc/examine(mob/user) +/datum/component/construction/proc/examine(datum/source, mob/user) if(desc) to_chat(user, desc) @@ -29,7 +29,7 @@ else update_parent(index) -/datum/component/construction/proc/action(obj/item/I, mob/living/user) +/datum/component/construction/proc/action(datum/source, obj/item/I, mob/living/user) return check_step(I, user) /datum/component/construction/proc/update_index(diff) diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index 6b5b486764..e5547ee0ec 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -7,8 +7,8 @@ var/first_dir // This only stores the dir arg from init -/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description) - if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color)) +/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255) + if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)) return COMPONENT_INCOMPATIBLE first_dir = _dir description = _description @@ -38,13 +38,14 @@ remove() apply() -/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color) +/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha) if(!_icon || !_icon_state) return FALSE // It has to be made from an image or dir breaks because of a byond bug var/temp_image = image(_icon, null, _icon_state, _layer, _dir) pic = new(temp_image) pic.color = _color + pic.alpha = _alpha return TRUE /datum/component/decal/proc/apply(atom/thing) @@ -59,16 +60,16 @@ if(isitem(master)) addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE) -/datum/component/decal/proc/rotate_react(old_dir, new_dir) +/datum/component/decal/proc/rotate_react(datum/source, old_dir, new_dir) if(old_dir == new_dir) return remove() pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir)) apply() -/datum/component/decal/proc/clean_react(strength) +/datum/component/decal/proc/clean_react(datum/source, strength) if(strength >= cleanable) qdel(src) -/datum/component/decal/proc/examine(mob/user) - to_chat(user, description) +/datum/component/decal/proc/examine(datum/source, mob/user) + to_chat(user, description) \ No newline at end of file diff --git a/code/datums/components/decals/blood.dm b/code/datums/components/decals/blood.dm index e4aae3cf05..7fae975678 100644 --- a/code/datums/components/decals/blood.dm +++ b/code/datums/components/decals/blood.dm @@ -32,7 +32,7 @@ blood_splatter_appearances[index] = pic return TRUE -/datum/component/decal/blood/proc/get_examine_name(mob/user, list/override) +/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override) var/atom/A = parent override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a" override[EXAMINE_POSITION_BEFORE] = " blood-stained " diff --git a/code/datums/components/earhealing.dm b/code/datums/components/earhealing.dm index 8fe6d2788e..9396eab3a3 100644 --- a/code/datums/components/earhealing.dm +++ b/code/datums/components/earhealing.dm @@ -9,7 +9,7 @@ return COMPONENT_INCOMPATIBLE RegisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), .proc/equippedChanged) -/datum/component/earhealing/proc/equippedChanged(mob/living/carbon/user, slot) +/datum/component/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot) if (slot == SLOT_EARS && istype(user)) if (!wearer) START_PROCESSING(SSobj, src) diff --git a/code/datums/components/earprotection.dm b/code/datums/components/earprotection.dm index f00b372218..2084943756 100644 --- a/code/datums/components/earprotection.dm +++ b/code/datums/components/earprotection.dm @@ -7,5 +7,5 @@ valid_slots = _valid_slots callback = CALLBACK(src, .proc/reducebang) -/datum/component/wearertargeting/earprotection/proc/reducebang(list/reflist) +/datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist) reflist[1]-- diff --git a/code/datums/components/edit_complainer.dm b/code/datums/components/edit_complainer.dm index f6de9eaf78..bf52296e2c 100644 --- a/code/datums/components/edit_complainer.dm +++ b/code/datums/components/edit_complainer.dm @@ -18,6 +18,6 @@ RegisterSignal(SSdcs, COMSIG_GLOB_VAR_EDIT, .proc/var_edit_react) -/datum/component/edit_complainer/proc/var_edit_react(list/arguments) +/datum/component/edit_complainer/proc/var_edit_react(datum/source, list/arguments) var/atom/movable/master = parent master.say(pick(say_lines)) diff --git a/code/datums/components/empprotection.dm b/code/datums/components/empprotection.dm index df4c49040b..c85cdf31c7 100644 --- a/code/datums/components/empprotection.dm +++ b/code/datums/components/empprotection.dm @@ -7,5 +7,5 @@ flags = _flags RegisterSignal(parent, list(COMSIG_ATOM_EMP_ACT), .proc/getEmpFlags) -/datum/component/empprotection/proc/getEmpFlags(severity) +/datum/component/empprotection/proc/getEmpFlags(datum/source, severity) return flags diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm new file mode 100644 index 0000000000..2276e7cd27 --- /dev/null +++ b/code/datums/components/footstep.dm @@ -0,0 +1,39 @@ +/datum/component/footstep + var/steps = 0 + var/volume + var/e_range + +/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + volume = volume_ + e_range = e_range_ + RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep) + +/datum/component/footstep/proc/play_footstep() + var/turf/open/T = get_turf(parent) + if(!istype(T)) + return + var/mob/living/LM = parent + var/v = volume + var/e = e_range + if(!T.footstep || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing) + return + if(iscarbon(LM)) + var/mob/living/carbon/C = LM + if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG)) + return + if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK) + v /= 2 + e -= 5 + steps++ + if(steps >= 6) + steps = 0 + if(steps % 2) + return + if(!LM.has_gravity(T) && steps != 0) // don't need to step as often when you hop around + return + playsound(T, pick(GLOB.footstep[T.footstep][1]), + GLOB.footstep[T.footstep][2] * v, + TRUE, + GLOB.footstep[T.footstep][3] + e) diff --git a/code/datums/components/forced_gravity.dm b/code/datums/components/forced_gravity.dm index bba0d8d71c..100bcf781c 100644 --- a/code/datums/components/forced_gravity.dm +++ b/code/datums/components/forced_gravity.dm @@ -1,8 +1,20 @@ /datum/component/forced_gravity - var/gravity = 1 + var/gravity var/ignore_space = FALSE //If forced gravity should also work on space turfs /datum/component/forced_gravity/Initialize(forced_value = 1) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE - gravity = forced_value \ No newline at end of file + RegisterSignal(COMSIG_ATOM_HAS_GRAVITY, .proc/gravity_check) + if(isturf(parent)) + RegisterSignal(COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check) + + gravity = forced_value + +/datum/component/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs) + if(!ignore_space && isspaceturf(location)) + return + gravs += gravity + +/datum/component/forced_gravity/proc/turf_gravity_check(datum/source, atom/checker, list/gravs) + return gravity_check(parent, gravs) \ No newline at end of file diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm index 9ee4c9c60b..9a67d01c5c 100644 --- a/code/datums/components/forensics.dm +++ b/code/datums/components/forensics.dm @@ -40,7 +40,7 @@ fibers = null return TRUE -/datum/component/forensics/proc/clean_act(strength) +/datum/component/forensics/proc/clean_act(datum/source, strength) if(strength >= CLEAN_STRENGTH_FINGERPRINTS) wipe_fingerprints() if(strength >= CLEAN_STRENGTH_BLOOD) diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index 6f95ccce35..cd5df8220b 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -13,7 +13,7 @@ expire_time = world.time + expire_in QDEL_IN(src, expire_in) RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/try_infect_buckle) - RegisterSignal(parent, COMSIG_MOVABLE_COLLIDE, .proc/try_infect_collide) + RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/try_infect_collide) RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/try_infect_crossed) RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, .proc/try_infect_attack_zone) RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/try_infect_attack) @@ -22,20 +22,20 @@ RegisterSignal(parent, COMSIG_FOOD_EATEN, .proc/try_infect_eat) RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean) -/datum/component/infective/proc/try_infect_eat(mob/living/eater, mob/living/feeder) +/datum/component/infective/proc/try_infect_eat(datum/source, mob/living/eater, mob/living/feeder) for(var/V in diseases) eater.ForceContractDisease(V) try_infect(feeder, BODY_ZONE_L_ARM) -/datum/component/infective/proc/clean(clean_strength) +/datum/component/infective/proc/clean(datum/source, clean_strength) if(clean_strength >= min_clean_strength) qdel(src) -/datum/component/infective/proc/try_infect_buckle(mob/M, force) +/datum/component/infective/proc/try_infect_buckle(datum/source, mob/M, force) if(isliving(M)) try_infect(M) -/datum/component/infective/proc/try_infect_collide(atom/A) +/datum/component/infective/proc/try_infect_collide(datum/source, atom/A) var/atom/movable/P = parent if(P.throwing) //this will be handled by try_infect_impact_zone() @@ -43,19 +43,19 @@ if(isliving(A)) try_infect(A) -/datum/component/infective/proc/try_infect_impact_zone(mob/living/target, hit_zone) +/datum/component/infective/proc/try_infect_impact_zone(datum/source, mob/living/target, hit_zone) try_infect(target, hit_zone) -/datum/component/infective/proc/try_infect_attack_zone(mob/living/carbon/target, mob/living/user, hit_zone) +/datum/component/infective/proc/try_infect_attack_zone(datum/source, mob/living/carbon/target, mob/living/user, hit_zone) try_infect(user, BODY_ZONE_L_ARM) try_infect(target, hit_zone) -/datum/component/infective/proc/try_infect_attack(mob/living/target, mob/living/user) +/datum/component/infective/proc/try_infect_attack(datum/source, mob/living/target, mob/living/user) if(!iscarbon(target)) //this case will be handled by try_infect_attack_zone try_infect(target) try_infect(user, BODY_ZONE_L_ARM) -/datum/component/infective/proc/try_infect_equipped(mob/living/L, slot) +/datum/component/infective/proc/try_infect_equipped(datum/source, mob/living/L, slot) var/old_permeability if(isitem(parent)) //if you are putting an infective item on, it obviously will not protect you, so set its permeability high enough that it will never block ContactContractDisease() @@ -69,7 +69,7 @@ var/obj/item/I = parent I.permeability_coefficient = old_permeability -/datum/component/infective/proc/try_infect_crossed(atom/movable/M) +/datum/component/infective/proc/try_infect_crossed(datum/source, atom/movable/M) if(isliving(M)) try_infect(M, BODY_ZONE_PRECISE_L_FOOT) diff --git a/code/datums/components/jousting.dm b/code/datums/components/jousting.dm index 34bed6d7e9..d1d0d6d504 100644 --- a/code/datums/components/jousting.dm +++ b/code/datums/components/jousting.dm @@ -22,17 +22,17 @@ RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/on_attack) -/datum/component/jousting/proc/on_equip(mob/user, slot) +/datum/component/jousting/proc/on_equip(datum/source, mob/user, slot) RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/mob_move, TRUE) current_holder = user -/datum/component/jousting/proc/on_drop(mob/user) +/datum/component/jousting/proc/on_drop(datum/source, mob/user) UnregisterSignal(user, COMSIG_MOVABLE_MOVED) current_holder = null current_direction = NONE current_tile_charge = 0 -/datum/component/jousting/proc/on_attack(mob/living/target, mob/user) +/datum/component/jousting/proc/on_attack(datum/source, mob/living/target, mob/user) if(user != current_holder) return var/current = current_tile_charge @@ -58,7 +58,7 @@ if(length(msg)) user.visible_message("[msg]!") -/datum/component/jousting/proc/mob_move(newloc, dir) +/datum/component/jousting/proc/mob_move(datum/source, newloc, dir) if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled)))) return if(dir != current_direction) diff --git a/code/datums/components/knockoff.dm b/code/datums/components/knockoff.dm index 3354548ca1..a36169e6df 100644 --- a/code/datums/components/knockoff.dm +++ b/code/datums/components/knockoff.dm @@ -3,7 +3,6 @@ var/knockoff_chance = 100 //Chance to knockoff var/list/target_zones //Aiming for these zones will cause the knockoff, null means all zones allowed var/list/slots_knockoffable //Can be only knocked off from these slots, null means all slots allowed - var/datum/component/redirect/disarm_redirect /datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable) if(!isitem(parent)) @@ -33,7 +32,7 @@ wearer.visible_message("[attacker] knocks off [wearer]'s [I.name]!","[attacker] knocks off your [I.name]!") -/datum/component/knockoff/proc/OnEquipped(mob/living/carbon/human/H,slot) +/datum/component/knockoff/proc/OnEquipped(datum/source, mob/living/carbon/human/H,slot) if(!istype(H)) return if(slots_knockoffable && !(slot in slots_knockoffable)) @@ -41,5 +40,5 @@ return RegisterSignal(H, COMSIG_HUMAN_DISARM_HIT, .proc/Knockoff, TRUE) -/datum/component/knockoff/proc/OnDropped(mob/living/M) +/datum/component/knockoff/proc/OnDropped(datum/source, mob/living/M) UnregisterSignal(M, COMSIG_HUMAN_DISARM_HIT) \ No newline at end of file diff --git a/code/datums/components/magnetic_catch.dm b/code/datums/components/magnetic_catch.dm index 8398f6f4b6..fb68b89ebf 100644 --- a/code/datums/components/magnetic_catch.dm +++ b/code/datums/components/magnetic_catch.dm @@ -1,23 +1,34 @@ /datum/component/magnetic_catch/Initialize() if(!isatom(parent)) return COMPONENT_INCOMPATIBLE - if(ismovableatom(parent)) - RegisterSignal(parent, COMSIG_MOVABLE_UNCROSS, .proc/uncross_react) - else - RegisterSignal(parent, COMSIG_ATOM_EXIT, .proc/exit_react) RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine) + if(ismovableatom(parent)) + RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/crossed_react) + RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/uncrossed_react) + for(var/i in get_turf(parent)) + if(i == parent) + continue + RegisterSignal(i, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react) + else + RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/entered_react) + RegisterSignal(parent, COMSIG_ATOM_EXITED, .proc/exited_react) + for(var/i in parent) + RegisterSignal(i, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react) -/datum/component/magnetic_catch/proc/uncross_react(atom/movable/thing) - if(!thing.throwing || thing.throwing.thrower) - return - qdel(thing.throwing) - return COMPONENT_MOVABLE_BLOCK_UNCROSS +/datum/component/magnetic_catch/proc/examine(datum/source, mob/user) + to_chat(user, "It has been installed with inertia dampening to prevent coffee spills.") -/datum/component/magnetic_catch/proc/exit_react(atom/movable/thing, atom/newloc) - if(!thing.throwing || thing.throwing.thrower) - return - qdel(thing.throwing) - return COMPONENT_ATOM_BLOCK_EXIT +/datum/component/magnetic_catch/proc/crossed_react(datum/source, atom/movable/thing) + RegisterSignal(thing, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react, TRUE) -/datum/component/magnetic_catch/proc/examine(mob/user) - to_chat(user, "It has been installed with inertia dampening to prevent coffee spills.") \ No newline at end of file +/datum/component/magnetic_catch/proc/uncrossed_react(datum/source, atom/movable/thing) + UnregisterSignal(thing, COMSIG_MOVABLE_PRE_THROW) + +/datum/component/magnetic_catch/proc/entered_react(datum/source, atom/movable/thing, atom/oldloc) + RegisterSignal(thing, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react, TRUE) + +/datum/component/magnetic_catch/proc/exited_react(datum/source, atom/movable/thing, atom/newloc) + UnregisterSignal(thing, COMSIG_MOVABLE_PRE_THROW) + +/datum/component/magnetic_catch/proc/throw_react(datum/source, list/arguments) + return COMPONENT_CANCEL_THROW \ No newline at end of file diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm index ec0c028292..48fa758db1 100644 --- a/code/datums/components/material_container.dm +++ b/code/datums/components/material_container.dm @@ -27,8 +27,13 @@ max_amount = max(0, max_amt) show_on_examine = _show_on_examine disable_attackby = _disable_attackby + if(allowed_types) - allowed_typecache = typecacheof(allowed_types) + if(ispath(allowed_types) && allowed_types == /obj/item/stack) + allowed_typecache = GLOB.typecache_stack + else + allowed_typecache = typecacheof(allowed_types) + precondition = _precondition after_insert = _after_insert @@ -44,7 +49,7 @@ var/mat_path = possible_mats[id] materials[id] = new mat_path() -/datum/component/material_container/proc/OnExamine(mob/user) +/datum/component/material_container/proc/OnExamine(datum/source, mob/user) if(show_on_examine) for(var/I in materials) var/datum/material/M = materials[I] @@ -52,7 +57,7 @@ if(amt) to_chat(user, "It has [amt] units of [lowertext(M.name)] stored.") -/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user) +/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user) var/list/tc = allowed_typecache if(disable_attackby) return @@ -242,24 +247,25 @@ //For spawning mineral sheets; internal use only /datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null) if(!M.sheet_type) - return FALSE - if(sheet_amt > 0) - if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT)) - sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT) - var/count = 0 - while(sheet_amt > MAX_STACK_SIZE) - new M.sheet_type(get_turf(parent), MAX_STACK_SIZE) - count += MAX_STACK_SIZE - use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) - sheet_amt -= MAX_STACK_SIZE - if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT)) - var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt) - if(target) - s.forceMove(target) - count += sheet_amt - use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) - return count - return FALSE + return 0 + if(sheet_amt <= 0) + return 0 + + if(!target) + target = get_turf(parent) + if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT)) + sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT) + var/count = 0 + while(sheet_amt > MAX_STACK_SIZE) + new M.sheet_type(target, MAX_STACK_SIZE) + count += MAX_STACK_SIZE + use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) + sheet_amt -= MAX_STACK_SIZE + if(sheet_amt >= 1) + new M.sheet_type(target, sheet_amt) + count += sheet_amt + use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) + return count /datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null) if(materials[id]) diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 3e37b07542..933c38505b 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -1,3 +1,6 @@ +#define MINOR_INSANITY_PEN 5 +#define MAJOR_INSANITY_PEN 10 + /datum/component/mood var/mood //Real happiness var/sanity = 100 //Current sanity @@ -5,25 +8,32 @@ var/mood_level = 5 //To track what stage of moodies they're on var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets var/datum/mood_event/list/mood_events = list() - var/mob/living/owner - var/datum/looping_sound/reverse_bear_trap/slow/soundloop //Insanity ticking + var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much? + var/holdmyinsanityeffect = 0 //before we edit our sanity lets take a look + var/obj/screen/mood/screen_obj /datum/component/mood/Initialize() if(!isliving(parent)) return COMPONENT_INCOMPATIBLE + START_PROCESSING(SSmood, src) - owner = parent - soundloop = new(list(owner), FALSE, TRUE) + RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event) RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event) - RegisterSignal(parent, COMSIG_ENTER_AREA, .proc/update_beauty) + + RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud) + var/mob/living/owner = parent + if(owner.hud_used) + modify_hud() + var/datum/hud/hud = owner.hud_used + hud.show_hud(hud.hud_version) /datum/component/mood/Destroy() STOP_PROCESSING(SSmood, src) - QDEL_NULL(soundloop) + unmodify_hud() return ..() -/datum/component/mood/proc/print_mood() +/datum/component/mood/proc/print_mood(mob/user) var/msg = "*---------*\nYour current mood\n" msg += "My mental status: " //Long term switch(sanity) @@ -67,8 +77,8 @@ var/datum/mood_event/event = mood_events[i] msg += event.description else - msg += "Nothing special has happened to me lately!\n" - to_chat(owner, msg) + msg += "I don't have much of a reaction to anything right now.\n" + to_chat(user || parent, msg) /datum/component/mood/proc/update_mood() //Called whenever a mood event is added or removed mood = 0 @@ -104,41 +114,25 @@ /datum/component/mood/proc/update_mood_icon() + var/mob/living/owner = parent if(owner.client && owner.hud_used) if(sanity < 25) - owner.hud_used.mood.icon_state = "mood_insane" + screen_obj.icon_state = "mood_insane" else - owner.hud_used.mood.icon_state = "mood[mood_level]" + screen_obj.icon_state = "mood[mood_level]" /datum/component/mood/process() //Called on SSmood process - switch(sanity) - if(SANITY_INSANE to SANITY_CRAZY) - owner.overlay_fullscreen("depression", /obj/screen/fullscreen/depression, 3) - update_mood_icon() - if(prob(7)) - owner.playsound_local(null, pick(CREEPY_SOUNDS), 40, 1) - soundloop.start() - if(SANITY_INSANE to SANITY_UNSTABLE) - owner.overlay_fullscreen("depression", /obj/screen/fullscreen/depression, 2) - if(prob(3)) - owner.playsound_local(null, pick(CREEPY_SOUNDS), 20, 1) - soundloop.stop() - if(SANITY_UNSTABLE to SANITY_DISTURBED) - owner.overlay_fullscreen("depression", /obj/screen/fullscreen/depression, 1) - soundloop.stop() - if(SANITY_DISTURBED to INFINITY) - owner.clear_fullscreen("depression") - soundloop.stop() + var/mob/living/owner = parent switch(mood_level) if(1) - DecreaseSanity(0.2, 0) + DecreaseSanity(0.2) if(2) - DecreaseSanity(0.125, 25) + DecreaseSanity(0.125, SANITY_CRAZY) if(3) - DecreaseSanity(0.075, 50) + DecreaseSanity(0.075, SANITY_UNSTABLE) if(4) - DecreaseSanity(0.025, 75) + DecreaseSanity(0.025, SANITY_DISTURBED) if(5) IncreaseSanity(0.1) if(6) @@ -146,42 +140,60 @@ if(7) IncreaseSanity(0.20) if(8) - IncreaseSanity(0.25, 125) + IncreaseSanity(0.25, SANITY_GREAT) if(9) - IncreaseSanity(0.4, 125) + IncreaseSanity(0.4, SANITY_GREAT) + + if(insanity_effect != holdmyinsanityeffect) + if(insanity_effect > holdmyinsanityeffect) + owner.crit_threshold += (insanity_effect - holdmyinsanityeffect) + else + owner.crit_threshold -= (holdmyinsanityeffect - insanity_effect) if(owner.has_trait(TRAIT_DEPRESSION)) if(prob(0.05)) - add_event("depression", /datum/mood_event/depression) - clear_event("jolly") + add_event(null, "depression", /datum/mood_event/depression) + clear_event(null, "jolly") if(owner.has_trait(TRAIT_JOLLY)) if(prob(0.05)) - add_event("jolly", /datum/mood_event/jolly) - clear_event("depression") + add_event(null, "jolly", /datum/mood_event/jolly) + clear_event(null, "depression") - var/area/A = get_area(owner) - if(A) - update_beauty(A) + holdmyinsanityeffect = insanity_effect + + HandleNutrition(owner) -/datum/component/mood/proc/DecreaseSanity(amount, limit = 0) - if(sanity < limit) //This might make KevinZ stop fucking pinging me. +/datum/component/mood/proc/DecreaseSanity(amount, minimum = SANITY_INSANE) + if(sanity < minimum) //This might make KevinZ stop fucking pinging me. IncreaseSanity(0.5) else - sanity = max(0, sanity - amount) + sanity = max(minimum, sanity - amount) + if(sanity < SANITY_UNSTABLE) + if(sanity < SANITY_CRAZY) + insanity_effect = (MAJOR_INSANITY_PEN) + else + insanity_effect = (MINOR_INSANITY_PEN) -/datum/component/mood/proc/IncreaseSanity(amount, limit = 99) - if(sanity > limit) +/datum/component/mood/proc/IncreaseSanity(amount, maximum = SANITY_NEUTRAL) + if(sanity > maximum) DecreaseSanity(0.5) //Removes some sanity to go back to our current limit. else - sanity = min(limit, sanity + amount) + sanity = min(maximum, sanity + amount) + if(sanity > SANITY_CRAZY) + if(sanity > SANITY_UNSTABLE) + insanity_effect = 0 + else + insanity_effect = MINOR_INSANITY_PEN -/datum/component/mood/proc/add_event(category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger. +/datum/component/mood/proc/add_event(datum/source, category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger. var/datum/mood_event/the_event if(mood_events[category]) the_event = mood_events[category] if(the_event.type != type) - clear_event(category) + clear_event(null, category) else + if(the_event.timeout) + addtimer(CALLBACK(src, .proc/clear_event, null, category), the_event.timeout, TIMER_UNIQUE|TIMER_OVERRIDE) return 0 //Don't have to update the event. the_event = new type(src, param) @@ -189,9 +201,9 @@ update_mood() if(the_event.timeout) - addtimer(CALLBACK(src, .proc/clear_event, category), the_event.timeout) + addtimer(CALLBACK(src, .proc/clear_event, null, category), the_event.timeout, TIMER_UNIQUE|TIMER_OVERRIDE) -/datum/component/mood/proc/clear_event(category) +/datum/component/mood/proc/clear_event(datum/source, category) var/datum/mood_event/event = mood_events[category] if(!event) return 0 @@ -200,22 +212,41 @@ qdel(event) update_mood() -/datum/component/mood/proc/update_beauty(area/A) - if(A.outdoors) //if we're outside, we don't care. - clear_event("area_beauty") - return FALSE - switch(A.beauty) - if(-INFINITY to BEAUTY_LEVEL_HORRID) - add_event("area_beauty", /datum/mood_event/horridroom) - if(BEAUTY_LEVEL_HORRID to BEAUTY_LEVEL_BAD) - add_event("area_beauty", /datum/mood_event/badroom) - if(BEAUTY_LEVEL_BAD to BEAUTY_LEVEL_MEH) - add_event("area_beauty", /datum/mood_event/mehroom) - if(BEAUTY_LEVEL_MEH to BEAUTY_LEVEL_DECENT) - clear_event("area_beauty") - if(BEAUTY_LEVEL_DECENT to BEAUTY_LEVEL_GOOD) - add_event("area_beauty", /datum/mood_event/decentroom) - if(BEAUTY_LEVEL_GOOD to BEAUTY_LEVEL_GREAT) - add_event("area_beauty", /datum/mood_event/goodroom) - if(BEAUTY_LEVEL_GREAT to INFINITY) - add_event("area_beauty", /datum/mood_event/greatroom) +/datum/component/mood/proc/modify_hud(datum/source) + var/mob/living/owner = parent + var/datum/hud/hud = owner.hud_used + screen_obj = new + hud.infodisplay += screen_obj + RegisterSignal(hud, COMSIG_PARENT_QDELETED, .proc/unmodify_hud) + RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click) + +/datum/component/mood/proc/unmodify_hud(datum/source) + if(!screen_obj) + return + var/mob/living/owner = parent + var/datum/hud/hud = owner.hud_used + if(hud && hud.infodisplay) + hud.infodisplay -= screen_obj + QDEL_NULL(screen_obj) + +/datum/component/mood/proc/hud_click(datum/source, location, control, params, mob/user) + print_mood(user) + + +/datum/component/mood/proc/HandleNutrition(mob/living/L) + switch(L.nutrition) + if(NUTRITION_LEVEL_FULL to INFINITY) + add_event(null, "nutrition", /datum/mood_event/fat) + if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL) + add_event(null, "nutrition", /datum/mood_event/wellfed) + if( NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) + add_event(null, "nutrition", /datum/mood_event/fed) + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) + clear_event(null, "nutrition") + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + add_event(null, "nutrition", /datum/mood_event/hungry) + if(0 to NUTRITION_LEVEL_STARVING) + add_event(null, "nutrition", /datum/mood_event/starving) + +#undef MINOR_INSANITY_PEN +#undef MAJOR_INSANITY_PEN diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index bbc2b1df31..426855f887 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -90,12 +90,12 @@ /datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, list/arguments) if(new_nanites) - adjust_nanites(new_nanites.nanite_volume) + adjust_nanites(null, new_nanites.nanite_volume) else - adjust_nanites(arguments[1]) //just add to the nanite volume + adjust_nanites(null, arguments[1]) //just add to the nanite volume /datum/component/nanites/process() - adjust_nanites(regen_rate) + adjust_nanites(null, regen_rate) for(var/X in programs) var/datum/nanite_program/NP = X NP.on_process() @@ -105,7 +105,7 @@ next_sync = world.time + NANITE_SYNC_DELAY //Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status) -/datum/component/nanites/proc/sync(datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE) +/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE) var/list/programs_to_remove = programs.Copy() var/list/programs_to_add = source.programs.Copy() for(var/X in programs) @@ -122,7 +122,7 @@ qdel(X) for(var/X in programs_to_add) var/datum/nanite_program/SNP = X - add_program(SNP.copy()) + add_program(null, SNP.copy()) /datum/component/nanites/proc/cloud_sync() if(!cloud_id) @@ -131,9 +131,9 @@ if(backup) var/datum/component/nanites/cloud_copy = backup.nanites if(cloud_copy) - sync(cloud_copy) + sync(null, cloud_copy) -/datum/component/nanites/proc/add_program(datum/nanite_program/new_program, datum/nanite_program/source_program) +/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program) for(var/X in programs) var/datum/nanite_program/NP = X if(NP.unique && NP.type == new_program.type) @@ -149,10 +149,10 @@ /datum/component/nanites/proc/consume_nanites(amount, force = FALSE) if(!force && safety_threshold && (nanite_volume - amount < safety_threshold)) return FALSE - adjust_nanites(-amount) + adjust_nanites(null, -amount) return (nanite_volume > 0) -/datum/component/nanites/proc/adjust_nanites(amount) +/datum/component/nanites/proc/adjust_nanites(datum/source, amount) nanite_volume = CLAMP(nanite_volume + amount, 0, max_nanites) if(nanite_volume <= 0) //oops we ran out qdel(src) @@ -168,39 +168,39 @@ nanite_percent = CLAMP(CEILING(nanite_percent, 10), 10, 100) holder.icon_state = "nanites[nanite_percent]" -/datum/component/nanites/proc/on_emp(severity) +/datum/component/nanites/proc/on_emp(datum/source, severity) nanite_volume *= (rand(0.60, 0.90)) //Lose 10-40% of nanites - adjust_nanites(-(rand(5, 50))) //Lose 5-50 flat nanite volume + adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume if(prob(40/severity)) cloud_id = 0 for(var/X in programs) var/datum/nanite_program/NP = X NP.on_emp(severity) -/datum/component/nanites/proc/on_shock(shock_damage) +/datum/component/nanites/proc/on_shock(datum/source, shock_damage) nanite_volume *= (rand(0.45, 0.80)) //Lose 20-55% of nanites - adjust_nanites(-(rand(5, 50))) //Lose 5-50 flat nanite volume + adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume for(var/X in programs) var/datum/nanite_program/NP = X NP.on_shock(shock_damage) -/datum/component/nanites/proc/on_minor_shock() - adjust_nanites(-(rand(5, 15))) //Lose 5-15 flat nanite volume +/datum/component/nanites/proc/on_minor_shock(datum/source) + adjust_nanites(null, -(rand(5, 15))) //Lose 5-15 flat nanite volume for(var/X in programs) var/datum/nanite_program/NP = X NP.on_minor_shock() -/datum/component/nanites/proc/on_death(gibbed) +/datum/component/nanites/proc/on_death(datum/source, gibbed) for(var/X in programs) var/datum/nanite_program/NP = X NP.on_death(gibbed) -/datum/component/nanites/proc/on_hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) +/datum/component/nanites/proc/on_hear(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) for(var/X in programs) var/datum/nanite_program/NP = X NP.on_hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) -/datum/component/nanites/proc/receive_signal(code, source = "an unidentified source") +/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source") for(var/X in programs) var/datum/nanite_program/NP = X NP.receive_signal(code, source) @@ -209,7 +209,7 @@ if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) qdel(src) //bodytype no longer sustains nanites -/datum/component/nanites/proc/check_access(obj/O) +/datum/component/nanites/proc/check_access(datum/source, obj/O) for(var/datum/nanite_program/triggered/access/access_program in programs) if(access_program.activated) return O.check_access_list(access_program.access) @@ -217,19 +217,19 @@ return FALSE return FALSE -/datum/component/nanites/proc/set_volume(amount) +/datum/component/nanites/proc/set_volume(datum/source, amount) nanite_volume = CLAMP(amount, 0, max_nanites) -/datum/component/nanites/proc/set_max_volume(amount) +/datum/component/nanites/proc/set_max_volume(datum/source, amount) max_nanites = max(1, max_nanites) -/datum/component/nanites/proc/set_cloud(amount) +/datum/component/nanites/proc/set_cloud(datum/source, amount) cloud_id = CLAMP(amount, 0, 100) -/datum/component/nanites/proc/set_safety(amount) +/datum/component/nanites/proc/set_safety(datum/source, amount) safety_threshold = CLAMP(amount, 0, max_nanites) -/datum/component/nanites/proc/set_regen(amount) +/datum/component/nanites/proc/set_regen(datum/source, amount) regen_rate = amount /datum/component/nanites/proc/confirm_nanites() @@ -243,10 +243,10 @@ nanite_data["safety_threshold"] = safety_threshold nanite_data["stealth"] = stealth -/datum/component/nanites/proc/get_programs(list/nanite_programs) +/datum/component/nanites/proc/get_programs(datum/source, list/nanite_programs) nanite_programs |= programs -/datum/component/nanites/proc/nanite_scan(mob/user, full_scan) +/datum/component/nanites/proc/nanite_scan(datum/source, mob/user, full_scan) if(!full_scan) if(!stealth) to_chat(user, "Nanites Detected") @@ -268,7 +268,7 @@ to_chat(user, "[NP.name] | [NP.activated ? "Active" : "Inactive"]") return TRUE -/datum/component/nanites/proc/nanite_ui_data(list/data, scan_level) +/datum/component/nanites/proc/nanite_ui_data(datum/source, list/data, scan_level) data["has_nanites"] = TRUE data["nanite_volume"] = nanite_volume data["regen_rate"] = regen_rate diff --git a/code/datums/components/paintable.dm b/code/datums/components/paintable.dm index 73aa1c02ed..756c42aa9d 100644 --- a/code/datums/components/paintable.dm +++ b/code/datums/components/paintable.dm @@ -12,7 +12,7 @@ var/atom/A = parent A.remove_atom_colour(FIXED_COLOUR_PRIORITY, current_paint) -/datum/component/spraycan_paintable/proc/Repaint(obj/item/toy/crayon/spraycan/spraycan, mob/living/user) +/datum/component/spraycan_paintable/proc/Repaint(datum/source, obj/item/toy/crayon/spraycan/spraycan, mob/living/user) if(!istype(spraycan) || user.a_intent == INTENT_HARM) return . = COMPONENT_NO_AFTERATTACK diff --git a/code/datums/components/rad_insulation.dm b/code/datums/components/rad_insulation.dm index 85a783df44..1ffc141a60 100644 --- a/code/datums/components/rad_insulation.dm +++ b/code/datums/components/rad_insulation.dm @@ -1,9 +1,24 @@ -/datum/component/rad_insulation // Yes, this really is just a component to add some vars +/datum/component/rad_insulation var/amount // Multiplier for radiation strength passing through - var/protects // Does this protect things in its contents from being affected? - var/contamination_proof // Can this object be contaminated? -/datum/component/rad_insulation/Initialize(_amount=RAD_MEDIUM_INSULATION, _protects=TRUE, _contamination_proof=TRUE) +/datum/component/rad_insulation/Initialize(_amount=RAD_MEDIUM_INSULATION, protects=TRUE, contamination_proof=TRUE) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + if(protects) // Does this protect things in its contents from being affected? + RegisterSignal(parent, COMSIG_ATOM_RAD_PROBE, .proc/rad_probe_react) + if(contamination_proof) // Can this object be contaminated? + RegisterSignal(parent, COMSIG_ATOM_RAD_CONTAMINATING, .proc/rad_contaminating) + if(_amount != 1) // If it's 1 it wont have any impact on radiation passing through anyway + RegisterSignal(parent, COMSIG_ATOM_RAD_WAVE_PASSING, .proc/rad_pass) + amount = _amount - protects = _protects - contamination_proof = _contamination_proof \ No newline at end of file + +/datum/component/rad_insulation/proc/rad_probe_react(datum/source) + return COMPONENT_BLOCK_RADIATION + +/datum/component/rad_insulation/proc/rad_contaminating(datum/source, strength) + return COMPONENT_BLOCK_CONTAMINATION + +/datum/component/rad_insulation/proc/rad_pass(datum/source, datum/radiation_wave/wave, width) + wave.intensity = wave.intensity*(1-((1-amount)/width)) // The further out the rad wave goes the less it's affected by insulation (larger width) \ No newline at end of file diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm index 3dd1ba2a6f..bf47793f81 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -58,7 +58,7 @@ else strength = max(strength, arguments[1]) -/datum/component/radioactive/proc/rad_examine(mob/user, atom/thing) +/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, atom/thing) var/atom/master = parent var/list/out = list() if(get_dist(master, user) <= 1) @@ -74,7 +74,7 @@ out += "." to_chat(user, out.Join()) -/datum/component/radioactive/proc/rad_attack(atom/movable/target, mob/living/user) +/datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user) radiation_pulse(parent, strength/20) target.rad_act(strength/2) strength -= strength / hl3_release_date diff --git a/code/datums/components/remote_materials.dm b/code/datums/components/remote_materials.dm new file mode 100644 index 0000000000..dd05660b3e --- /dev/null +++ b/code/datums/components/remote_materials.dm @@ -0,0 +1,111 @@ +/* +This component allows machines to connect remotely to a material container +(namely an /obj/machinery/ore_silo) elsewhere. It offers optional graceful +fallback to a local material storage in case remote storage is unavailable, and +handles linking back and forth. +*/ + +/datum/component/remote_materials + // Three possible states: + // 1. silo exists, materials is parented to silo + // 2. silo is null, materials is parented to parent + // 3. silo is null, materials is null + var/obj/machinery/ore_silo/silo + var/datum/component/material_container/mat_container + var/category + var/allow_standalone + var/local_size = INFINITY + +/datum/component/remote_materials/Initialize(category, mapload, allow_standalone = TRUE, force_connect = FALSE) + if (!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + src.category = category + src.allow_standalone = allow_standalone + + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy) + + var/turf/T = get_turf(parent) + if (force_connect || (mapload && is_station_level(T.z))) + addtimer(CALLBACK(src, .proc/LateInitialize)) + else if (allow_standalone) + _MakeLocal() + +/datum/component/remote_materials/proc/LateInitialize() + silo = GLOB.ore_silo_default + if (silo) + silo.connected += src + mat_container = silo.GetComponent(/datum/component/material_container) + else + _MakeLocal() + +/datum/component/remote_materials/Destroy() + if (silo) + silo.connected -= src + silo.updateUsrDialog() + silo = null + mat_container = null + else if (mat_container) + // specify explicitly in case the other component is deleted first + var/atom/P = parent + mat_container.retrieve_all(P.drop_location()) + return ..() + +/datum/component/remote_materials/proc/_MakeLocal() + silo = null + mat_container = parent.AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), + local_size, + FALSE, + /obj/item/stack) + +/datum/component/remote_materials/proc/set_local_size(size) + local_size = size + if (!silo && mat_container) + mat_container.max_amount = size + +// called if disconnected by ore silo UI or destruction +/datum/component/remote_materials/proc/disconnect_from(obj/machinery/ore_silo/old_silo) + if (!old_silo || silo != old_silo) + return + silo = null + mat_container = null + if (allow_standalone) + _MakeLocal() + +/datum/component/remote_materials/proc/OnAttackBy(datum/source, obj/item/I, mob/user) + if (istype(I, /obj/item/multitool)) + var/obj/item/multitool/M = I + if (!QDELETED(M.buffer) && istype(M.buffer, /obj/machinery/ore_silo)) + if (silo == M.buffer) + to_chat(user, "[parent] is already connected to [silo].") + return COMPONENT_NO_AFTERATTACK + if (silo) + silo.connected -= src + silo.updateUsrDialog() + else if (mat_container) + mat_container.retrieve_all() + qdel(mat_container) + silo = M.buffer + silo.connected += src + silo.updateUsrDialog() + mat_container = silo.GetComponent(/datum/component/material_container) + to_chat(user, "You connect [parent] to [silo] from the multitool's buffer.") + return COMPONENT_NO_AFTERATTACK + + else if (silo && istype(I, /obj/item/stack)) + if (silo.remote_attackby(parent, user, I)) + return COMPONENT_NO_AFTERATTACK + +/datum/component/remote_materials/proc/on_hold() + return silo && silo.holds["[get_area(parent)]/[category]"] + +/datum/component/remote_materials/proc/silo_log(obj/machinery/M, action, amount, noun, list/mats) + if (silo) + silo.silo_log(M || parent, action, amount, noun, mats) + +/datum/component/remote_materials/proc/format_amount() + if (mat_container) + return "[mat_container.total_amount] / [mat_container.max_amount == INFINITY ? "Unlimited" : mat_container.max_amount] ([silo ? "remote" : "local"])" + else + return "0 / 0" diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 4a40cae0d9..7b80f87657 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -26,11 +26,11 @@ RegisterSignal(parent, COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/vehicle_moved) -/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE) +/datum/component/riding/proc/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) restore_position(M) unequip_buckle_inhands(M) -/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE) +/datum/component/riding/proc/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) handle_vehicle_offsets() /datum/component/riding/proc/handle_vehicle_layer() @@ -46,7 +46,7 @@ /datum/component/riding/proc/set_vehicle_dir_layer(dir, layer) directional_vehicle_layers["[dir]"] = layer -/datum/component/riding/proc/vehicle_moved() +/datum/component/riding/proc/vehicle_moved(datum/source) var/atom/movable/AM = parent for(var/i in AM.buckled_mobs) ride_check(i) diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm index 8148267016..ff424dc02e 100644 --- a/code/datums/components/rotation.dm +++ b/code/datums/components/rotation.dm @@ -77,16 +77,16 @@ remove_verbs() . = ..() -/datum/component/simple_rotation/proc/ExamineMessage(mob/user) +/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user) if(rotation_flags & ROTATION_ALTCLICK) to_chat(user, "Alt-click to rotate it clockwise.") -/datum/component/simple_rotation/proc/HandRot(mob/user, rotation = default_rotation_direction) +/datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction) if(!can_be_rotated.Invoke(user, rotation) || !can_user_rotate.Invoke(user, rotation)) return BaseRot(user, rotation) -/datum/component/simple_rotation/proc/WrenchRot(obj/item/I, mob/living/user) +/datum/component/simple_rotation/proc/WrenchRot(datum/source, obj/item/I, mob/living/user) if(!can_be_rotated.Invoke(user,default_rotation_direction) || !can_user_rotate.Invoke(user,default_rotation_direction)) return if(istype(I,/obj/item/wrench)) diff --git a/code/datums/components/signal_redirect.dm b/code/datums/components/signal_redirect.dm index 4de7e99a02..db98d5664a 100644 --- a/code/datums/components/signal_redirect.dm +++ b/code/datums/components/signal_redirect.dm @@ -3,15 +3,31 @@ /datum/component/redirect dupe_mode = COMPONENT_DUPE_ALLOWED + var/list/signals + var/datum/callback/turfchangeCB -/datum/component/redirect/Initialize(list/signals, datum/callback/_callback, flags=NONE) +/datum/component/redirect/Initialize(list/_signals, flags=NONE) //It's not our job to verify the right signals are registered here, just do it. - if(!LAZYLEN(signals) || !istype(_callback)) - warning("signals are [list2params(signals)], callback is [_callback]]") + if(!LAZYLEN(_signals)) return COMPONENT_INCOMPATIBLE if(flags & REDIRECT_TRANSFER_WITH_TURF && isturf(parent)) - RegisterSignal(parent, COMSIG_TURF_CHANGE, .proc/turf_change) - RegisterSignal(parent, signals, _callback) + // If they also want to listen to the turf change then we need to set it up so both callbacks run + if(_signals[COMSIG_TURF_CHANGE]) + turfchangeCB = _signals[COMSIG_TURF_CHANGE] + if(!istype(turfchangeCB)) + . = COMPONENT_INCOMPATIBLE + CRASH("Redirect components must be given instanced callbacks, not proc paths.") + _signals[COMSIG_TURF_CHANGE] = CALLBACK(src, .proc/turf_change) + + signals = _signals -/datum/component/redirect/proc/turf_change(path, new_baseturfs, flags, list/transfers) +/datum/component/redirect/RegisterWithParent() + for(var/signal in signals) + RegisterSignal(parent, signal, signals[signal]) + +/datum/component/redirect/UnregisterFromParent() + UnregisterSignal(parent, signals) + +/datum/component/redirect/proc/turf_change(datum/source, path, new_baseturfs, flags, list/transfers) transfers += src + return turfchangeCB?.InvokeAsync(arglist(args)) diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 9bb00ecd28..a32a9cab43 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -9,7 +9,7 @@ callback = _callback RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip) -/datum/component/slippery/proc/Slip(atom/movable/AM) +/datum/component/slippery/proc/Slip(datum/source, atom/movable/AM) var/mob/victim = AM if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags) && callback) callback.Invoke(victim) diff --git a/code/datums/components/spooky.dm b/code/datums/components/spooky.dm index 6e9001ead5..8989cb499d 100644 --- a/code/datums/components/spooky.dm +++ b/code/datums/components/spooky.dm @@ -4,7 +4,7 @@ /datum/component/spooky/Initialize() RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/spectral_attack) -/datum/component/spooky/proc/spectral_attack(mob/living/carbon/C, mob/user) +/datum/component/spooky/proc/spectral_attack(datum/source, mob/living/carbon/C, mob/user) if(ishuman(user)) //this weapon wasn't meant for mortals. var/mob/living/carbon/human/U = user if(!istype(U.dna.species, /datum/species/skeleton)) diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm new file mode 100644 index 0000000000..29b074c3a7 --- /dev/null +++ b/code/datums/components/squeak.dm @@ -0,0 +1,87 @@ +/datum/component/squeak + var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1) + var/list/override_squeak_sounds + var/squeak_chance = 100 + var/volume = 30 + + // This is so shoes don't squeak every step + var/steps = 0 + var/step_delay = 1 + + // This is to stop squeak spam from inhand usage + var/last_use = 0 + var/use_delay = 20 + +/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), .proc/play_squeak) + if(ismovableatom(parent)) + RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak) + RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/play_squeak_crossed) + RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react) + if(isitem(parent)) + RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) + if(istype(parent, /obj/item/clothing/shoes)) + RegisterSignal(parent, COMSIG_SHOES_STEP_ACTION, .proc/step_squeak) + + override_squeak_sounds = custom_sounds + if(chance_override) + squeak_chance = chance_override + if(volume_override) + volume = volume_override + if(isnum(step_delay_override)) + step_delay = step_delay_override + if(isnum(use_delay_override)) + use_delay = use_delay_override + +/datum/component/squeak/proc/play_squeak() + if(prob(squeak_chance)) + if(!override_squeak_sounds) + playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) + else + playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1) + +/datum/component/squeak/proc/step_squeak() + if(steps > step_delay) + play_squeak() + steps = 0 + else + steps++ + +/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM) + if(isitem(AM)) + var/obj/item/I = AM + if(I.item_flags & ABSTRACT) + return + else if(istype(AM, /obj/item/projectile)) + var/obj/item/projectile/P = AM + if(P.original != parent) + return + var/atom/current_parent = parent + if(isturf(current_parent.loc)) + play_squeak() + +/datum/component/squeak/proc/use_squeak() + if(last_use + use_delay < world.time) + last_use = world.time + play_squeak() + +/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot) + RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE) + +/datum/component/squeak/proc/on_drop(datum/source, mob/user) + UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING) + +// Disposal pipes related shit +/datum/component/squeak/proc/disposing_react(datum/source, obj/structure/disposalholder/holder, obj/machinery/disposal/source) + //We don't need to worry about unregistering this signal as it will happen for us automaticaly when the holder is qdeleted + RegisterSignal(holder, COMSIG_ATOM_DIR_CHANGE, .proc/holder_dir_change) + +/datum/component/squeak/proc/holder_dir_change(datum/source, old_dir, new_dir) + //If the dir changes it means we're going through a bend in the pipes, let's pretend we bumped the wall + if(old_dir != new_dir) + play_squeak() diff --git a/code/datums/components/stationloving.dm b/code/datums/components/stationloving.dm index 15f47dd8a5..bbcb0d88a6 100644 --- a/code/datums/components/stationloving.dm +++ b/code/datums/components/stationloving.dm @@ -42,7 +42,7 @@ var/turf/currentturf = get_turf(src) to_chat(get(parent, /mob), "You can't help but feel that you just lost something back there...") var/turf/targetturf = relocate() - log_game("[parent] has been moved out of bounds in [AREACOORD(currentturf)]. Moving it to [AREACOORD(targetturf)].") + log_game("[parent] has been moved out of bounds in [loc_name(currentturf)]. Moving it to [loc_name(targetturf)].") if(inform_admins) message_admins("[parent] has been moved out of bounds in [ADMIN_VERBOSEJMP(currentturf)]. Moving it to [ADMIN_VERBOSEJMP(targetturf)].") @@ -65,17 +65,17 @@ return FALSE -/datum/component/stationloving/proc/check_deletion(force) // TRUE = interrupt deletion, FALSE = proceed with deletion +/datum/component/stationloving/proc/check_deletion(datum/source, force) // TRUE = interrupt deletion, FALSE = proceed with deletion var/turf/T = get_turf(parent) if(inform_admins && force) message_admins("[parent] has been !!force deleted!! in [ADMIN_VERBOSEJMP(T)].") - log_game("[parent] has been !!force deleted!! in [AREACOORD(T)].") + log_game("[parent] has been !!force deleted!! in [loc_name(T)].") if(!force && !allow_death) var/turf/targetturf = relocate() - log_game("[parent] has been destroyed in [AREACOORD(T)]. Moving it to [AREACOORD(targetturf)].") + log_game("[parent] has been destroyed in [loc_name(T)]. Moving it to [loc_name(targetturf)].") if(inform_admins) message_admins("[parent] has been destroyed in [ADMIN_VERBOSEJMP(T)]. Moving it to [ADMIN_VERBOSEJMP(targetturf)].") return TRUE diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm index 557d07c93d..4d7e8bddc5 100644 --- a/code/datums/components/storage/concrete/_concrete.dm +++ b/code/datums/components/storage/concrete/_concrete.dm @@ -72,7 +72,7 @@ var/datum/component/storage/slave = i slave.refresh_mob_views() -/datum/component/storage/concrete/emp_act(severity) +/datum/component/storage/concrete/emp_act(datum/source, severity) if(emp_shielded) return var/atom/real_location = real_location() @@ -90,13 +90,13 @@ slaves -= S return FALSE -/datum/component/storage/concrete/proc/on_contents_del(atom/A) +/datum/component/storage/concrete/proc/on_contents_del(datum/source, atom/A) var/atom/real_location = parent if(A in real_location) usr = null remove_from_storage(A, null) -/datum/component/storage/concrete/proc/on_deconstruct(disassembled) +/datum/component/storage/concrete/proc/on_deconstruct(datum/source, disassembled) if(drop_all_on_deconstruct) do_quick_empty() diff --git a/code/datums/components/storage/concrete/bag_of_holding.dm b/code/datums/components/storage/concrete/bag_of_holding.dm index fcc313e131..bf97ec6516 100644 --- a/code/datums/components/storage/concrete/bag_of_holding.dm +++ b/code/datums/components/storage/concrete/bag_of_holding.dm @@ -1,6 +1,6 @@ /datum/component/storage/concrete/bluespace/bag_of_holding/handle_item_insertion(obj/item/W, prevent_warning = FALSE, mob/living/user) var/atom/A = parent - if(A == W) + if(A == W) //don't put yourself into yourself. return var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(W.GetAllContents(), typecacheof(/obj/item/storage/backpack/holding)) matching -= A @@ -30,7 +30,7 @@ for (var/obj/structure/ladder/unbreakable/binary/ladder in GLOB.ladders) ladder.ActivateAlmonds() message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(loccheck)].") - log_game("[key_name(user)] detonated a bag of holding at [AREACOORD(loccheck)].") + log_game("[key_name(user)] detonated a bag of holding at [loc_name(loccheck)].") qdel(A) return . = ..() diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 22c418007d..55af26b6b2 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -89,12 +89,13 @@ RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, .proc/show_to_ghost) RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/refresh_mob_views) RegisterSignal(parent, COMSIG_ATOM_EXITED, .proc/_remove_and_refresh) + RegisterSignal(parent, COMSIG_ATOM_CANREACH, .proc/canreach_react) RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, .proc/preattack_intercept) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/attack_self) RegisterSignal(parent, COMSIG_ITEM_PICKUP, .proc/signal_on_pickup) - RegisterSignal(parent, COMSIG_MOVABLE_PRE_THROW, .proc/close_all) + RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, .proc/close_all) RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_alt_click) RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, .proc/mousedrop_onto) @@ -118,6 +119,7 @@ return var/obj/item/I = parent modeswitch_action = new(I) + RegisterSignal(modeswitch_action, COMSIG_ACTION_TRIGGER, .proc/action_trigger) if(I.obj_flags & IN_INVENTORY) var/mob/M = I.loc if(!istype(M)) @@ -143,14 +145,24 @@ var/datum/component/storage/concrete/master = master() return master? master.real_location() : null -/datum/component/storage/proc/attack_self(mob/M) +/datum/component/storage/proc/canreach_react(datum/source, list/next) + var/datum/component/storage/concrete/master = master() + if(!master) + return + . = COMPONENT_BLOCK_REACH + next += master.parent + for(var/i in master.slaves) + var/datum/component/storage/slave = i + next += slave.parent + +/datum/component/storage/proc/attack_self(datum/source, mob/M) if(locked) to_chat(M, "[parent] seems to be locked!") return FALSE if((M.get_active_held_item() == parent) && allow_quick_empty) quick_empty(M) -/datum/component/storage/proc/preattack_intercept(obj/O, mob/M, params) +/datum/component/storage/proc/preattack_intercept(datum/source, obj/O, mob/M, params) if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE)) return FALSE . = COMPONENT_NO_ATTACK @@ -263,7 +275,7 @@ remove_from_storage(I, _target) return TRUE -/datum/component/storage/proc/set_locked(new_state) +/datum/component/storage/proc/set_locked(datum/source, new_state) locked = new_state if(locked) close_all() @@ -371,11 +383,11 @@ close(M) . = TRUE //returns TRUE if any mobs actually got a close(M) call -/datum/component/storage/proc/emp_act(severity) +/datum/component/storage/proc/emp_act(datum/source, severity) if(emp_shielded) return var/datum/component/storage/concrete/master = master() - master.emp_act(severity) + master.emp_act(source, severity) //This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right. //The numbers are calculated from the bottom-left The bottom-left slot being 1,1. @@ -405,7 +417,7 @@ return FALSE return master._removal_reset(thing) -/datum/component/storage/proc/_remove_and_refresh(atom/movable/thing) +/datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) _removal_reset(thing) refresh_mob_views() @@ -447,7 +459,7 @@ return FALSE //This proc is called when you want to place an item into the storage item. -/datum/component/storage/proc/attackby(obj/item/I, mob/M, params) +/datum/component/storage/proc/attackby(datum/source, obj/item/I, mob/M, params) if(istype(I, /obj/item/hand_labeler)) var/obj/item/hand_labeler/labeler = I if(labeler.mode) @@ -476,13 +488,13 @@ return real_location.contents.Copy() //Abuses the fact that lists are just references, or something like that. -/datum/component/storage/proc/signal_return_inv(list/interface, recursive = TRUE) +/datum/component/storage/proc/signal_return_inv(datum/source, list/interface, recursive = TRUE) if(!islist(interface)) return FALSE interface |= return_inv(recursive) return TRUE -/datum/component/storage/proc/mousedrop_onto(atom/over_object, mob/M) +/datum/component/storage/proc/mousedrop_onto(datum/source, atom/over_object, mob/M) set waitfor = FALSE . = COMPONENT_NO_MOUSEDROP var/atom/A = parent @@ -519,7 +531,7 @@ if(force || M.CanReach(parent, view_only = TRUE)) show_to(M) -/datum/component/storage/proc/mousedrop_receive(atom/movable/O, mob/M) +/datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M) if(isitem(O)) var/obj/item/I = O if(iscarbon(M) || isdrone(M)) @@ -540,7 +552,7 @@ if(real_location == I.loc) return FALSE //Means the item is already in the storage item if(locked) - if(M) + if(M && !stop_messages) host.add_fingerprint(M) to_chat(M, "[host] seems to be locked!") return FALSE @@ -618,18 +630,18 @@ var/obj/O = parent O.update_icon() -/datum/component/storage/proc/signal_insertion_attempt(obj/item/I, mob/M, silent = FALSE, force = FALSE) +/datum/component/storage/proc/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE) if((!force && !can_be_inserted(I, TRUE, M)) || (I == parent)) return FALSE return handle_item_insertion(I, silent, M) -/datum/component/storage/proc/signal_can_insert(obj/item/I, mob/M, silent = FALSE) +/datum/component/storage/proc/signal_can_insert(datum/source, obj/item/I, mob/M, silent = FALSE) return can_be_inserted(I, silent, M) -/datum/component/storage/proc/show_to_ghost(mob/dead/observer/M) +/datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M) return user_show_to_mob(M, TRUE) -/datum/component/storage/proc/signal_show_attempt(mob/showto, force = FALSE) +/datum/component/storage/proc/signal_show_attempt(datum/source, mob/showto, force = FALSE) return user_show_to_mob(showto, force) /datum/component/storage/proc/on_check() @@ -638,14 +650,14 @@ /datum/component/storage/proc/check_locked() return locked -/datum/component/storage/proc/signal_take_type(type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted) +/datum/component/storage/proc/signal_take_type(datum/source, type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted) if(!force) if(check_adjacent) if(!user || !user.CanReach(destination) || !user.CanReach(parent)) return FALSE var/list/taking = typecache_filter_list(contents(), typecacheof(type)) - if(length(taking) > amount) - taking.Cut(amount) + if(taking.len > amount) + taking.len = amount if(inserted) //duplicated code for performance, don't bother checking retval/checking for list every item. for(var/i in taking) if(remove_from_storage(i, destination)) @@ -659,7 +671,7 @@ var/atom/real_location = real_location() return max(0, max_items - real_location.contents.len) -/datum/component/storage/proc/signal_fill_type(type, amount = 20, force = FALSE) +/datum/component/storage/proc/signal_fill_type(datum/source, type, amount = 20, force = FALSE) var/atom/real_location = real_location() if(!force) amount = min(remaining_space_items(), amount) @@ -668,7 +680,7 @@ CHECK_TICK return TRUE -/datum/component/storage/proc/on_attack_hand(mob/user) +/datum/component/storage/proc/on_attack_hand(datum/source, mob/user) var/atom/A = parent if(!attack_hand_interact) return @@ -701,25 +713,25 @@ else show_to(user) -/datum/component/storage/proc/signal_on_pickup(mob/user) +/datum/component/storage/proc/signal_on_pickup(datum/source, mob/user) var/atom/A = parent update_actions() for(var/mob/M in range(1, A)) if(M.active_storage == src) close(M) -/datum/component/storage/proc/signal_take_obj(atom/movable/AM, new_loc, force = FALSE) +/datum/component/storage/proc/signal_take_obj(datum/source, atom/movable/AM, new_loc, force = FALSE) if(!(AM in real_location())) return FALSE return remove_from_storage(AM, new_loc) -/datum/component/storage/proc/signal_quick_empty(atom/loctarget) +/datum/component/storage/proc/signal_quick_empty(datum/source, atom/loctarget) return do_quick_empty(loctarget) -/datum/component/storage/proc/signal_hide_attempt(mob/target) +/datum/component/storage/proc/signal_hide_attempt(datum/source, mob/target) return hide_from(target) -/datum/component/storage/proc/on_alt_click(mob/user) +/datum/component/storage/proc/on_alt_click(datum/source, mob/user) if(!isliving(user) || user.incapacitated() || !quickdraw || locked || !user.CanReach(parent)) return var/obj/item/I = locate() in real_location() @@ -731,6 +743,10 @@ return user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") +/datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source) + gather_mode_switch(source.owner) + return COMPONENT_ACTION_BLOCK_TRIGGER + /datum/component/storage/proc/gather_mode_switch(mob/user) collection_mode = (collection_mode+1)%3 switch(collection_mode) diff --git a/code/datums/components/swarming.dm b/code/datums/components/swarming.dm index f97e03579a..17b2178df6 100644 --- a/code/datums/components/swarming.dm +++ b/code/datums/components/swarming.dm @@ -11,7 +11,7 @@ RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/join_swarm) RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/leave_swarm) -/datum/component/swarming/proc/join_swarm(atom/movable/AM) +/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/AM) GET_COMPONENT_FROM(other_swarm, /datum/component/swarming, AM) if(!other_swarm) return @@ -20,7 +20,7 @@ other_swarm.swarm() other_swarm.swarm_members |= src -/datum/component/swarming/proc/leave_swarm(atom/movable/AM) +/datum/component/swarming/proc/leave_swarm(datum/source, atom/movable/AM) GET_COMPONENT_FROM(other_swarm, /datum/component/swarming, AM) if(!other_swarm || !(other_swarm in swarm_members)) return diff --git a/code/datums/components/thermite.dm b/code/datums/components/thermite.dm index c9c1c5da3e..45243014dd 100644 --- a/code/datums/components/thermite.dm +++ b/code/datums/components/thermite.dm @@ -68,14 +68,14 @@ else QDEL_IN(fakefire, 50) -/datum/component/thermite/proc/clean_react(strength) +/datum/component/thermite/proc/clean_react(datum/source, strength) //Thermite is just some loose powder, you could probably clean it with your hands. << todo? qdel(src) -/datum/component/thermite/proc/flame_react(exposed_temperature, exposed_volume) +/datum/component/thermite/proc/flame_react(datum/source, exposed_temperature, exposed_volume) if(exposed_temperature > 1922) // This is roughly the real life requirement to ignite thermite thermite_melt() -/datum/component/thermite/proc/attackby_react(obj/item/thing, mob/user, params) +/datum/component/thermite/proc/attackby_react(datum/source, obj/item/thing, mob/user, params) if(thing.is_hot()) thermite_melt(user) \ No newline at end of file diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index ad6e76182d..c5966452bb 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -84,7 +84,7 @@ GLOBAL_LIST_EMPTY(uplinks) gamemode = _gamemode uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted) -/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user) +/datum/component/uplink/proc/OnAttackBy(datum/source, obj/item/I, mob/user) if(!active) return //no hitting everyone/everything just to try to slot tcs in! if(istype(I, /obj/item/stack/telecrystal)) @@ -101,7 +101,7 @@ GLOBAL_LIST_EMPTY(uplinks) qdel(I) return -/datum/component/uplink/proc/interact(mob/user) +/datum/component/uplink/proc/interact(datum/source, mob/user) if(locked) return active = TRUE @@ -201,28 +201,28 @@ GLOBAL_LIST_EMPTY(uplinks) /datum/component/uplink/proc/implant_activation() var/obj/item/implant/implant = parent locked = FALSE - interact(implant.imp_in) + interact(null, implant.imp_in) -/datum/component/uplink/proc/implanting(list/arguments) +/datum/component/uplink/proc/implanting(datum/source, list/arguments) var/mob/user = arguments[2] owner = "[user.key]" -/datum/component/uplink/proc/old_implant(list/arguments, obj/item/implant/new_implant) +/datum/component/uplink/proc/old_implant(datum/source, list/arguments, obj/item/implant/new_implant) // It kinda has to be weird like this until implants are components return SEND_SIGNAL(new_implant, COMSIG_IMPLANT_EXISTING_UPLINK, src) -/datum/component/uplink/proc/new_implant(datum/component/uplink/uplink) +/datum/component/uplink/proc/new_implant(datum/source, datum/component/uplink/uplink) uplink.telecrystals += telecrystals return COMPONENT_DELETE_NEW_IMPLANT // PDA signal responses -/datum/component/uplink/proc/new_ringtone(mob/living/user, new_ring_text) +/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text) var/obj/item/pda/master = parent if(trim(lowertext(new_ring_text)) != trim(lowertext(master.lock_code))) //why is the lock code stored on the pda? return locked = FALSE - interact(user) + interact(null, user) to_chat(user, "The PDA softly beeps.") user << browse(null, "window=pda") master.mode = 0 @@ -230,22 +230,22 @@ GLOBAL_LIST_EMPTY(uplinks) // Radio signal responses -/datum/component/uplink/proc/new_frequency(list/arguments) +/datum/component/uplink/proc/new_frequency(datum/source, list/arguments) var/obj/item/radio/master = parent var/frequency = arguments[1] if(frequency != master.traitor_frequency) return locked = FALSE if(ismob(master.loc)) - interact(master.loc) + interact(null, master.loc) // Pen signal responses -/datum/component/uplink/proc/pen_rotation(degrees, mob/living/carbon/user) +/datum/component/uplink/proc/pen_rotation(datum/source, degrees, mob/living/carbon/user) var/obj/item/pen/master = parent if(degrees != master.traitor_unlock_degrees) return locked = FALSE master.degrees = 0 - interact(user) + interact(null, user) to_chat(user, "Your pen makes a clicking noise, before quickly rotating back to 0 degrees!") \ No newline at end of file diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm new file mode 100644 index 0000000000..a1f538e4dd --- /dev/null +++ b/code/datums/components/waddling.dm @@ -0,0 +1,15 @@ +/datum/component/waddling + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + +/datum/component/waddling/Initialize() + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle) + +/datum/component/waddling/proc/Waddle() + var/mob/living/L = parent + if(L.incapacitated() || L.lying) + return + animate(L, pixel_z = 4, time = 0) + animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2) + animate(pixel_z = 0, transform = matrix(), time = 0) diff --git a/code/datums/components/wearertargeting.dm b/code/datums/components/wearertargeting.dm index 107ab41e39..0aa0831127 100644 --- a/code/datums/components/wearertargeting.dm +++ b/code/datums/components/wearertargeting.dm @@ -12,13 +12,13 @@ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) -/datum/component/wearertargeting/proc/on_equip(mob/equipper, slot) +/datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot) if((slot in valid_slots) && istype(equipper, mobtype)) RegisterSignal(equipper, signals, callback, TRUE) else UnregisterSignal(equipper, signals) -/datum/component/wearertargeting/proc/on_drop(mob/user) +/datum/component/wearertargeting/proc/on_drop(datum/source, mob/user) UnregisterSignal(user, signals) /datum/component/wearertargeting/Destroy() diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm index 1a6bc015d6..6d504cefd4 100644 --- a/code/datums/components/wet_floor.dm +++ b/code/datums/components/wet_floor.dm @@ -90,7 +90,7 @@ S.intensity = intensity S.lube_flags = lube_flags -/datum/component/wet_floor/proc/dry(strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY) +/datum/component/wet_floor/proc/dry(datum/source, strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY) for(var/i in time_left_list) if(text2num(i) <= strength) time_left_list[i] = max(0, time_left_list[i] - duration_decrease) @@ -120,8 +120,8 @@ if(O.obj_flags & FROZEN) O.make_unfrozen() add_wet(TURF_WET_WATER, max_time_left()) - dry(TURF_WET_ICE) - dry(ALL, FALSE, decrease) + dry(null, TURF_WET_ICE) + dry(null, ALL, FALSE, decrease) check() last_process = world.time diff --git a/code/datums/datum.dm b/code/datums/datum.dm index aba03c784c..e74e30b536 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -2,7 +2,9 @@ var/gc_destroyed //Time when this object was destroyed. var/list/active_timers //for SStimer var/list/datum_components //for /datum/components - var/list/comp_lookup //for /datum/components + var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register + var/list/signal_procs + var/signal_enabled = FALSE var/datum_flags = NONE var/datum/weakref/weak_reference @@ -20,6 +22,7 @@ // Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE. /datum/proc/Destroy(force=FALSE, ...) tag = null + datum_flags &= ~DF_USE_TAG //In case something tries to REF us weak_reference = null //ensure prompt GCing of weakref. var/list/timers = active_timers @@ -30,6 +33,9 @@ continue qdel(timer) + //BEGIN: ECS SHIT + signal_enabled = FALSE + var/list/dc = datum_components if(dc) var/all_components = dc[/datum/component] @@ -55,6 +61,10 @@ comp.UnregisterSignal(src, sig) comp_lookup = lookup = null + for(var/target in signal_procs) + UnregisterSignal(target, signal_procs[target]) + //END: ECS SHIT + return QDEL_HINT_QUEUE #ifdef DATUMVAR_DEBUGGING_MODE @@ -86,16 +96,16 @@ //Return a LIST for serialize_datum to encode! Not the actual json! /datum/proc/serialize_list(list/options) - return NOT_IMPLEMENTED + CRASH("Attempted to serialize datum [src] of type [type] without serialize_list being implemented!") //Accepts a LIST from deserialize_datum. Should return src or another datum. /datum/proc/deserialize_list(json, list/options) - return NOT_IMPLEMENTED + CRASH("Attempted to deserialize datum [src] of type [type] without deserialize_list being implemented!") //Serializes into JSON. Does not encode type. /datum/proc/serialize_json(list/options) . = serialize_list(options) - if((. == NOT_IMPLEMENTED) || !islist(.)) + if(!islist(.)) . = null else . = json_encode(.) @@ -146,4 +156,4 @@ if(!istype(returned, /datum)) qdel(D) else - return returned \ No newline at end of file + return returned diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 56f2243015..d5c983bc39 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,3 +1,7 @@ +#define VV_MSG_MARKED "
Marked Object" +#define VV_MSG_EDITED "
Var Edited" +#define VV_MSG_DELETED "
Deleted" + /datum/proc/CanProcCall(procname) return TRUE @@ -9,6 +13,7 @@ return FALSE vars[var_name] = var_value datum_flags |= DF_VAR_EDITED + return TRUE /datum/proc/vv_get_var(var_name) switch(var_name) @@ -68,6 +73,7 @@ src << browse_rsc(sprite, "vv[hash].png") title = "[D] ([REF(D)]) = [type]" + var/formatted_type = replacetext("[type]", "/", "/") var/sprite_text if(sprite) @@ -77,36 +83,40 @@ if(istype(D, /atom)) var/atom/A = D if(isliving(A)) - atomsnowflake += "[D]" - if(A.dir) - atomsnowflake += "
<< [dir2text(A.dir)] >>" + atomsnowflake += "[D]" + atomsnowflake += "
<< [dir2text(A.dir) || A.dir] >>" var/mob/living/M = A atomsnowflake += {" -
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"] +
[M.ckey || "No ckey"] / [M.real_name || "No real name"]
- BRUTE:[M.getBruteLoss()] - FIRE:[M.getFireLoss()] - TOXIN:[M.getToxLoss()] - OXY:[M.getOxyLoss()] - CLONE:[M.getCloneLoss()] - BRAIN:[M.getBrainLoss()] - STAMINA:[M.getStaminaLoss()] + BRUTE:[M.getBruteLoss()] + FIRE:[M.getFireLoss()] + TOXIN:[M.getToxLoss()] + OXY:[M.getOxyLoss()] + CLONE:[M.getCloneLoss()] + BRAIN:[M.getBrainLoss()] + STAMINA:[M.getStaminaLoss()] + AROUSAL:[M.getArousalLoss()] "} else - atomsnowflake += "[D]" - if(A.dir) - atomsnowflake += "
<< [dir2text(A.dir)] >>" + atomsnowflake += "[D]" + atomsnowflake += "
<< [dir2text(A.dir) || A.dir] >>" + else if("name" in D.vars) + atomsnowflake += "[D]" else - atomsnowflake += "[D]" + atomsnowflake += "[formatted_type]" + formatted_type = null - var/formatted_type = replacetext("[type]", "/", "/") var/marked if(holder && holder.marked_datum && holder.marked_datum == D) - marked = "
Marked Object" + marked = VV_MSG_MARKED var/varedited_line = "" if(!islist && (D.datum_flags & DF_VAR_EDITED)) - varedited_line = "
Var Edited" + varedited_line = VV_MSG_EDITED + var/deleted_line + if(!islist && D.gc_destroyed) + deleted_line = VV_MSG_DELETED var/list/dropdownoptions = list() if (islist) @@ -167,112 +177,9 @@ } - +
@@ -317,8 +341,9 @@
[formatted_type] - [marked] - [varedited_line] + [marked] + [varedited_line] + [deleted_line]
@@ -326,8 +351,7 @@ Refresh