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 Select option @@ -363,8 +387,9 @@ [variable_html.Join()] @@ -372,6 +397,10 @@ src << browse(html, "window=variables[refid];size=475x650") +/client/proc/vv_update_display(datum/D, span, content) + src << output("[span]:[content]", "variables[REF(D)].browser:replace_span") + + #define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) /proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) var/header @@ -471,7 +500,6 @@ return src.holder.show_player_panel(M) - href_list["datumrefresh"] = href_list["mob_player_panel"] else if(href_list["godmode"]) if(!check_rights(R_ADMIN)) @@ -483,7 +511,6 @@ return src.cmd_admin_godmode(M) - href_list["datumrefresh"] = href_list["godmode"] else if(href_list["mark_object"]) if(!check_rights(NONE)) @@ -494,8 +521,10 @@ to_chat(usr, "This can only be done to instances of type /datum") return - src.holder.marked_datum = D - href_list["datumrefresh"] = href_list["mark_object"] + if(holder.marked_datum) + vv_update_display(holder.marked_datum, "marked", "") + holder.marked_datum = D + vv_update_display(D, "marked", VV_MSG_MARKED) else if(href_list["proc_call"]) if(!check_rights(NONE)) @@ -511,10 +540,11 @@ return var/datum/D = locate(href_list["delete"]) - if(!D) + if(!istype(D)) to_chat(usr, "Unable to locate item!") admin_delete(D) - href_list["datumrefresh"] = href_list["delete"] + if (isturf(D)) // show the turf that took its place + debug_variables(D) else if(href_list["osay"]) if(!check_rights(R_FUN, 0)) @@ -573,18 +603,33 @@ message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") M.fully_replace_character_name(M.real_name,new_name) - href_list["datumrefresh"] = href_list["rename"] + vv_update_display(M, "name", new_name) + vv_update_display(M, "real_name", M.real_name || "No real name") else if(href_list["varnameedit"] && href_list["datumedit"]) if(!check_rights(NONE)) return - var/D = locate(href_list["datumedit"]) + var/datum/D = locate(href_list["datumedit"]) if(!istype(D, /datum)) to_chat(usr, "This can only be used on datums") return - modify_variables(D, href_list["varnameedit"], 1) + if (!modify_variables(D, href_list["varnameedit"], 1)) + return + switch(href_list["varnameedit"]) + if("name") + vv_update_display(D, "name", "[D]") + if("dir") + if(isatom(D)) + var/dir = D.vars["dir"] + vv_update_display(D, "dir", dir2text(dir) || dir) + if("ckey") + if(isliving(D)) + vv_update_display(D, "ckey", D.vars["ckey"] || "No ckey") + if("real_name") + if(isliving(D)) + vv_update_display(D, "real_name", D.vars["real_name"] || "No real name") else if(href_list["varnamechange"] && href_list["datumchange"]) if(!check_rights(NONE)) @@ -716,7 +761,6 @@ return src.give_spell(M) - href_list["datumrefresh"] = href_list["give_spell"] else if(href_list["remove_spell"]) if(!check_rights(NONE)) @@ -728,7 +772,6 @@ return remove_spell(M) - href_list["datumrefresh"] = href_list["remove_spell"] else if(href_list["give_disease"]) if(!check_rights(NONE)) @@ -740,7 +783,6 @@ return src.give_disease(M) - href_list["datumrefresh"] = href_list["give_spell"] else if(href_list["gib"]) if(!check_rights(R_FUN)) @@ -763,7 +805,6 @@ return togglebuildmode(M) - href_list["datumrefresh"] = href_list["build_mode"] else if(href_list["drop_everything"]) if(!check_rights(NONE)) @@ -814,7 +855,7 @@ for (var/i in armorlist) pickerlist += list(list("value" = armorlist[i], "name" = i)) - var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [O]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, Type = "text", values = pickerlist) + var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [O]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist) if (islist(result)) if (result["button"] == 2) // If the user pressed the cancel button @@ -915,8 +956,6 @@ log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") - href_list["datumrefresh"] = href_list["addreagent"] - else if(href_list["explode"]) if(!check_rights(R_FUN)) return @@ -927,7 +966,6 @@ return src.cmd_admin_explosion(A) - href_list["datumrefresh"] = href_list["explode"] else if(href_list["emp"]) if(!check_rights(R_FUN)) @@ -939,7 +977,6 @@ return src.cmd_admin_emp(A) - href_list["datumrefresh"] = href_list["emp"] else if(href_list["modtransform"]) if(!check_rights(R_DEBUG)) @@ -968,8 +1005,6 @@ if(!isnull(angle)) A.transform = M.Turn(angle) - href_list["datumrefresh"] = href_list["modtransform"] - else if(href_list["rotatedatum"]) if(!check_rights(NONE)) return @@ -984,7 +1019,7 @@ A.setDir(turn(A.dir, -45)) if("left") A.setDir(turn(A.dir, 45)) - href_list["datumrefresh"] = href_list["rotatedatum"] + vv_update_display(A, "dir", dir2text(A.dir)) else if(href_list["editorgans"]) if(!check_rights(NONE)) @@ -996,7 +1031,33 @@ return manipulate_organs(C) - href_list["datumrefresh"] = href_list["editorgans"] + + else if(href_list["givemartialart"]) + if(!check_rights(NONE)) + return + + var/mob/living/carbon/C = locate(href_list["givemartialart"]) in GLOB.carbon_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/list/artpaths = subtypesof(/datum/martial_art) + var/list/artnames = list() + for(var/i in artpaths) + var/datum/martial_art/M = i + artnames[initial(M.name)] = M + + var/result = input(usr, "Choose the martial art to teach","JUDO CHOP") as null|anything in artnames + if(!usr) + return + if(QDELETED(C)) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/chosenart = artnames[result] + var/datum/martial_art/MA = new chosenart + MA.teach(C) else if(href_list["givetrauma"]) if(!check_rights(NONE)) @@ -1018,8 +1079,6 @@ if(result) C.gain_trauma(result) - href_list["datumrefresh"] = href_list["givetrauma"] - else if(href_list["curetraumas"]) if(!check_rights(NONE)) return @@ -1031,8 +1090,6 @@ C.cure_all_traumas(TRAUMA_RESILIENCE_ABSOLUTE) - href_list["datumrefresh"] = href_list["curetraumas"] - else if(href_list["hallucinate"]) if(!check_rights(NONE)) return @@ -1262,21 +1319,32 @@ to_chat(usr, "Mob doesn't exist anymore") return + var/newamt switch(Text) if("brute") L.adjustBruteLoss(amount) + newamt = L.getBruteLoss() if("fire") L.adjustFireLoss(amount) + newamt = L.getFireLoss() if("toxin") L.adjustToxLoss(amount) + newamt = L.getToxLoss() if("oxygen") L.adjustOxyLoss(amount) + newamt = L.getOxyLoss() if("brain") L.adjustBrainLoss(amount) + newamt = L.getBrainLoss() if("clone") L.adjustCloneLoss(amount) + newamt = L.getCloneLoss() if("stamina") L.adjustStaminaLoss(amount) + newamt = L.getStaminaLoss() + if("arousal") + L.adjustArousalLoss(amount) + newamt = L.getArousalLoss() else to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") return @@ -1286,4 +1354,10 @@ var/msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [L] " message_admins(msg) admin_ticket_log(L, msg) - href_list["datumrefresh"] = href_list["mobToDamage"] + vv_update_display(L, Text, "[newamt]") + else if(href_list["copyoutfit"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["copyoutfit"]) in GLOB.carbon_list + if(istype(H)) + H.copy_outfit() \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 9f274c0aa3..0ace2ca8fd 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -233,7 +233,7 @@ /datum/symptom/heal/coma/CanHeal(datum/disease/advance/A) var/mob/living/M = A.affected_mob - if(M.has_trait(TRAIT_FAKEDEATH)) + if(M.has_trait(TRAIT_DEATHCOMA)) return power else if(M.IsUnconscious() || M.stat == UNCONSCIOUS) return power * 0.9 diff --git a/code/datums/diseases/parrotpossession.dm b/code/datums/diseases/parrotpossession.dm index ee58c28761..d9c4b324f6 100644 --- a/code/datums/diseases/parrotpossession.dm +++ b/code/datums/diseases/parrotpossession.dm @@ -21,7 +21,7 @@ cure() else if(prob(parrot.speak_chance)) if(parrot.speech_buffer.len) - affected_mob.say(pick(parrot.speech_buffer)) + affected_mob.say(pick(parrot.speech_buffer), forced = "parrot possession") /datum/disease/parrot_possession/cure() if(parrot && parrot.loc == affected_mob) diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm index 8f13d2e2fa..64f453cd48 100644 --- a/code/datums/diseases/pierrot_throat.dm +++ b/code/datums/diseases/pierrot_throat.dm @@ -25,4 +25,4 @@ to_chat(affected_mob, "Your thoughts are interrupted by a loud HONK!") if(4) if(prob(5)) - affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) + affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) , forced = "pierrot's throat") diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 2113a99813..b295f5f10b 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -16,6 +16,7 @@ var/list/stage4 = list("You feel white bread.") var/list/stage5 = list("Oh the humanity!") var/new_form = /mob/living/carbon/human + var/bantype /datum/disease/transformation/Copy() var/datum/disease/transformation/D = ..() @@ -49,10 +50,6 @@ if(istype(affected_mob, /mob/living/carbon) && affected_mob.stat != DEAD) if(stage5) to_chat(affected_mob, pick(stage5)) - if(jobban_isbanned(affected_mob, new_form)) - if(!QDELETED(affected_mob)) - affected_mob.death(1) - return if(QDELETED(affected_mob)) return if(affected_mob.notransform) @@ -64,6 +61,8 @@ affected_mob.dropItemToGround(I) var/mob/living/new_mob = new new_form(affected_mob.loc) if(istype(new_mob)) + if(bantype && jobban_isbanned(affected_mob, bantype)) + replace_banned_player(new_mob) new_mob.a_intent = INTENT_HARM if(affected_mob.mind) affected_mob.mind.transfer_to(new_mob) @@ -74,7 +73,22 @@ new_mob.real_name = new_mob.name qdel(affected_mob) +/datum/disease/transformation/proc/replace_banned_player(var/mob/living/new_mob) // This can run well after the mob has been transferred, so need a handle on the new mob to kill it if needed. + set waitfor = FALSE + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [affected_mob.name]?", bantype, null, bantype, 50, affected_mob) + if(LAZYLEN(candidates)) + var/mob/dead/observer/C = pick(candidates) + to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") + message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbaned player.") + affected_mob.ghostize(0) + affected_mob.key = C.key + else + to_chat(new_mob, "Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!") + new_mob.death() + if (!QDELETED(new_mob)) + new_mob.ghostize(can_reenter_corpse = FALSE) + new_mob.key = null /datum/disease/transformation/jungle_fever name = "Jungle Fever" @@ -92,6 +106,8 @@ visibility_flags = 0 agent = "Kongey Vibrion M-909" new_form = /mob/living/carbon/monkey + bantype = ROLE_MONKEY + stage1 = list() stage2 = list() @@ -120,7 +136,7 @@ affected_mob.confused += 10 if(4) if(prob(3)) - affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh.")) + affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh."), forced = "jungle fever") /datum/disease/transformation/jungle_fever/cure() remove_monkey(affected_mob.mind) @@ -153,19 +169,20 @@ stage5 = list("Your skin feels as if it's about to burst off!") new_form = /mob/living/silicon/robot infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_ROBOTIC) + bantype = "Cyborg" /datum/disease/transformation/robot/stage_act() ..() switch(stage) if(3) if (prob(8)) - affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) + affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop"), forced = "robotic transformation") if (prob(4)) to_chat(affected_mob, "You feel a stabbing pain in your head.") affected_mob.Unconscious(40) if(4) if (prob(20)) - affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee...")) + affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee..."), forced = "robotic transformation") /datum/disease/transformation/xeno @@ -184,6 +201,7 @@ stage4 = list("Your skin feels very tight.", "Your blood boils!", "You can feel... something...inside you.") stage5 = list("Your skin feels as if it's about to burst off!") new_form = /mob/living/carbon/alien/humanoid/hunter + bantype = ROLE_ALIEN /datum/disease/transformation/xeno/stage_act() ..() @@ -194,7 +212,7 @@ affected_mob.Unconscious(40) if(4) if (prob(20)) - affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!")) + affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!"), forced = "xenomorph transformation") /datum/disease/transformation/slime @@ -246,10 +264,10 @@ switch(stage) if(3) if (prob(8)) - affected_mob.say(pick("YAP", "Woof!")) + affected_mob.say(pick("YAP", "Woof!"), forced = "corgi transformation") if(4) if (prob(20)) - affected_mob.say(pick("Bark!", "AUUUUUU")) + affected_mob.say(pick("Bark!", "AUUUUUU"), forced = "corgi transformation") /datum/disease/transformation/morph name = "Gluttony's Blessing" @@ -267,3 +285,43 @@ stage5 = list("You have become a morph.") new_form = /mob/living/simple_animal/hostile/morph infectable_biotypes = list(MOB_ORGANIC, MOB_INORGANIC, MOB_UNDEAD) //magic! + +/datum/disease/transformation/gondola + name = "Gondola Transformation" + cure_text = "Condensed Capsaicin, ingested or injected." //getting pepper sprayed doesn't help + cures = list("condensedcapsaicin") //beats the hippie crap right out of your system + cure_chance = 80 + stage_prob = 5 + agent = "Tranquility" + desc = "Consuming the flesh of a Gondola comes at a terrible price." + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list("You seem a little lighter in your step.") + stage2 = list("You catch yourself smiling for no reason.") + stage3 = list("A cruel sense of calm overcomes you.", "You can't feel your arms!", "You let go of the urge to hurt clowns.") + stage4 = list("You can't feel your arms. It does not bother you anymore.", "You forgive the clown for hurting you.") + stage5 = list("You have become a Gondola.") + new_form = /mob/living/simple_animal/pet/gondola + +/datum/disease/transformation/gondola/stage_act() + ..() + switch(stage) + if(2) + if (prob(5)) + affected_mob.emote("smile") + if (prob(20)) + affected_mob.reagents.add_reagent_list(list("pax" = 5)) + if(3) + if (prob(5)) + affected_mob.emote("smile") + if (prob(20)) + affected_mob.reagents.add_reagent_list(list("pax" = 5)) + if(4) + if (prob(5)) + affected_mob.emote("smile") + if (prob(20)) + affected_mob.reagents.add_reagent_list(list("pax" = 5)) + if (prob(2)) + to_chat(affected_mob, "You let go of what you were holding.") + var/obj/item/I = affected_mob.get_active_held_item() + affected_mob.dropItemToGround(I) diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index 919eaa6e12..b288046380 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -29,21 +29,21 @@ STI KALY - blind switch(stage) if(2) if(prob(1)&&prob(50)) - affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!")) + affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"), forced = "wizarditis") if(prob(1)&&prob(50)) to_chat(affected_mob, "You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].") if(3) if(prob(1)&&prob(50)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!")) + affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"), forced = "wizarditis") if(prob(1)&&prob(50)) to_chat(affected_mob, "You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].") if(4) if(prob(1)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!")) + affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"), forced = "wizarditis") return if(prob(1)&&prob(50)) to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].") @@ -111,7 +111,7 @@ STI KALY - blind if(!L) return - affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!") + affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!", forced = "wizarditis teleport") affected_mob.forceMove(pick(L)) return diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 8474306852..ed18b3cade 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -12,6 +12,7 @@ var/list/temporary_mutations = list() //Timers for temporary mutations var/list/previous = list() //For temporary name/ui/ue/blood_type modifications var/mob/living/holder + var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875 /datum/dna/New(mob/living/new_holder) if(istype(new_holder)) @@ -23,7 +24,9 @@ if(cholder.dna == src) cholder.dna = null holder = null - QDEL_NULL(species) + + if(delete_species) + QDEL_NULL(species) mutations.Cut() //This only references mutations, just dereference. temporary_mutations.Cut() //^ @@ -41,12 +44,12 @@ destination.dna.features = features.Copy() destination.dna.real_name = real_name destination.dna.temporary_mutations = temporary_mutations.Copy() - if(transfer_SE) - destination.dna.struc_enzymes = struc_enzymes if(ishuman(destination)) var/mob/living/carbon/human/H = destination H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text + if(transfer_SE) + destination.dna.struc_enzymes = struc_enzymes /datum/dna/proc/copy_dna(datum/dna/new_dna) new_dna.unique_enzymes = unique_enzymes @@ -209,10 +212,10 @@ /datum/dna/proc/initialize_dna(newblood_type) if(newblood_type) blood_type = newblood_type - features = random_features() unique_enzymes = generate_unique_enzymes() uni_identity = generate_uni_identity() struc_enzymes = generate_struc_enzymes() + features = random_features() /datum/dna/stored //subtype used by brain mob's stored_dna @@ -245,17 +248,21 @@ stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human -/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1) +/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) if(mrace && has_dna()) - dna.species.on_species_loss(src) - var/old_species = dna.species + var/datum/species/new_race if(ispath(mrace)) - dna.species = new mrace() + new_race = new mrace + else if(istype(mrace)) + new_race = mrace else - dna.species = mrace - dna.species.on_species_gain(src, old_species) + return + dna.species.on_species_loss(src, new_race, pref_load) + var/datum/species/old_species = dna.species + dna.species = new_race + dna.species.on_species_gain(src, old_species, pref_load) -/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1) +/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) ..() if(icon_update) update_body() diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 8ce632e32d..57cdb9bcf5 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -16,7 +16,7 @@ var/emote_type = EMOTE_VISIBLE //Whether the emote is visible or audible var/restraint_check = FALSE //Checks if the mob is restrained before performing the emote var/muzzle_ignore = FALSE //Will only work if the emote is EMOTE_AUDIBLE - var/list/mob_type_allowed_typecache = list(/mob) //Types that are allowed to use that emote + var/list/mob_type_allowed_typecache = /mob //Types that are allowed to use that emote var/list/mob_type_blacklist_typecache //Types that are NOT allowed to use that emote var/list/mob_type_ignore_stat_typecache var/stat_allowed = CONSCIOUS @@ -25,13 +25,22 @@ /datum/emote/New() if(key_third_person) emote_list[key_third_person] = src - mob_type_allowed_typecache = typecacheof(mob_type_allowed_typecache) + if (ispath(mob_type_allowed_typecache)) + switch (mob_type_allowed_typecache) + if (/mob) + mob_type_allowed_typecache = GLOB.typecache_mob + if (/mob/living) + mob_type_allowed_typecache = GLOB.typecache_living + else + mob_type_allowed_typecache = typecacheof(mob_type_allowed_typecache) + else + mob_type_allowed_typecache = typecacheof(mob_type_allowed_typecache) mob_type_blacklist_typecache = typecacheof(mob_type_blacklist_typecache) mob_type_ignore_stat_typecache = typecacheof(mob_type_ignore_stat_typecache) -/datum/emote/proc/run_emote(mob/user, params, type_override) +/datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE) . = TRUE - if(!can_run_emote(user)) + if(!can_run_emote(user, TRUE, intentional)) return FALSE var/msg = select_message_type(user) if(params && message_param) @@ -47,7 +56,7 @@ if(!msg) return - user.log_message(msg, INDIVIDUAL_EMOTE_LOG) + user.log_message(msg, LOG_EMOTE) msg = "[user] " + msg for(var/mob/M in GLOB.dead_mob_list) @@ -61,7 +70,6 @@ user.audible_message(msg) else user.visible_message(msg) - log_talk(user,"[key_name(user)] : [msg]",LOGEMOTE) /datum/emote/proc/replace_pronoun(mob/user, message) if(findtext(message, "their")) @@ -94,7 +102,7 @@ /datum/emote/proc/select_param(mob/user, params) return replacetext(message_param, "%t", params) -/datum/emote/proc/can_run_emote(mob/user, status_check = TRUE) +/datum/emote/proc/can_run_emote(mob/user, status_check = TRUE, intentional = FALSE) . = TRUE if(!is_type_in_typecache(user, mob_type_allowed_typecache)) return FALSE @@ -102,9 +110,24 @@ return FALSE if(status_check && !is_type_in_typecache(user, mob_type_ignore_stat_typecache)) if(user.stat > stat_allowed) - to_chat(user, "You cannot [key] while unconscious.") + if(!intentional) + return FALSE + switch(user.stat) + if(SOFT_CRIT) + to_chat(user, "You cannot [key] while in a critical condition.") + if(UNCONSCIOUS) + to_chat(user, "You cannot [key] while unconscious.") + if(DEAD) + to_chat(user, "You cannot [key] while dead.") return FALSE - if(restraint_check && (user.restrained() || user.buckled)) + if(restraint_check && (user.IsStun() || user.IsKnockdown())) + if(!intentional) + return FALSE + to_chat(user, "You cannot [key] while stunned.") + return FALSE + if(restraint_check && user.restrained()) + if(!intentional) + return FALSE to_chat(user, "You cannot [key] while restrained.") return FALSE diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm index 9f521dac8a..0b3e431af6 100644 --- a/code/datums/explosion.dm +++ b/code/datums/explosion.dm @@ -86,13 +86,13 @@ GLOBAL_LIST_EMPTY(explosions) if(adminlog) message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [ADMIN_VERBOSEJMP(epicenter)]") - log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [AREACOORD(epicenter)]") + log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [loc_name(epicenter)]") var/x0 = epicenter.x var/y0 = epicenter.y var/z0 = epicenter.z var/area/areatype = get_area(epicenter) - SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type)) + SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1))) // Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves. // Stereo users will also hear the direction of the explosion! diff --git a/code/datums/forced_movement.dm b/code/datums/forced_movement.dm index e07e4c62ed..3cdf2b1fd8 100644 --- a/code/datums/forced_movement.dm +++ b/code/datums/forced_movement.dm @@ -82,7 +82,7 @@ . = . && (vic.loc != tar.loc) -/mob/Collide(atom/A) +/mob/Bump(atom/A) . = ..() if(force_moving && force_moving.allow_climbing && isstructure(A)) var/obj/structure/S = A diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index a30ed5f927..46de2c5c92 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -7,15 +7,25 @@ /datum/getrev/New() testmerge = world.TgsTestMerges() log_world("Running /tg/ revision:") - var/list/logs = world.file2list(".git/logs/HEAD") - if(logs) - logs = splittext(logs[logs.len - 1], " ") - date = unix2date(text2num(logs[5])) - commit = logs[2] - log_world("[commit]: [date]") - logs = world.file2list(".git/logs/refs/remotes/origin/master") - if(logs.len) - originmastercommit = splittext(logs[logs.len - 1], " ")[2] + var/datum/tgs_revision_information/revinfo = world.TgsRevision() + if(revinfo) + commit = revinfo.commit + originmastercommit = revinfo.origin_commit + else + var/list/logs = world.file2list(".git/logs/HEAD") + if(logs.len) + logs = splittext(logs[logs.len - 1], " ") + date = unix2date(text2num(logs[5])) + commit = logs[2] + log_world("[commit]: [date]") + else + log_world("Unable to read git logs, revision information not available") + originmastercommit = commit = "Unknown" + date = unix2date(world.timeofday) + return + logs = world.file2list(".git/logs/refs/remotes/origin/master") + if(logs.len) + originmastercommit = splittext(logs[logs.len - 1], " ")[2] if(testmerge.len) log_world(commit) @@ -67,17 +77,17 @@ to_chat(src, "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]") to_chat(src, "Enforce Human Authority: [CONFIG_GET(flag/enforce_human_authority)]") to_chat(src, "Allow Latejoin Antagonists: [CONFIG_GET(flag/allow_latejoin_antagonists)]") - to_chat(src, "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_flag_list/continuous))] of [config.modes.len] roundtypes") - to_chat(src, "Allow Midround Antagonists: [length(CONFIG_GET(keyed_flag_list/midround_antag))] of [config.modes.len] roundtypes") + to_chat(src, "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_list/continuous))] of [config.modes.len] roundtypes") + to_chat(src, "Allow Midround Antagonists: [length(CONFIG_GET(keyed_list/midround_antag))] of [config.modes.len] roundtypes") if(CONFIG_GET(flag/show_game_type_odds)) - var/list/probabilities = CONFIG_GET(keyed_number_list/probability) + var/list/probabilities = CONFIG_GET(keyed_list/probability) if(SSticker.IsRoundInProgress()) var/prob_sum = 0 var/current_odds_differ = FALSE var/list/probs = list() var/list/modes = config.gamemode_cache - var/list/min_pop = CONFIG_GET(keyed_number_list/min_pop) - var/list/max_pop = CONFIG_GET(keyed_number_list/max_pop) + var/list/min_pop = CONFIG_GET(keyed_list/min_pop) + var/list/max_pop = CONFIG_GET(keyed_list/max_pop) for(var/mode in modes) var/datum/game_mode/M = mode var/ctag = initial(M.config_tag) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 4ef292d1b1..d673cdb16d 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -51,7 +51,7 @@ tele_play_specials(teleatom, curturf, effectin, asoundin) var/success = force_teleport ? teleatom.forceMove(destturf) : teleatom.Move(destturf) if (success) - log_game("[teleatom] ([key_name(teleatom)]) has teleported from [AREACOORD(curturf)] to [AREACOORD(destturf)]") + log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") tele_play_specials(teleatom, destturf, effectout, asoundout) if(ismegafauna(teleatom)) message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_VERBOSEJMP(curturf)] to [ADMIN_VERBOSEJMP(destturf)].") @@ -60,6 +60,8 @@ var/mob/M = teleatom M.cancel_camera() + return TRUE + /proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound) if (location && !isobserver(teleatom)) if (sound) diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 9d4b86b5ef..4923609db8 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -60,7 +60,6 @@ user.remote_control = null if(!QDELETED(eye)) - eye.RemoveImages() QDEL_NULL(eye) if(connected_holopad && !QDELETED(hologram)) diff --git a/code/datums/hud.dm b/code/datums/hud.dm index f235cb6dc4..32bce89f4d 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -12,7 +12,7 @@ GLOBAL_LIST_INIT(huds, list( DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(), DATA_HUD_SENTIENT_DISEASE = new/datum/atom_hud/sentient_disease(), - DATA_HUD_AI_DETECT = new/datum/atom_hud(), //CIT - EMPTY PLACEHOLDER UNTIL SYNC + DATA_HUD_AI_DETECT = new/datum/atom_hud/ai_detector(), ANTAG_HUD_CULT = new/datum/atom_hud/antag(), ANTAG_HUD_REV = new/datum/atom_hud/antag(), ANTAG_HUD_OPS = new/datum/atom_hud/antag(), @@ -26,7 +26,7 @@ GLOBAL_LIST_INIT(huds, list( ANTAG_HUD_SINTOUCHED = new/datum/atom_hud/antag/hidden(), ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(), ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(), - ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden() + ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(), )) /datum/atom_hud @@ -101,7 +101,8 @@ GLOBAL_LIST_INIT(huds, list( return FALSE hudatoms |= A for(var/mob/M in hudusers) - add_to_single_hud(M, A) + if(!queued_to_see[M]) + add_to_single_hud(M, A) return TRUE /datum/atom_hud/proc/add_to_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client diff --git a/code/datums/looping_sounds/item_sounds.dm b/code/datums/looping_sounds/item_sounds.dm index d0ec277b36..e729ed22dd 100644 --- a/code/datums/looping_sounds/item_sounds.dm +++ b/code/datums/looping_sounds/item_sounds.dm @@ -13,7 +13,7 @@ volume = 25 var/last_radiation -/datum/looping_sound/geiger/get_sound(looped) +/datum/looping_sound/geiger/get_sound(starttime) var/danger switch(last_radiation) if(RAD_BACKGROUND_RADIATION to RAD_GEIGER_LOW) @@ -26,7 +26,7 @@ danger = 4 else return null - return ..(looped, mid_sounds[danger]) + return ..(starttime, mid_sounds[danger]) /datum/looping_sound/geiger/stop() . = ..() @@ -41,11 +41,6 @@ mid_length = 3.5 volume = 25 -/datum/looping_sound/reverse_bear_trap/slow - mid_sounds = list('sound/effects/clock_tick.ogg') - mid_length = 10 - volume = 40 - /datum/looping_sound/reverse_bear_trap_beep mid_sounds = list('sound/machines/beep.ogg') diff --git a/code/datums/looping_sounds/looping_sound.dm b/code/datums/looping_sounds/looping_sound.dm index aed7c3ace8..2eba36dc90 100644 --- a/code/datums/looping_sounds/looping_sound.dm +++ b/code/datums/looping_sounds/looping_sound.dm @@ -24,10 +24,11 @@ var/end_sound var/chance var/volume = 100 - var/muted = TRUE var/max_loops var/direct + var/timerid + /datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE) if(!mid_sounds) WARNING("A looping sound datum was created without sounds to play.") @@ -47,25 +48,27 @@ /datum/looping_sound/proc/start(atom/add_thing) if(add_thing) output_atoms |= add_thing - if(!muted) + if(timerid) return - muted = FALSE on_start() /datum/looping_sound/proc/stop(atom/remove_thing) if(remove_thing) output_atoms -= remove_thing - if(muted) + if(!timerid) return - muted = TRUE + on_stop() + deltimer(timerid) + timerid = null -/datum/looping_sound/proc/sound_loop(looped=0) - if(muted || (max_loops && looped > max_loops)) - on_stop(looped) +/datum/looping_sound/proc/sound_loop(starttime) + if(max_loops && world.time >= starttime + mid_length * max_loops) + stop() return if(!chance || prob(chance)) - play(get_sound(looped)) - addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length) + play(get_sound(starttime)) + if(!timerid) + timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_STOPPABLE | TIMER_LOOP) /datum/looping_sound/proc/play(soundfile) var/list/atoms_cache = output_atoms @@ -80,7 +83,7 @@ else playsound(thing, S, volume) -/datum/looping_sound/proc/get_sound(looped, _mid_sounds) +/datum/looping_sound/proc/get_sound(starttime, _mid_sounds) if(!_mid_sounds) . = mid_sounds else @@ -95,6 +98,6 @@ start_wait = start_length addtimer(CALLBACK(src, .proc/sound_loop), start_wait) -/datum/looping_sound/proc/on_stop(looped) +/datum/looping_sound/proc/on_stop() if(end_sound) play(end_sound) \ No newline at end of file diff --git a/code/datums/martial.dm b/code/datums/martial.dm index c4b0eb7c60..2bc01e0bf6 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -55,7 +55,7 @@ playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) D.visible_message("[A] has attempted to [atk_verb] [D]!", \ "[A] has attempted to [atk_verb] [D]!", null, COMBAT_MESSAGE_RANGE) - add_logs(A, D, "attempted to [atk_verb]") + log_combat(A, D, "attempted to [atk_verb]") return 0 var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) @@ -67,7 +67,7 @@ D.apply_damage(damage, BRUTE, affecting, armor_block) - add_logs(A, D, "punched") + log_combat(A, D, "punched") if((D.stat != DEAD) && damage >= A.dna.species.punchstunthreshold) D.visible_message("[A] has knocked [D] down!!", \ diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index 20c3570bc1..c93fc47f2b 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -20,7 +20,7 @@ playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) D.visible_message("[A] has attempted to [atk_verb] [D]!", \ "[A] has attempted to [atk_verb] [D]!", null, COMBAT_MESSAGE_RANGE) - add_logs(A, D, "attempted to hit", atk_verb) + log_combat(A, D, "attempted to hit", atk_verb) return 0 @@ -33,7 +33,7 @@ "[A] has [atk_verb]ed [D]!", null, COMBAT_MESSAGE_RANGE) D.apply_damage(damage, STAMINA, affecting, armor_block) - add_logs(A, D, "punched (boxing) ") + log_combat(A, D, "punched (boxing) ") if(D.getStaminaLoss() > 100) var/knockout_prob = (D.getStaminaLoss() + rand(-15,15))*0.75 if((D.stat != DEAD) && prob(knockout_prob)) @@ -42,7 +42,7 @@ D.apply_effect(200,EFFECT_KNOCKDOWN,armor_block) D.SetSleeping(100) D.forcesay(GLOB.hit_appends) - add_logs(A, D, "knocked out (boxing) ") + log_combat(A, D, "knocked out (boxing) ") else if(D.lying) D.forcesay(GLOB.hit_appends) return 1 diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index 4a51ac3251..55cd4a3f7a 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -59,7 +59,7 @@ playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1) D.apply_damage(10, BRUTE) D.Knockdown(120) - add_logs(A, D, "cqc slammed") + log_combat(A, D, "slammed (CQC)") return TRUE /datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -72,7 +72,7 @@ var/atom/throw_target = get_edge_target_turf(D, A.dir) D.throw_at(throw_target, 1, 14, A) D.apply_damage(10, BRUTE) - add_logs(A, D, "cqc kicked") + log_combat(A, D, "kicked (CQC)") if(D.IsKnockdown() && !D.stat) D.visible_message("[A] kicks [D]'s head, knocking [D.p_them()] out!", \ "[A] kicks your head, knocking you out!") @@ -129,7 +129,7 @@ A.start_pulling(D, 1) if(A.pulling) D.stop_pulling() - add_logs(A, D, "grabbed", addition="aggressively") + log_combat(A, D, "grabbed", addition="aggressively") A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab return TRUE @@ -140,7 +140,7 @@ add_to_streak("H",D) if(check_streak(A,D)) return TRUE - add_logs(A, D, "CQC'd") + log_combat(A, D, "attacked (CQC)") A.do_attack_animation(D) var/picked_hit_type = pick("CQC'd", "Big Bossed") var/bonus_damage = 13 @@ -154,14 +154,14 @@ playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) D.visible_message("[A] [picked_hit_type] [D]!", \ "[A] [picked_hit_type] you!") - add_logs(A, D, "[picked_hit_type] with CQC") + log_combat(A, D, "[picked_hit_type] (CQC)") if(A.resting && !D.stat && !D.IsKnockdown()) D.visible_message("[A] leg sweeps [D]!", \ "[A] leg sweeps you!") playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) D.apply_damage(10, BRUTE) D.Knockdown(60) - add_logs(A, D, "cqc sweeped") + log_combat(A, D, "sweeped (CQC)") return TRUE /datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -185,7 +185,7 @@ D.visible_message("[A] attempted to disarm [D]!", \ "[A] attempted to disarm [D]!") playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - add_logs(A, D, "disarmed with CQC", "[I ? " grabbing \the [I]" : ""]") + log_combat(A, D, "disarmed (CQC)", "[I ? " grabbing \the [I]" : ""]") if(restraining && A.pulling == D) D.visible_message("[A] puts [D] into a chokehold!", \ "[A] puts you into a chokehold!") diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 21a82c7b7e..8a5f0f9439 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -93,7 +93,7 @@ playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) D.apply_damage(5, BRUTE) D.Knockdown(40) - add_logs(A, D, "leg sweeped") + log_combat(A, D, "leg sweeped") return 1 /datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch @@ -103,7 +103,7 @@ if(D.losebreath <= 10) D.losebreath = CLAMP(D.losebreath + 5, 0, 10) D.adjustOxyLoss(10) - add_logs(A, D, "quickchoked") + log_combat(A, D, "quickchoked") return 1 /datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) @@ -113,19 +113,19 @@ D.apply_damage(5, BRUTE) if(D.silent <= 10) D.silent = CLAMP(D.silent + 10, 0, 10) - add_logs(A, D, "neck chopped") + log_combat(A, D, "neck chopped") return 1 /datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(check_streak(A,D)) return 1 - add_logs(A, D, "grabbed with krav maga") + log_combat(A, D, "grabbed (Krav Maga)") ..() /datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(check_streak(A,D)) return 1 - add_logs(A, D, "punched") + log_combat(A, D, "punched") var/picked_hit_type = pick("punches", "kicks") var/bonus_damage = 10 if(D.IsKnockdown() || D.resting || D.lying) @@ -140,7 +140,7 @@ playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1) D.visible_message("[A] [picked_hit_type] [D]!", \ "[A] [picked_hit_type] you!") - add_logs(A, D, "[picked_hit_type] with [name]") + log_combat(A, D, "[picked_hit_type] with [name]") return 1 /datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) @@ -159,7 +159,7 @@ D.visible_message("[A] attempted to disarm [D]!", \ "[A] attempted to disarm [D]!") playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - add_logs(A, D, "disarmed with krav maga", "[I ? " removing \the [I]" : ""]") + log_combat(A, D, "disarmed (Krav Maga)", "[I ? " removing \the [I]" : ""]") return 1 //Krav Maga Gloves diff --git a/code/datums/martial/mushpunch.dm b/code/datums/martial/mushpunch.dm index 7c99d4d8aa..33d5bb51bf 100644 --- a/code/datums/martial/mushpunch.dm +++ b/code/datums/martial/mushpunch.dm @@ -17,7 +17,7 @@ D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time. D.Knockdown(20) if(atk_verb) - add_logs(A, D, "[atk_verb] (Mushroom Punch)") + log_combat(A, D, "[atk_verb] (Mushroom Punch)") return TRUE /obj/item/mushpunch diff --git a/code/datums/martial/plasma_fist.dm b/code/datums/martial/plasma_fist.dm index 0150a3695d..f540dc0783 100644 --- a/code/datums/martial/plasma_fist.dm +++ b/code/datums/martial/plasma_fist.dm @@ -32,14 +32,14 @@ sleep(1) /datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D) - A.say("TORNADO SWEEP!") + A.say("TORNADO SWEEP!", forced="plasma fist") TornadoAnimate(A) var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null) var/list/turfs = list() for(var/turf/T in range(1,A)) turfs.Add(T) R.cast(turfs) - add_logs(A, D, "tornado sweeped(Plasma Fist)") + log_combat(A, D, "tornado sweeped(Plasma Fist)") return /datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -48,18 +48,18 @@ playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) D.throw_at(throw_target, 200, 4,A) - A.say("HYAH!") - add_logs(A, D, "threw back (Plasma Fist)") + A.say("HYAH!", forced="plasma fist") + log_combat(A, D, "threw back (Plasma Fist)") return /datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D) A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - A.say("PLASMA FIST!") + A.say("PLASMA FIST!", forced="plasma fist") D.visible_message("[A] has hit [D] with THE PLASMA FIST TECHNIQUE!", \ "[A] has hit [D] with THE PLASMA FIST TECHNIQUE!") D.gib() - add_logs(A, D, "gibbed (Plasma Fist)") + log_combat(A, D, "gibbed (Plasma Fist)") return /datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm index ce3463367d..1cb18f903f 100644 --- a/code/datums/martial/psychotic_brawl.dm +++ b/code/datums/martial/psychotic_brawl.dm @@ -29,12 +29,12 @@ D.drop_all_held_items() D.stop_pulling() if(A.a_intent == INTENT_GRAB) - add_logs(A, D, "grabbed", addition="aggressively") + log_combat(A, D, "grabbed", addition="aggressively") D.visible_message("[A] violently grabs [D]!", \ "[A] violently grabs you!") A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab else - add_logs(A, D, "grabbed", addition="passively") + log_combat(A, D, "grabbed", addition="passively") A.grab_state = GRAB_PASSIVE if(4) A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) @@ -62,5 +62,5 @@ basic_hit(A,D) if(atk_verb) - add_logs(A, D, "[atk_verb] (Psychotic Brawling)") - return 1 + log_combat(A, D, "[atk_verb] (Psychotic Brawling)") + return 1 \ No newline at end of file diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index cda88187cd..4a15afd672 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -45,7 +45,7 @@ D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) D.Knockdown(60)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun() return 1 - add_logs(A, D, "wrist wrenched (Sleeping Carp)") + log_combat(A, D, "wrist wrenched (Sleeping Carp)") return basic_hit(A,D) /datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -57,7 +57,7 @@ D.Knockdown(80) playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) return 1 - add_logs(A, D, "back-kicked (Sleeping Carp)") + log_combat(A, D, "back-kicked (Sleeping Carp)") return basic_hit(A,D) /datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -70,7 +70,7 @@ D.Knockdown(40)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun() playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) return 1 - add_logs(A, D, "stomach kneed (Sleeping Carp)") + log_combat(A, D, "stomach kneed (Sleeping Carp)") return basic_hit(A,D) /datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -83,7 +83,7 @@ playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) D.Knockdown(80)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun() return 1 - add_logs(A, D, "head kicked (Sleeping Carp)") + log_combat(A, D, "head kicked (Sleeping Carp)") return basic_hit(A,D) /datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -96,7 +96,7 @@ D.apply_damage(50, BRUTE, BODY_ZONE_CHEST) playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1) return 1 - add_logs(A, D, "elbow dropped (Sleeping Carp)") + log_combat(A, D, "elbow dropped (Sleeping Carp)") return basic_hit(A,D) /datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -111,12 +111,12 @@ D.drop_all_held_items() D.stop_pulling() if(A.a_intent == INTENT_GRAB) - add_logs(A, D, "grabbed", addition="aggressively") + log_combat(A, D, "grabbed", addition="aggressively") D.visible_message("[A] violently grabs [D]!", \ "[A] violently grabs you!") A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab else - add_logs(A, D, "grabbed", addition="passively") + log_combat(A, D, "grabbed", addition="passively") A.grab_state = GRAB_PASSIVE return 1 @@ -133,7 +133,7 @@ if(prob(D.getBruteLoss()) && !D.lying) D.visible_message("[D] stumbles and falls!", "The blow sends you to the ground!") D.Knockdown(80) - add_logs(A, D, "[atk_verb] (Sleeping Carp)") + log_combat(A, D, "[atk_verb] (Sleeping Carp)") return 1 diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 62a03af933..e57edf9fb2 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -121,7 +121,7 @@ /datum/martial_art/wrestling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) if(check_streak(A,D)) return 1 - add_logs(A, D, "punched with wrestling") + log_combat(A, D, "punched with wrestling") ..() /datum/martial_art/wrestling/proc/throw_wrassle(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -192,7 +192,7 @@ if (!D.stat) D.emote("scream") D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human/.Knockdown, 20)) - add_logs(A, D, "has thrown with wrestling") + log_combat(A, D, "has thrown with wrestling") return 0 /datum/martial_art/wrestling/proc/FlipAnimation(mob/living/carbon/human/D) @@ -308,7 +308,7 @@ D.pixel_y = 0 - add_logs(A, D, "body-slammed") + log_combat(A, D, "body-slammed") return 0 /datum/martial_art/wrestling/proc/CheckStrikeTurf(mob/living/carbon/human/A, turf/T) @@ -330,7 +330,7 @@ D.adjustBruteLoss(rand(10,20)) playsound(A.loc, "swing_hit", 50, 1) D.Unconscious(20) - add_logs(A, D, "headbutted") + log_combat(A, D, "headbutted") /datum/martial_art/wrestling/proc/kick(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!D) @@ -347,7 +347,7 @@ if (T && isturf(T)) D.Knockdown(20) D.throw_at(T, 3, 2) - add_logs(A, D, "roundhouse-kicked") + log_combat(A, D, "roundhouse-kicked") /datum/martial_art/wrestling/proc/drop(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!D) @@ -420,13 +420,13 @@ else if (A) A.pixel_y = 0 - add_logs(A, D, "leg-dropped") + log_combat(A, D, "leg-dropped") return /datum/martial_art/wrestling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) if(check_streak(A,D)) return 1 - add_logs(A, D, "wrestling-disarmed") + log_combat(A, D, "wrestling-disarmed") ..() /datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -438,7 +438,7 @@ D.visible_message("[A] gets [D] in a cinch!", \ "[A] gets [D] in a cinch!") D.Stun(rand(60,100)) - add_logs(A, D, "cinched") + log_combat(A, D, "cinched") return 1 /obj/item/storage/belt/champion/wrestling diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5beb84a1f6..d467d8fd9d 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -62,6 +62,8 @@ var/unconvertable = FALSE var/late_joiner = FALSE + var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator + /datum/mind/New(var/key) src.key = key soulOwner = src @@ -254,7 +256,6 @@ var/mob/living/carbon/human/traitor_mob = current if (!istype(traitor_mob)) return - . = TRUE var/list/all_contents = traitor_mob.GetAllContents() var/obj/item/pda/PDA = locate() in all_contents @@ -302,6 +303,7 @@ to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") . = 0 else + . = uplink_loc uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key) var/unlock_note @@ -700,7 +702,7 @@ if(!has_antag_datum(/datum/antagonist/cult,TRUE)) SSticker.mode.add_cultist(src,FALSE,equip=TRUE) special_role = ROLE_CULTIST - to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar-Sie.") + to_chat(current, "You catch a glimpse of the Realm of Nar'Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar'Sie.") to_chat(current, "Assist your new brethren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") /datum/mind/proc/make_Rev() diff --git a/code/datums/mood_events/drink_events.dm b/code/datums/mood_events/drink_events.dm new file mode 100644 index 0000000000..db5a91009e --- /dev/null +++ b/code/datums/mood_events/drink_events.dm @@ -0,0 +1,24 @@ +/datum/mood_event/drunk + mood_change = 3 + description = "Everything just feels better after a drink or two.\n" + timeout = 3000 + +/datum/mood_event/quality_nice + description = "That drink wasn't bad at all.\n" + mood_change = 1 + timeout = 1200 + +/datum/mood_event/quality_good + description = "That drink was pretty good.\n" + mood_change = 2 + timeout = 1200 + +/datum/mood_event/quality_verygood + description = "That drink was great!\n" + mood_change = 3 + timeout = 1200 + +/datum/mood_event/quality_fantastic + description = "That drink was amazing!\n" + mood_change = 4 + timeout = 1200 diff --git a/code/datums/mood_events/drug_events.dm b/code/datums/mood_events/drug_events.dm index 5d585ab6b2..40c239180e 100644 --- a/code/datums/mood_events/drug_events.dm +++ b/code/datums/mood_events/drug_events.dm @@ -1,39 +1,39 @@ -/datum/mood_event/drugs/high +/datum/mood_event/high mood_change = 6 description = "Woooow duudeeeeee...I'm tripping baaalls...\n" -/datum/mood_event/drugs/smoked +/datum/mood_event/smoked description = "I have had a smoke recently.\n" mood_change = 2 timeout = 3600 -/datum/mood_event/drugs/overdose +/datum/mood_event/overdose mood_change = -8 timeout = 3000 -/datum/mood_event/drugs/overdose/add_effects(drug_name) +/datum/mood_event/overdose/add_effects(drug_name) description = "I think I took a bit too much of that [drug_name]\n" -/datum/mood_event/drugs/withdrawal_light +/datum/mood_event/withdrawal_light mood_change = -2 -/datum/mood_event/drugs/withdrawal_light/add_effects(drug_name) +/datum/mood_event/withdrawal_light/add_effects(drug_name) description = "I could use some [drug_name]\n" -/datum/mood_event/drugs/withdrawal_medium +/datum/mood_event/withdrawal_medium mood_change = -5 -/datum/mood_event/drugs/withdrawal_medium/add_effects(drug_name) +/datum/mood_event/withdrawal_medium/add_effects(drug_name) description = "I really need [drug_name]\n" -/datum/mood_event/drugs/withdrawal_severe +/datum/mood_event/withdrawal_severe mood_change = -8 -/datum/mood_event/drugs/withdrawal_severe/add_effects(drug_name) +/datum/mood_event/withdrawal_severe/add_effects(drug_name) description = "Oh god I need some [drug_name]\n" -/datum/mood_event/drugs/withdrawal_critical +/datum/mood_event/withdrawal_critical mood_change = -10 -/datum/mood_event/drugs/withdrawal_critical/add_effects(drug_name) +/datum/mood_event/withdrawal_critical/add_effects(drug_name) description = "[drug_name]! [drug_name]! [drug_name]!\n" diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 3ee3e9b048..2a93f74fa7 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -1,5 +1,5 @@ /datum/mood_event/handcuffed - description = "I guess my antics have finally caught up with me..\n" + description = "I guess my antics have finally caught up with me.\n" mood_change = -1 /datum/mood_event/broken_vow //Used for when mimes break their vow of silence @@ -63,8 +63,8 @@ timeout = 2400 /datum/mood_event/noshoes - description = "I am a disgrace to comedy everywhere!\n" - mood_change = -5 + description = "I am a disgrace to comedy everywhere!\n" + mood_change = -5 /datum/mood_event/tased description = "There's no \"z\" in \"taser\". It's in the zap.\n" @@ -84,8 +84,8 @@ if(ishuman(owner)) var/mob/living/carbon/human/H = owner if(iscatperson(H)) - H.startTailWag() - addtimer(CALLBACK(H, /mob/living/carbon/human.proc/endTailWag), 30) + H.dna.species.start_wagging_tail(H) + addtimer(CALLBACK(H.dna.species, /datum/species.proc/stop_wagging_tail, H), 30) description = "They want to play on the table!\n" mood_change = 2 diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 54eb74f10f..2422c5ea56 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -18,6 +18,11 @@ mood_change = 3 timeout = 3000 +/datum/mood_event/exercise + description = "Working out releases those endorphins!\n" + mood_change = 3 + timeout = 3000 + /datum/mood_event/pet_corgi description = "Corgis are adorable! I can't stop petting them!\n" mood_change = 3 @@ -60,3 +65,8 @@ /datum/mood_event/family_heirloom description = "My family heirloom is safe with me.\n" mood_change = 1 + +/datum/mood_event/goodmusic + description = "There is something soothing about this music.\n" + mood_change = 3 + timeout = 600 diff --git a/code/datums/mood_events/needs_events.dm b/code/datums/mood_events/needs_events.dm index 6d0ac42769..c67f4bf160 100644 --- a/code/datums/mood_events/needs_events.dm +++ b/code/datums/mood_events/needs_events.dm @@ -1,37 +1,45 @@ //nutrition -/datum/mood_event/nutrition/fat +/datum/mood_event/fat description = "I'm so fat...\n" //muh fatshaming mood_change = -4 -/datum/mood_event/nutrition/wellfed +/datum/mood_event/wellfed description = "My belly feels round and full.\n" mood_change = 6 -/datum/mood_event/nutrition/fed +/datum/mood_event/fed description = "I have recently had some food.\n" mood_change = 3 -/datum/mood_event/nutrition/hungry +/datum/mood_event/hungry description = "I'm getting a bit hungry.\n" mood_change = -8 -/datum/mood_event/nutrition/starving +/datum/mood_event/starving description = "I'm starving!\n" mood_change = -15 //Disgust -/datum/mood_event/disgust/gross +/datum/mood_event/gross description = "I saw something gross.\n" mood_change = -2 -/datum/mood_event/disgust/verygross +/datum/mood_event/verygross description = "I think I'm going to puke...\n" mood_change = -5 -/datum/mood_event/disgust/disgusted +/datum/mood_event/disgusted description = "Oh god that's disgusting...\n" mood_change = -8 +/datum/mood_event/disgust/bad_smell + description = "You smell something horribly decayed inside this room.\n" + mood_change = -3 + +/datum/mood_event/disgust/nauseating_stench + description = "The stench of rotting carcasses is unbearable!\n" + mood_change = -7 + //Generic needs events /datum/mood_event/favorite_food description = "I really enjoyed eating that.\n" @@ -39,12 +47,12 @@ timeout = 2400 /datum/mood_event/gross_food - description = "I really didn't like that food.\n" + description = "I really didn't like that food.\n" mood_change = -2 timeout = 2400 /datum/mood_event/disgusting_food - description = "That food was disgusting!\n" + description = "That food was disgusting!\n" mood_change = -4 timeout = 2400 diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index dbe150b0fa..e114a43736 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -107,7 +107,7 @@ if(1) owner.emote("twitch") if(2 to 3) - owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") + owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]", forced="tourette's syndrome") var/x_offset_old = owner.pixel_x var/y_offset_old = owner.pixel_y var/x_offset = owner.pixel_x + rand(-2,2) diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm index 33facca9a1..7d49db8429 100644 --- a/code/datums/position_point_vector.dm +++ b/code/datums/position_point_vector.dm @@ -6,8 +6,8 @@ #define RETURN_PRECISE_POSITION(A) new /datum/position(A) #define RETURN_PRECISE_POINT(A) new /datum/point(A) -#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) {new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)} -#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) {new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)} +#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)) +#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)) /proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below. var/datum/point/P = new diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index f02d352310..6fa1e2a476 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -24,8 +24,9 @@ START_PROCESSING(SSradiation, src) /datum/radiation_wave/Destroy() + . = QDEL_HINT_IWILLGC STOP_PROCESSING(SSradiation, src) - return ..() + ..() /datum/radiation_wave/process() master_turf = get_step(master_turf, move_dir) @@ -80,12 +81,10 @@ var/atom/thing = atoms[k] if(!thing) continue - var/datum/component/rad_insulation/insulation = thing.GetComponent(/datum/component/rad_insulation) - if(!insulation) - continue - intensity = intensity*(1-((1-insulation.amount)/width)) // The further out the rad wave goes the less it's affected by insulation + SEND_SIGNAL(thing, COMSIG_ATOM_RAD_WAVE_PASSING, src, width) /datum/radiation_wave/proc/radiate(list/atoms, strength) + var/contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1, 1/(steps*range_modifier)) for(var/k in 1 to atoms.len) var/atom/thing = atoms[k] if(!thing) @@ -106,11 +105,8 @@ )) if(!can_contaminate || blacklisted[thing.type]) continue - var/contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1, 1/(steps*range_modifier)) if(prob(contamination_chance)) // Only stronk rads get to have little baby rads - var/datum/component/rad_insulation/insulation = thing.GetComponent(/datum/component/rad_insulation) - if(insulation && insulation.contamination_proof) + if(SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION) continue - else - var/rad_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT - thing.AddComponent(/datum/component/radioactive, rad_strength, source) \ No newline at end of file + var/rad_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT + thing.AddComponent(/datum/component/radioactive, rad_strength, source) \ No newline at end of file diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index 163e087737..4006c13a2c 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -154,11 +154,12 @@ suffix = "lavaland_surface_ufo_crash.dmm" cost = 5 -/datum/map_template/ruin/lavaland/alien_nest - name = "Alien Nest" - id = "alien-nest" - description = "Not even Necropolis is safe from alien infestation. The competition for hosts has locked the legion and aliens in an endless conflict that can only be resolved by a PKA." - suffix = "lavaland_surface_alien_nest.dmm" +/datum/map_template/ruin/lavaland/xeno_nest + name = "Xenomorph Nest" + id = "xeno-nest" + description = "These xenomorphs got bored of horrifically slaughtering people on space stations, and have settled down on a nice lava filled hellscape to focus on what's really important in life. \ + Quality memes." + suffix = "lavaland_surface_xeno_nest.dmm" cost = 20 /datum/map_template/ruin/lavaland/fountain diff --git a/code/datums/saymode.dm b/code/datums/saymode.dm index 93f733439c..ed6edd11ab 100644 --- a/code/datums/saymode.dm +++ b/code/datums/saymode.dm @@ -40,7 +40,7 @@ return FALSE var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) var/msg = "[changeling.changelingID]: [message]" - log_talk(user,"[changeling.changelingID]/[user.key] : [message]",LOGSAY) + user.log_talk(message, LOG_SAY, tag="changeling [changeling.changelingID]") for(var/_M in GLOB.player_list) var/mob/M = _M if(M in GLOB.dead_mob_list) @@ -129,7 +129,7 @@ if(!mind) return TRUE if(is_monkey_leader(mind) || (ismonkey(user) && is_monkey(mind))) - log_talk(user, "(MONKEY) [user]/[user.key]: [message]",LOGSAY) + user.log_talk(message, LOG_SAY, tag="monkey") if(prob(75) && ismonkey(user)) user.visible_message("\The [user] chimpers.") var/msg = "\[[is_monkey_leader(mind) ? "Monkey Leader" : "Monkey"]\] [user]: [message]" diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index b53b334132..8e6ce98fc7 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -12,6 +12,8 @@ var/credit_cost = INFINITY var/can_be_bought = TRUE + var/port_x_offset + var/port_y_offset /datum/map_template/shuttle/proc/prerequisites_met() return TRUE @@ -21,7 +23,33 @@ mappath = "[prefix][shuttle_id].dmm" . = ..() -/datum/map_template/shuttle/load(turf/T, centered) +/datum/map_template/shuttle/preload_size(path, cache) + . = ..(path, TRUE) // Done this way because we still want to know if someone actualy wanted to cache the map + if(!cached_map) + return + + var/key + var/list/models = cached_map.grid_models + for(key in models) + if(findtext(models[key], "[/obj/docking_port/mobile]")) // Yay compile time checks + break // This works by assuming there will ever only be one mobile dock in a template at most + + var/datum/grid_set/gset + for(var/i in cached_map.gridSets) + gset = i + var/ycrd = gset.ycrd + for(var/line in gset.gridLines) + if(key != line) + ycrd-- + continue + port_x_offset = gset.xcrd + port_y_offset = ycrd + break + + if(!cache) + cached_map = null + +/datum/map_template/shuttle/load(turf/T, centered, register=TRUE) . = ..() if(!.) return @@ -34,7 +62,34 @@ if(length(place.baseturfs) < 2) // Some snowflake shuttle shit continue place.baseturfs.Insert(3, /turf/baseturf_skipover/shuttle) - + + for(var/obj/docking_port/mobile/port in place) + if(register) + port.register() + if(isnull(port_x_offset)) + return + switch(port.dir) // Yeah this looks a little ugly but mappers had to do this in their head before + if(NORTH) + port.width = width + port.height = height + port.dwidth = port_x_offset - 1 + port.dheight = port_y_offset - 1 + if(EAST) + port.width = height + port.height = width + port.dwidth = height - port_y_offset + port.dheight = port_x_offset - 1 + if(SOUTH) + port.width = width + port.height = height + port.dwidth = width - port_x_offset + port.dheight = height - port_y_offset + if(WEST) + port.width = height + port.height = width + port.dwidth = port_y_offset - 1 + port.dheight = width - port_x_offset + for(var/obj/structure/closet/closet in place) if(closet.anchorable) closet.anchored = TRUE @@ -110,6 +165,11 @@ // Shuttles start here: +/datum/map_template/shuttle/emergency/backup + suffix = "backup" + name = "Backup Shuttle" + can_be_bought = FALSE + /datum/map_template/shuttle/emergency/airless suffix = "airless" name = "Build your own shuttle kit" @@ -126,6 +186,7 @@ var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine] P.special_enabled = TRUE + /datum/map_template/shuttle/emergency/asteroid suffix = "asteroid" name = "Asteroid Station Emergency Shuttle" @@ -228,7 +289,7 @@ suffix = "scrapheap" name = "Standby Evacuation Vessel \"Scrapheap Challenge\"" credit_cost = -1000 - description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean to heavily on the exterior windows, they are fragile. VIRUS ALERT: This entry seems to be booby-trapped with a redirector trap. Buy this at your own risk." + description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean too heavily on the exterior windows, they are fragile." admin_notes = "An abomination with no functional medbay, sections missing, and some very fragile windows. Surprisingly airtight." /datum/map_template/shuttle/emergency/narnar @@ -324,11 +385,11 @@ /datum/map_template/shuttle/whiteship/box suffix = "box" - name = "NT Medical Ship" + name = "Hospital Ship" /datum/map_template/shuttle/whiteship/meta suffix = "meta" - name = "NT Recovery Whiteship" + name = "Salvage Ship" /datum/map_template/shuttle/whiteship/pubby suffix = "pubby" @@ -340,8 +401,11 @@ /datum/map_template/shuttle/whiteship/delta suffix = "delta" - name = "Unnamed NT Vessel" - admin_notes = "The Delta whiteship doesn't have a name, apparently." + name = "NT Frigate" + +/datum/map_template/shuttle/whiteship/pod + suffix = "whiteship_pod" + name = "Salvage Pod" /datum/map_template/shuttle/cargo/box suffix = "box" @@ -445,8 +509,8 @@ suffix = "syndicate_dropship" name = "Syndicate Dropship" -/datum/map_template/shuttle/ruin/syndicate_fighter - suffix = "syndicate_fighter" +/datum/map_template/shuttle/ruin/syndicate_fighter_shiv + suffix = "syndicate_fighter_shiv" name = "Syndicate Fighter" /datum/map_template/shuttle/snowdin/mining diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index b0f21fa776..d41cf4381c 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -70,7 +70,7 @@ return ..() /datum/status_effect/vanguard_shield/on_apply() - owner.log_message("gained Vanguard stun immunity", INDIVIDUAL_ATTACK_LOG) + owner.log_message("gained Vanguard stun immunity", LOG_ATTACK) owner.add_stun_absorption("vanguard", INFINITY, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " radiating with a soft yellow light!") owner.visible_message("[owner] begins to faintly glow!", "You will absorb all stuns for the next twenty seconds.") owner.SetStun(0, FALSE) @@ -105,7 +105,7 @@ else stuns_blocked = 0 //so logging is correct in cases where there were stuns blocked but we didn't stun for other reasons owner.visible_message("[owner]'s glowing aura fades!", message_to_owner) - owner.log_message("lost Vanguard stun immunity[stuns_blocked ? "and was stunned for [stuns_blocked]":""]", INDIVIDUAL_ATTACK_LOG) + owner.log_message("lost Vanguard stun immunity[stuns_blocked ? "and was stunned for [stuns_blocked]":""]", LOG_ATTACK) /datum/status_effect/inathneqs_endowment @@ -120,7 +120,7 @@ alerttooltipstyle = "clockcult" /datum/status_effect/inathneqs_endowment/on_apply() - owner.log_message("gained Inath-neq's invulnerability", INDIVIDUAL_ATTACK_LOG) + owner.log_message("gained Inath-neq's invulnerability", LOG_ATTACK) owner.visible_message("[owner] shines with azure light!", "You feel Inath-neq's power flow through you! You're invincible!") var/oldcolor = owner.color owner.color = "#1E8CE1" @@ -133,7 +133,7 @@ return ..() /datum/status_effect/inathneqs_endowment/on_remove() - owner.log_message("lost Inath-neq's invulnerability", INDIVIDUAL_ATTACK_LOG) + owner.log_message("lost Inath-neq's invulnerability", LOG_ATTACK) owner.visible_message("The light around [owner] flickers and dissipates!", "You feel Inath-neq's power fade from your body!") owner.status_flags &= ~GODMODE playsound(owner, 'sound/magic/ethereal_exit.ogg', 50, 1) @@ -185,7 +185,7 @@ ..() /datum/status_effect/his_grace/on_apply() - owner.log_message("gained His Grace's stun immunity", INDIVIDUAL_ATTACK_LOG) + owner.log_message("gained His Grace's stun immunity", LOG_ATTACK) owner.add_stun_absorption("hisgrace", INFINITY, 3, null, "His Grace protects you from the stun!") return ..() @@ -209,7 +209,7 @@ owner.adjustCloneLoss(-grace_heal) /datum/status_effect/his_grace/on_remove() - owner.log_message("lost His Grace's stun immunity", INDIVIDUAL_ATTACK_LOG) + owner.log_message("lost His Grace's stun immunity", LOG_ATTACK) if(islist(owner.stun_absorption) && owner.stun_absorption["hisgrace"]) owner.stun_absorption -= "hisgrace" @@ -242,7 +242,7 @@ /datum/status_effect/cult_master/proc/deathrattle() if(!QDELETED(GLOB.cult_narsie)) - return //if nar-sie is alive, don't even worry about it + return //if Nar'Sie is alive, don't even worry about it var/area/A = get_area(owner) for(var/datum/mind/B in SSticker.mode.cult) if(isliving(B.current)) @@ -304,7 +304,7 @@ last_oxyloss = owner.getOxyLoss() last_cloneloss = owner.getCloneLoss() last_staminaloss = owner.getStaminaLoss() - owner.log_message("gained blood-drunk stun immunity", INDIVIDUAL_ATTACK_LOG) + owner.log_message("gained blood-drunk stun immunity", LOG_ATTACK) owner.add_stun_absorption("blooddrunk", INFINITY, 4) owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1) @@ -380,7 +380,7 @@ owner.cloneloss *= 0.1 owner.staminaloss *= 0.1 owner.updatehealth() - owner.log_message("lost blood-drunk stun immunity", INDIVIDUAL_ATTACK_LOG) + owner.log_message("lost blood-drunk stun immunity", LOG_ATTACK) if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"]) owner.stun_absorption -= "blooddrunk" @@ -479,7 +479,7 @@ if(deathTick < 4) deathTick += 1 else - owner.visible_message("[owner]'s soul is absorbed into the rod, releaving the previous snake of it's duty.") + owner.visible_message("[owner]'s soul is absorbed into the rod, relieving the previous snake of its duty.") var/mob/living/simple_animal/hostile/retaliate/poison/snake/healSnake = new(owner.loc) var/list/chems = list("bicaridine", "salbutamol", "kelotane", "antitoxin") healSnake.poison_type = pick(chems) diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 74349caa73..9904a28d84 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -72,7 +72,7 @@ if(prob(20)) if(carbon_owner) carbon_owner.handle_dreams() - if(prob(10) && owner.health > HEALTH_THRESHOLD_CRIT) + if(prob(10) && owner.health > owner.crit_threshold) owner.emote("snore") /obj/screen/alert/status_effect/asleep @@ -124,7 +124,7 @@ qdel(src) /datum/status_effect/belligerent/proc/do_movement_toggle(force_damage) - var/number_legs = owner.get_num_legs() + var/number_legs = owner.get_num_legs(FALSE) if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check() && number_legs) if(force_damage || owner.m_intent != MOVE_INTENT_WALK) if(GLOB.ratvar_awakens) @@ -224,7 +224,7 @@ if(is_eligible_servant(owner)) to_chat(owner, "\"[text2ratvar("You are mine and his, now.")]\"") if(add_servant_of_ratvar(owner)) - owner.log_message("Conversion was done with a Mania Motor.", INDIVIDUAL_ATTACK_LOG) + owner.log_message("conversion was done with a Mania Motor", LOG_ATTACK, color="#BE8700") owner.Unconscious(100) else if(prob(severity * 0.15)) @@ -468,7 +468,7 @@ var/health_difference = old_health - owner.health if(!health_difference) return - owner.visible_message("The light in [owner]'s eyes dims as they're harmed!", \ + owner.visible_message("The light in [owner]'s eyes dims as [owner.p_theyre()] harmed!", \ "The dazzling lights dim as you're harmed!") health_difference *= 2 //so 10 health difference translates to 20 deciseconds of stun reduction duration -= health_difference diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm index ee974a6e6e..dfe0a1d94e 100644 --- a/code/datums/status_effects/gas.dm +++ b/code/datums/status_effects/gas.dm @@ -9,11 +9,11 @@ /obj/screen/alert/status_effect/freon name = "Frozen Solid" - desc = "You're frozen inside of an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!" + desc = "You're frozen inside an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!" icon_state = "frozen" /datum/status_effect/freon/on_apply() - redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST), CALLBACK(src, .proc/owner_resist))) + redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist)))) if(!owner.stat) to_chat(owner, "You become frozen in a cube!") cube = icon('icons/effects/freeze.dmi', "ice_cube") diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm index ff3cb85b27..c7a8fa5f55 100644 --- a/code/datums/traits/good.dm +++ b/code/datums/traits/good.dm @@ -9,8 +9,6 @@ gain_text = "You feel like you could drink a whole keg!" lose_text = "You don't feel as resistant to alcohol anymore. Somehow." - - /datum/quirk/apathetic name = "Apathetic" desc = "You just don't care as much as other people. That's nice to have in a place like this, I guess." @@ -23,11 +21,10 @@ mood.mood_modifier = 0.8 /datum/quirk/apathetic/remove() - GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder) - if(mood) - mood.mood_modifier = 1 //Change this once/if species get their own mood modifiers. - - + if(quirk_holder) + GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder) + if(mood) + mood.mood_modifier = 1 //Change this once/if species get their own mood modifiers. /datum/quirk/drunkhealing name = "Drunken Resilience" @@ -38,7 +35,6 @@ lose_text = "You no longer feel like drinking would ease your pain." medical_record_text = "Patient has unusually efficient liver metabolism and can slowly regenerate wounds by drinking alcoholic beverages." - /datum/quirk/freerunning name = "Freerunning" desc = "You're great at quick moves! You can climb tables more quickly." @@ -47,8 +43,6 @@ gain_text = "You feel lithe on your feet!" lose_text = "You feel clumsy again." - - /datum/quirk/jolly name = "Jolly" desc = "You sometimes just feel happy, for no reason at all." @@ -56,17 +50,31 @@ mob_trait = TRAIT_JOLLY mood_quirk = TRUE - - /datum/quirk/light_step name = "Light Step" - desc = "You walk with a gentle step, making stepping on sharp objects quieter and less painful." + desc = "You walk with a gentle step; stepping on sharp objects is quieter, less painful and you won't leave footprints behind you." value = 1 mob_trait = TRAIT_LIGHT_STEP gain_text = "You walk with a little more litheness." lose_text = "You start tromping around like a barbarian." +/datum/quirk/musician + name = "Musician" + desc = "You can tune handheld musical instruments to play melodies that clear certain negative effects and soothe the soul." + value = 1 + mob_trait = TRAIT_MUSICIAN + gain_text = "You know everything about musical instruments." + lose_text = "You forget how musical instruments work." +/datum/quirk/musician/on_spawn() + var/mob/living/carbon/human/H = quirk_holder + var/obj/item/instrument/guitar/guitar = new(get_turf(H)) + H.put_in_hands(guitar) + H.equip_to_slot(guitar, SLOT_IN_BACKPACK) + var/obj/item/musicaltuner/musicaltuner = new(get_turf(H)) + H.put_in_hands(musicaltuner) + H.equip_to_slot(musicaltuner, SLOT_IN_BACKPACK) + H.regenerate_icons() /datum/quirk/night_vision name = "Night Vision" @@ -83,7 +91,20 @@ return eyes.Insert(H) //refresh their eyesight and vision +/datum/quirk/photographer + name = "Photographer" + desc = "You know how to handle a camera, shortening the delay between each shot." + value = 1 + mob_trait = TRAIT_PHOTOGRAPHER + gain_text = "You know everything about photography." + lose_text = "You forget how photo cameras work." +/datum/quirk/photographer/on_spawn() + var/mob/living/carbon/human/H = quirk_holder + var/obj/item/camera/camera = new(get_turf(H)) + H.put_in_hands(camera) + H.equip_to_slot(camera, SLOT_NECK) + H.regenerate_icons() /datum/quirk/selfaware name = "Self-Aware" @@ -91,16 +112,12 @@ value = 2 mob_trait = TRAIT_SELF_AWARE - - /datum/quirk/skittish name = "Skittish" desc = "You can conceal yourself in danger. Ctrl-shift-click a closed locker to jump into it, as long as you have access." value = 2 mob_trait = TRAIT_SKITTISH - - /datum/quirk/spiritual name = "Spiritual" desc = "You're in tune with the gods, and your prayers may be more likely to be heard. Or not." @@ -109,7 +126,20 @@ gain_text = "You feel a little more faithful to the gods today." lose_text = "You feel less faithful in the gods." +/datum/quirk/tagger + name = "Tagger" + desc = "You're an experienced artist. While drawing graffiti, you can get twice as many uses out of drawing supplies." + value = 1 + mob_trait = TRAIT_TAGGER + gain_text = "You know how to tag walls efficiently." + lose_text = "You forget how to tag walls properly." +/datum/quirk/tagger/on_spawn() + var/mob/living/carbon/human/H = quirk_holder + var/obj/item/toy/crayon/spraycan/spraycan = new(get_turf(H)) + H.put_in_hands(spraycan) + H.equip_to_slot(spraycan, SLOT_IN_BACKPACK) + H.regenerate_icons() /datum/quirk/voracious name = "Voracious" diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 2f2ee53e3e..b05e00d35c 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -15,8 +15,6 @@ else quirk_holder.blood_volume -= 0.275 - - /datum/quirk/depression name = "Depression" desc = "You sometimes just hate life." @@ -27,8 +25,6 @@ medical_record_text = "Patient has a severe mood disorder causing them to experience sudden moments of sadness." mood_quirk = TRUE - - /datum/quirk/family_heirloom name = "Family Heirloom" desc = "You are the current owner of an heirloom, passed down for generations. You have to keep it safe!" @@ -111,8 +107,6 @@ /datum/quirk/brainproblems/on_process() quirk_holder.adjustBrainLoss(0.2) - - /datum/quirk/nearsighted //t. errorage name = "Nearsighted" desc = "You are nearsighted without prescription glasses, but spawn with a pair." @@ -131,8 +125,6 @@ H.equip_to_slot(glasses, SLOT_GLASSES) H.regenerate_icons() //this is to remove the inhand icon, which persists even if it's not in their hands - - /datum/quirk/nyctophobia name = "Nyctophobia" desc = "As far as you can remember, you've always been afraid of the dark. While in the dark without a light source, you instinctually act careful, and constantly feel a sense of dread." @@ -152,8 +144,6 @@ else SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia") - - /datum/quirk/nonviolent name = "Pacifist" desc = "The thought of violence makes you sick. So much so, in fact, that you can't hurt anyone." @@ -168,8 +158,6 @@ to_chat(quirk_holder, "Your antagonistic nature has caused you to renounce your pacifism.") qdel(src) - - /datum/quirk/poor_aim name = "Poor Aim" desc = "You're terrible with guns and can't line up a straight shot to save your life. Dual-wielding is right out." @@ -177,8 +165,6 @@ mob_trait = TRAIT_POOR_AIM medical_record_text = "Patient possesses a strong tremor in both hands." - - /datum/quirk/prosopagnosia name = "Prosopagnosia" desc = "You have a mental disorder that prevents you from being able to recognize faces at all." @@ -186,8 +172,6 @@ mob_trait = TRAIT_PROSOPAGNOSIA medical_record_text = "Patient suffers from prosopagnosia and cannot recognize faces." - - /datum/quirk/prosthetic_limb name = "Prosthetic Limb" desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!" @@ -220,8 +204,6 @@ to_chat(quirk_holder, "Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \ you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.") - - /datum/quirk/insanity name = "Reality Dissociation Syndrome" desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. This is not a license to grief." @@ -247,8 +229,6 @@ to_chat(quirk_holder, "Please note that your dissociation syndrome does NOT give you the right to attack people or otherwise cause any interference to \ the round. You are not an antagonist, and the rules will treat you the same as other crewmembers.") - - /datum/quirk/social_anxiety name = "Social Anxiety" desc = "Talking to people is very difficult for you, and you often stutter or even lock up." @@ -260,7 +240,7 @@ /datum/quirk/social_anxiety/on_process() var/nearby_people = 0 - for(var/mob/living/carbon/human/H in view(5, quirk_holder)) + for(var/mob/living/carbon/human/H in oview(3, quirk_holder)) if(H.client) nearby_people++ var/mob/living/carbon/human/H = quirk_holder diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index 8ef9bf0a11..4fc30de473 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -10,8 +10,6 @@ lose_text = "You can taste again!" medical_record_text = "Patient suffers from ageusia and is incapable of tasting food or reagents." - - /datum/quirk/pineapple_liker name = "Ananas Affinity" desc = "You find yourself greatly enjoying fruits of the ananas genus. You can't seem to ever get enough of their sweet goodness!" @@ -26,8 +24,9 @@ /datum/quirk/pineapple_liker/remove() var/mob/living/carbon/human/H = quirk_holder - var/datum/species/species = H.dna.species - species.liked_food &= ~PINEAPPLE + if(H) + var/datum/species/species = H.dna.species + species.liked_food &= ~PINEAPPLE /datum/quirk/pineapple_hater name = "Ananas Aversion" @@ -43,8 +42,9 @@ /datum/quirk/pineapple_hater/remove() var/mob/living/carbon/human/H = quirk_holder - var/datum/species/species = H.dna.species - species.disliked_food &= ~PINEAPPLE + if(H) + var/datum/species/species = H.dna.species + species.disliked_food &= ~PINEAPPLE /datum/quirk/deviant_tastes name = "Deviant Tastes" @@ -62,11 +62,10 @@ /datum/quirk/deviant_tastes/remove() var/mob/living/carbon/human/H = quirk_holder - var/datum/species/species = H.dna.species - species.liked_food = initial(species.liked_food) - species.disliked_food = initial(species.disliked_food) - - + if(H) + var/datum/species/species = H.dna.species + species.liked_food = initial(species.liked_food) + species.disliked_food = initial(species.disliked_food) /datum/quirk/monochromatic name = "Monochromacy" @@ -83,4 +82,5 @@ quirk_holder.playsound_local(quirk_holder, 'sound/ambience/ambidet1.ogg', 50, FALSE) /datum/quirk/monochromatic/remove() - quirk_holder.remove_client_colour(/datum/client_colour/monochrome) + if(quirk_holder) + quirk_holder.remove_client_colour(/datum/client_colour/monochrome) diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index 2a00f51314..173f7e6b33 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -81,9 +81,13 @@ if(ishuman(L)) //Are you immune? var/mob/living/carbon/human/H = L var/thermal_protection = H.get_thermal_protection() - if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) + if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT) return TRUE - L = L.loc //Matryoshka check + if(isliving(L))// if we're a non immune mob inside an immune mob we have to reconsider if that mob is immune to protect ourselves + var/mob/living/the_mob = L + if("ash" in the_mob.weather_immunities) + return TRUE + L = L.loc //Check parent items immunities (recurses up to the turf) return FALSE //RIP you /datum/weather/ash_storm/weather_act(mob/living/L) diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index 0e38475c85..f1b08ee18b 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -257,8 +257,8 @@ if("cut") I = L.is_holding_tool_quality(TOOL_WIRECUTTER) if(I || IsAdminGhost(usr)) - if(I) - I.play_tool_sound(src, 20) + if(I && holder) + I.play_tool_sound(holder, 20) cut_color(target_wire) . = TRUE else @@ -266,8 +266,8 @@ if("pulse") I = L.is_holding_tool_quality(TOOL_MULTITOOL) if(I || IsAdminGhost(usr)) - if(I) - I.play_tool_sound(src, 20) + if(I && holder) + I.play_tool_sound(holder, 20) pulse_color(target_wire, L) . = TRUE else diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index e6f79c67b0..63140e6b25 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -80,7 +80,7 @@ A.set_electrified(30) if(usr) LAZYADD(A.shockedby, text("\[[time_stamp()]\] [key_name(usr)]")) - add_logs(usr, A, "electrified") + log_combat(usr, A, "electrified") if(WIRE_SAFETY) A.safe = !A.safe if(!A.density) @@ -135,7 +135,7 @@ A.set_electrified(-1) if(usr) LAZYADD(A.shockedby, text("\[[time_stamp()]\] [key_name(usr)]")) - add_logs(usr, A, "electrified") + log_combat(usr, A, "electrified") if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. A.safe = mend if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable. diff --git a/code/datums/wires/emitter.dm b/code/datums/wires/emitter.dm index df1cf05a9c..d0e1352c0e 100644 --- a/code/datums/wires/emitter.dm +++ b/code/datums/wires/emitter.dm @@ -1,13 +1,17 @@ /datum/wires/emitter - randomize = 1 //Only one wire don't need blueprints holder_type = /obj/machinery/power/emitter /datum/wires/emitter/New(atom/holder) - wires = list(WIRE_ZAP) + wires = list(WIRE_ZAP,WIRE_HACK) ..() /datum/wires/emitter/on_pulse(wire) var/obj/machinery/power/emitter/E = holder - E.fire_beam_pulse() + switch(wire) + if(WIRE_ZAP) + E.fire_beam_pulse() + if(WIRE_HACK) + E.mode = !E.mode + E.set_projectile() ..() diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm index 9de3b04333..3d1ed8b746 100644 --- a/code/datums/wires/explosive.dm +++ b/code/datums/wires/explosive.dm @@ -23,7 +23,7 @@ /datum/wires/explosive/c4/explode() var/obj/item/grenade/plastic/c4/P = holder - P.explode() + P.prime() /datum/wires/explosive/pizza diff --git a/modular_citadel/code/modules/vore/eating/living_vr.dm b/modular_citadel/code/modules/vore/eating/living_vr.dm index f1b0af9258..fb39b34941 100644 --- a/modular_citadel/code/modules/vore/eating/living_vr.dm +++ b/modular_citadel/code/modules/vore/eating/living_vr.dm @@ -161,7 +161,8 @@ belly.nom_mob(prey, user) if (pred == user) message_admins("[key_name(pred)] ate [key_name(prey)].") - log_attack("[key_name(pred)] ate [key_name(prey)]") + pred.log_message("[key_name(pred)] ate [key_name(prey)].", LOG_ATTACK) + prey.log_message("[key_name(prey)] was eaten by [key_name(pred)].", LOG_ATTACK) return TRUE // // Master vore proc that actually does vore procedures @@ -230,10 +231,13 @@ prey_braindead = 1 if (pred == user) message_admins("[ADMIN_LOOKUPFLW(pred)] ate [ADMIN_LOOKUPFLW(prey)][!prey_braindead ? "" : " (BRAINDEAD)"][prey_stat ? " (DEAD/UNCONSCIOUS)" : ""].") - log_attack("[key_name(pred)] ate [key_name(prey)]") + pred.log_message("[key_name(pred)] ate [key_name(prey)].", LOG_ATTACK) + prey.log_message("[key_name(prey)] was eaten by [key_name(pred)].", LOG_ATTACK) else message_admins("[ADMIN_LOOKUPFLW(user)] forced [ADMIN_LOOKUPFLW(pred)] to eat [ADMIN_LOOKUPFLW(prey)].") - log_attack("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)].") + user.log_message("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)].", LOG_ATTACK) + pred.log_message("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)].", LOG_ATTACK) + prey.log_message("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)].", LOG_ATTACK) return TRUE //