diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 009ed44faf..e8bc1d954e 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -69,27 +69,6 @@ #define ADMIN_VERBOSEJMP(src) "[src ? "[AREACOORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]" #define ADMIN_INDIVIDUALLOG(user) "(LOGS)" -#define ADMIN_PUNISHMENT_LIGHTNING "Lightning bolt" -#define ADMIN_PUNISHMENT_BRAINDAMAGE "Brain damage" -#define ADMIN_PUNISHMENT_GIB "Gib" -#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device" -#define ADMIN_PUNISHMENT_FIREBALL "Fireball" -#define ADMIN_PUNISHMENT_ROD "Immovable Rod" -#define ADMIN_PUNISHMENT_SUPPLYPOD_QUICK "Supply Pod (Quick)" -#define ADMIN_PUNISHMENT_SUPPLYPOD "Supply Pod" -#define ADMIN_PUNISHMENT_MAZING "Puzzle" -#define ADMIN_PUNISHMENT_PIE "Cream Pie" -#define ADMIN_PUNISHMENT_CUSTOM_PIE "Custom Cream Pie" -#define ADMIN_PUNISHMENT_SHOES "Knot Shoes" -#define ADMIN_PUNISHMENT_CRACK ":B:oneless" -#define ADMIN_PUNISHMENT_BLEED ":B:loodless" -#define ADMIN_PUNISHMENT_SCARIFY "Scarify" -#define ADMIN_PUNISHMENT_PICKLE "Pickle-ify" -#define ADMIN_PUNISHMENT_FRY "Fry" -#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate" -#define ADMIN_PUNISHMENT_CLUWNE "Cluwne" -#define ADMIN_PUNISHMENT_GOODBYE "Their final message" //sandstorm - #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 #define AHELP_RESOLVED 3 diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 41c164b667..28e0d9d159 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -712,3 +712,11 @@ #define COMSIG_ALARM_TRIGGERED "comsig_alarm_triggered" ///Send when an alarm source is cleared (alarm_type, area/source_area) #define COMSIG_ALARM_CLEARED "comsig_alarm_clear" + +/// Admin helps +/// From /datum/admin_help/RemoveActive(). +/// Fired when an adminhelp is made inactive either due to closing or resolving. +#define COMSIG_ADMIN_HELP_MADE_INACTIVE "admin_help_made_inactive" + +/// Called when the player replies. From /client/proc/cmd_admin_pm(). +#define COMSIG_ADMIN_HELP_REPLIED "admin_help_replied" diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm index 578dfe87e5..64d8b5f02c 100644 --- a/code/__DEFINES/layers_planes.dm +++ b/code/__DEFINES/layers_planes.dm @@ -200,5 +200,8 @@ #define SPLASHSCREEN_PLANE 90 #define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE" +// Admin popup layer +#define ADMIN_POPUP_LAYER 1 + ///Layer for screentips #define SCREENTIP_LAYER 40 diff --git a/code/_globalvars/lists/admin.dm b/code/_globalvars/lists/admin.dm new file mode 100644 index 0000000000..9ee6ab6208 --- /dev/null +++ b/code/_globalvars/lists/admin.dm @@ -0,0 +1,8 @@ +/proc/init_smites() + var/list/smites = list() + for (var/_smite_path in subtypesof(/datum/smite)) + var/datum/smite/smite_path = _smite_path + smites[initial(smite_path.name)] = smite_path + return smites + +GLOBAL_LIST_INIT_TYPED(smites, /datum/smite, init_smites()) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index f7c864a89f..148d0be3d7 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -347,3 +347,6 @@ /datum/config_entry/str_list/randomizing_station_name_message default = list() + +/// Gives the ability to send players a maptext popup. +/datum/config_entry/flag/popup_admin_pm diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm index 529f9dee5c..2725a71eeb 100644 --- a/code/controllers/subsystem/traumas.dm +++ b/code/controllers/subsystem/traumas.dm @@ -39,7 +39,8 @@ SUBSYSTEM_DEF(traumas) "mimes" = strings(PHOBIA_FILE, "mimes"), "cats" = strings(PHOBIA_FILE, "cats"), "syndicate"= strings(PHOBIA_FILE, "syndicate"), - "eye" = strings(PHOBIA_FILE, "eye") + "eye" = strings(PHOBIA_FILE, "eye"), + "ocky icky" = strings(PHOBIA_FILE, "ocky icky") ) phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)), diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm index 10c217c6a9..4dbe2d507a 100644 --- a/code/datums/brain_damage/phobia.dm +++ b/code/datums/brain_damage/phobia.dm @@ -213,3 +213,7 @@ /datum/brain_trauma/mild/phobia/conspiracies phobia_type = "conspiracies" random_gain = FALSE + +/datum/brain_trauma/mild/phobia/ocky_icky + phobia_type = "ocky icky" + random_gain = FALSE diff --git a/code/datums/components/admin_popup.dm b/code/datums/components/admin_popup.dm new file mode 100644 index 0000000000..0542dd1a0c --- /dev/null +++ b/code/datums/components/admin_popup.dm @@ -0,0 +1,125 @@ +/// Applied to clients when they receive an admin popup, alerting them to +/// their ticket. +/datum/component/admin_popup + /// The user's most active ticket. If this is resolved, closed, or replied to, + /// then the component will delete itself. + var/datum/admin_help/ticket + + var/atom/movable/screen/admin_popup/admin_popup + +/datum/component/admin_popup/Initialize(datum/admin_help/ticket) + if (!istype(parent, /client)) + return COMPONENT_INCOMPATIBLE + + if (!istype(ticket)) + return COMPONENT_INCOMPATIBLE + + create_notice() + + RegisterSignal( + ticket, + list( + COMSIG_ADMIN_HELP_MADE_INACTIVE, + COMSIG_ADMIN_HELP_REPLIED, + COMSIG_PARENT_QDELETING, + ), + PROC_REF(delete_self), + ) + +/datum/component/admin_popup/Destroy(force) + var/client/parent_client = parent + + parent_client?.screen -= admin_popup + QDEL_NULL(admin_popup) + + if (!QDELETED(ticket)) + UnregisterSignal(ticket, list( + COMSIG_ADMIN_HELP_MADE_INACTIVE, + COMSIG_ADMIN_HELP_REPLIED, + COMSIG_PARENT_QDELETING, + )) + + ticket = null + + return ..() + +/datum/component/admin_popup/proc/create_notice() + if(admin_popup) + qdel(admin_popup) + admin_popup = new + + var/client/parent_client = parent + admin_popup.maptext_width = view_to_pixels(parent_client.view_size.getView())[1] + parent_client.screen += admin_popup + +/datum/component/admin_popup/proc/delete_self() + SIGNAL_HANDLER + qdel(src) + +/// The UI element for admin popups +/atom/movable/screen/admin_popup + icon = null + icon_state = null + plane = ABOVE_HUD_PLANE + layer = ADMIN_POPUP_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + screen_loc = "TOP-5,LEFT" + maptext_height = 480 + maptext_width = 480 + maptext = "" + + var/static/list/colors = list( + COLOR_RED, + COLOR_ORANGE, + COLOR_YELLOW, + COLOR_LIME, + COLOR_CYAN, + COLOR_PURPLE, + ) + + /// The last color chosen in the animation, sourced from the static list colors. + var/last_color_index = 0 + + /// The `world.time` when the last color update occurred. + var/last_update_time = 0 + +/atom/movable/screen/admin_popup/Initialize(mapload, datum/hud/hud_owner, ...) + . = ..() + + START_PROCESSING(SSobj, src) + update_text() + +/atom/movable/screen/admin_popup/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/atom/movable/screen/admin_popup/process(seconds_per_tick) + update_text() + +/atom/movable/screen/admin_popup/proc/update_text() + // Even if processing time changes, we want this to remain slow. + // We want to pester them into reading their ticket, not give them a seizure! + if (world.time - last_update_time < 2 SECONDS) + return + + last_color_index = (last_color_index % colors.len) + 1 + + var/message = "" + message += "HEY!
An admin is trying to talk to you!
Check your chat window,
and click their name to respond!" + message += "
" + + maptext = MAPTEXT(message) + last_update_time = world.time + +/// Tries to give the target an admin popup. +/// If it fails, will send the error to the passed admin. +/proc/give_admin_popup(client/target, client/admin, message) + log_admin("[key_name(admin)] sent an admin popup to [key_name(target)].") + + var/datum/admin_help/current_ticket = target.current_ticket + if (!current_ticket) + to_chat(admin, span_warning("[key_name(target)] had no active ahelp, aborting.")) + return + + admin.cmd_admin_pm(target, message) + target.AddComponent(/datum/component/admin_popup, current_ticket) diff --git a/code/datums/components/manual_blinking.dm b/code/datums/components/manual_blinking.dm new file mode 100644 index 0000000000..d5afbcabdc --- /dev/null +++ b/code/datums/components/manual_blinking.dm @@ -0,0 +1,83 @@ +/datum/component/manual_blinking + dupe_mode = COMPONENT_DUPE_UNIQUE + + var/obj/item/organ/eyes/E + var/warn_grace = FALSE + var/warn_dying = FALSE + var/last_blink + var/check_every = 20 SECONDS + var/grace_period = 6 SECONDS + var/damage_rate = 1 // organ damage taken per tick + var/list/valid_emotes = list(/datum/emote/living/carbon/blink, /datum/emote/living/carbon/blink_r) + +/datum/component/manual_blinking/Initialize() + if(!iscarbon(parent)) + return COMPONENT_INCOMPATIBLE + + var/mob/living/carbon/C = parent + E = C.getorganslot(ORGAN_SLOT_EYES) + + if(E) + START_PROCESSING(SSdcs, src) + last_blink = world.time + to_chat(C, "You suddenly realize you're blinking manually.") + +/datum/component/manual_blinking/Destroy(force, silent) + E = null + STOP_PROCESSING(SSdcs, src) + to_chat(parent, "You revert back to automatic blinking.") + return ..() + +/datum/component/manual_blinking/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOB_EMOTE, .proc/check_emote) + RegisterSignal(parent, COMSIG_ORGAN_INSERTED, .proc/check_added_organ) + RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/check_removed_organ) + RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/restart) + RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/pause) + +/datum/component/manual_blinking/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_MOB_EMOTE) + UnregisterSignal(parent, COMSIG_ORGAN_INSERTED) + UnregisterSignal(parent, COMSIG_ORGAN_REMOVED) + UnregisterSignal(parent, COMSIG_LIVING_REVIVE) + UnregisterSignal(parent, COMSIG_MOB_DEATH) + +/datum/component/manual_blinking/proc/restart() + START_PROCESSING(SSdcs, src) + +/datum/component/manual_blinking/proc/pause() + STOP_PROCESSING(SSdcs, src) + +/datum/component/manual_blinking/process() + var/mob/living/carbon/C = parent + + if(world.time > (last_blink + check_every + grace_period)) + if(!warn_dying) + to_chat(C, "Your eyes begin to wither, you need to blink!") + warn_dying = TRUE + + E.applyOrganDamage(damage_rate) + else if(world.time > (last_blink + check_every)) + if(!warn_grace) + to_chat(C, "You feel a need to blink!") + warn_grace = TRUE + +/datum/component/manual_blinking/proc/check_added_organ(mob/who_cares, obj/item/organ/O) + var/obj/item/organ/eyes/new_eyes = O + + if(istype(new_eyes,/obj/item/organ/eyes)) + E = new_eyes + START_PROCESSING(SSdcs, src) + +/datum/component/manual_blinking/proc/check_removed_organ(mob/who_cares, obj/item/organ/O) + var/obj/item/organ/eyes/bye_beyes = O // oh come on, that's pretty good + + if(istype(bye_beyes, /obj/item/organ/eyes)) + E = null + STOP_PROCESSING(SSdcs, src) + +/datum/component/manual_blinking/proc/check_emote(mob/living/carbon/user, datum/emote/emote) + if(emote.type in valid_emotes) + warn_grace = FALSE + warn_dying = FALSE + last_blink = world.time diff --git a/code/datums/components/manual_breathing.dm b/code/datums/components/manual_breathing.dm new file mode 100644 index 0000000000..45155285bf --- /dev/null +++ b/code/datums/components/manual_breathing.dm @@ -0,0 +1,93 @@ +/datum/component/manual_breathing + dupe_mode = COMPONENT_DUPE_UNIQUE + + var/obj/item/organ/lungs/L + var/warn_grace = FALSE + var/warn_dying = FALSE + var/last_breath + var/check_every = 12 SECONDS + var/grace_period = 6 SECONDS + var/damage_rate = 1 // organ damage taken per tick + var/datum/emote/next_breath_type = /datum/emote/inhale + +/datum/component/manual_breathing/Initialize() + if(!iscarbon(parent)) + return COMPONENT_INCOMPATIBLE + + var/mob/living/carbon/C = parent + L = C.getorganslot(ORGAN_SLOT_LUNGS) + + if(L) + START_PROCESSING(SSdcs, src) + last_breath = world.time + to_chat(C, "You suddenly realize you're breathing manually.") + +/datum/component/manual_breathing/Destroy(force, silent) + L = null + STOP_PROCESSING(SSdcs, src) + to_chat(parent, "You revert back to automatic breathing.") + return ..() + +/datum/component/manual_breathing/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOB_EMOTE, .proc/check_emote) + RegisterSignal(parent, COMSIG_ORGAN_INSERTED, .proc/check_added_organ) + RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/check_removed_organ) + RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/restart) + RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/pause) + +/datum/component/manual_breathing/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_MOB_EMOTE) + UnregisterSignal(parent, COMSIG_ORGAN_INSERTED) + UnregisterSignal(parent, COMSIG_ORGAN_REMOVED) + UnregisterSignal(parent, COMSIG_LIVING_REVIVE) + UnregisterSignal(parent, COMSIG_MOB_DEATH) + +/datum/component/manual_breathing/proc/restart() + START_PROCESSING(SSdcs, src) + +/datum/component/manual_breathing/proc/pause() + STOP_PROCESSING(SSdcs, src) + +/datum/component/manual_breathing/process() + var/mob/living/carbon/C = parent + + var/next_text = initial(next_breath_type.key) + if(world.time > (last_breath + check_every + grace_period)) + if(!warn_dying) + to_chat(C, "You begin to suffocate, you need to [next_text]!") + warn_dying = TRUE + + L.applyOrganDamage(damage_rate) + C.losebreath += 0.8 + else if(world.time > (last_breath + check_every)) + if(!warn_grace) + to_chat(C, "You feel a need to [next_text]!") + warn_grace = TRUE + +/datum/component/manual_breathing/proc/check_added_organ(mob/who_cares, obj/item/organ/O) + var/obj/item/organ/eyes/new_lungs = O + + if(istype(new_lungs,/obj/item/organ/lungs)) + L = new_lungs + START_PROCESSING(SSdcs, src) + +/datum/component/manual_breathing/proc/check_removed_organ(mob/who_cares, obj/item/organ/O) + var/obj/item/organ/lungs/old_lungs = O + + if(istype(old_lungs, /obj/item/organ/lungs)) + L = null + STOP_PROCESSING(SSdcs, src) + +/datum/component/manual_breathing/proc/check_emote(mob/living/carbon/user, datum/emote/emote) + if(emote.type == next_breath_type) + if(next_breath_type == /datum/emote/inhale) + next_breath_type = /datum/emote/exhale + else + next_breath_type = /datum/emote/inhale + + warn_grace = FALSE + warn_dying = FALSE + last_breath = world.time + + var/mob/living/carbon/C = parent + C.losebreath = max(0, C.losebreath - 0.4) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7a8ea640c9..969a4ceee9 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -30,6 +30,7 @@ GLOBAL_PROTECT(admin_verbs_admin) // /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ /datum/verbs/menu/Admin/verb/playerpanel, + /client/proc/cmd_admin_rejuvenate, // VENUS CODE, MOSLEY CREDIT THE PROPER PEOPLE PLEASE /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ /client/proc/check_ai_laws, /*shows AI and borg laws*/ // /client/proc/ghost_pool_protection, /*opens a menu for toggling ghost roles*/ @@ -238,6 +239,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( /client/proc/toggle_view_range, /client/proc/cmd_admin_check_contents, /datum/admins/proc/access_news_network, + /client/proc/cmd_admin_rejuvenate, // VENUS CODE, MOSLEY CREDIT THE PROPER PEOPLE PLEASE /client/proc/admin_end_shift, /client/proc/admin_call_shuttle, /client/proc/admin_cancel_shuttle, diff --git a/code/modules/admin/smites/berforate.dm b/code/modules/admin/smites/berforate.dm new file mode 100644 index 0000000000..b8b4e2f8c7 --- /dev/null +++ b/code/modules/admin/smites/berforate.dm @@ -0,0 +1,46 @@ +/// Fires an absurd amount of bullets at the target +/datum/smite/berforate + name = ":B:erforate" + /// Determines how fucked the target is + var/hatred +/datum/smite/berforate/configure(client/user) + var/static/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE") + hatred = input(user, "How much do you hate this guy?") in how_fucked_is_this_dude +/datum/smite/berforate/effect(client/user, mob/living/target) + . = ..() + if (!iscarbon(target)) + to_chat(user, "This must be used on a carbon mob.", confidential = TRUE) + return + var/repetitions + var/shots_per_limb_per_rep = 2 + var/damage + switch (hatred) + if ("A little") + repetitions = 1 + damage = 5 + if ("A lot") + repetitions = 2 + damage = 8 + if ("So fucking much") + repetitions = 3 + damage = 10 + if ("FUCK THIS DUDE") + repetitions = 4 + damage = 10 + var/mob/living/carbon/dude = target + var/list/open_adj_turfs = get_adjacent_open_turfs(dude) + var/list/wound_bonuses = list(15, 70, 110, 250) + var/delay_per_shot = 1 + var/delay_counter = 1 + dude.Immobilize(5 SECONDS) + for (var/wound_bonus_rep in 1 to repetitions) + for (var/_limb in dude.bodyparts) + var/obj/item/bodypart/limb = _limb + var/shots_this_limb = 0 + for (var/_iter_turf in shuffle(open_adj_turfs)) + var/turf/iter_turf = _iter_turf + addtimer(CALLBACK(GLOBAL_PROC, .proc/firing_squad, dude, iter_turf, limb.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter) + delay_counter += delay_per_shot + shots_this_limb += 1 + if (shots_this_limb > shots_per_limb_per_rep) + break diff --git a/code/modules/admin/smites/bloodless.dm b/code/modules/admin/smites/bloodless.dm new file mode 100644 index 0000000000..68b67e7c13 --- /dev/null +++ b/code/modules/admin/smites/bloodless.dm @@ -0,0 +1,17 @@ +/// Slashes up the target +/datum/smite/bloodless + name = ":B:loodless" +/datum/smite/bloodless/effect(client/user, mob/living/target) + . = ..() + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + var/mob/living/carbon/carbon_target = target + for(var/_limb in carbon_target.bodyparts) + var/obj/item/bodypart/limb = _limb + var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate)) + limb.force_wound_upwards(type_wound, smited = TRUE) + type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate)) + limb.force_wound_upwards(type_wound, smited = TRUE) + type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe)) + limb.force_wound_upwards(type_wound, smited = TRUE) diff --git a/code/modules/admin/smites/boneless.dm b/code/modules/admin/smites/boneless.dm new file mode 100644 index 0000000000..6d35508f39 --- /dev/null +++ b/code/modules/admin/smites/boneless.dm @@ -0,0 +1,13 @@ +/// Gives the target critically bad wounds +/datum/smite/boneless + name = ":B:oneless" +/datum/smite/boneless/effect(client/user, mob/living/target) + . = ..() + if (!iscarbon(target)) + to_chat(user, "This must be used on a carbon mob.", confidential = TRUE) + return + var/mob/living/carbon/carbon_target = target + for(var/_limb in carbon_target.bodyparts) + var/obj/item/bodypart/limb = _limb + var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate)) + limb.force_wound_upwards(type_wound, smited = TRUE) diff --git a/code/modules/admin/smites/bonk.dm b/code/modules/admin/smites/bonk.dm new file mode 100644 index 0000000000..9921f21a7f --- /dev/null +++ b/code/modules/admin/smites/bonk.dm @@ -0,0 +1,9 @@ +/// Bonks the target +/datum/smite/bonk + name = "Bonk" + +/datum/smite/bonk/effect(client/user, mob/living/target) + . = ..() + playsound(target, 'modular_splurt/sound/misc/bonk.ogg', 100, 1) + target.AddElement(/datum/element/squish, 60 SECONDS) + to_chat(target, "Bonk.") diff --git a/code/modules/admin/smites/bookify.dm b/code/modules/admin/smites/bookify.dm new file mode 100644 index 0000000000..eba95af538 --- /dev/null +++ b/code/modules/admin/smites/bookify.dm @@ -0,0 +1,13 @@ +#define BOOKIFY_TIME (2 SECONDS) +/// Turns the target into a book +/datum/smite/bookify + name = "Bookify" + +/datum/smite/bookify/effect(client/user, mob/living/carbon/human/target as mob) + . = ..() + var/mutable_appearance/book_appearance = mutable_appearance('icons/obj/library.dmi', "book") + var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect") + target.transformation_animation(book_appearance, time = BOOKIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE) + addtimer(CALLBACK(GLOBAL_PROC, .proc/bookify, target), BOOKIFY_TIME) + playsound(target, 'modular_splurt/sound/misc/bookify.ogg', 60, 1) +#undef BOOKIFY_TIME diff --git a/code/modules/admin/smites/brain_damage.dm b/code/modules/admin/smites/brain_damage.dm new file mode 100644 index 0000000000..ce7d6ae478 --- /dev/null +++ b/code/modules/admin/smites/brain_damage.dm @@ -0,0 +1,6 @@ +/// Inflicts crippling brain damage on the target +/datum/smite/brain_damage + name = "Brain damage" +/datum/smite/brain_damage/effect(client/user, mob/living/target) + . = ..() + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, BRAIN_DAMAGE_DEATH - 1, BRAIN_DAMAGE_DEATH - 1) diff --git a/code/modules/admin/smites/bread.dm b/code/modules/admin/smites/bread.dm new file mode 100644 index 0000000000..a92c5c8e27 --- /dev/null +++ b/code/modules/admin/smites/bread.dm @@ -0,0 +1,14 @@ +#define BREADIFY_TIME (5 SECONDS) + +/// Turns the target into bread +/datum/smite/bread + name = "Bread" + +/datum/smite/bread/effect(client/user, mob/living/target) + . = ..() + var/mutable_appearance/bread_appearance = mutable_appearance('icons/obj/food/burgerbread.dmi', "bread") + var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect") + target.transformation_animation(bread_appearance,time = BREADIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE) + addtimer(CALLBACK(GLOBAL_PROC, .proc/breadify, target), BREADIFY_TIME) + +#undef BREADIFY_TIME diff --git a/code/modules/admin/smites/bsa.dm b/code/modules/admin/smites/bsa.dm new file mode 100644 index 0000000000..fa89af32e7 --- /dev/null +++ b/code/modules/admin/smites/bsa.dm @@ -0,0 +1,32 @@ +#define BSA_CHANCE_TO_BREAK_TILE_TO_PLATING 80 +#define BSA_MAX_DAMAGE 99 +#define BSA_PARALYZE_TIME (40 SECONDS) +#define BSA_STUTTER_TIME (40 SECONDS) + +/// Fires the BSA at the target +/datum/smite/bsa + name = "Bluespace Artillery Device" + +/datum/smite/bsa/effect(client/user, mob/living/target) + . = ..() + + explosion(target.loc, 0, 0, 0, 0) + + var/turf/open/floor/target_turf = get_turf(target) + if (istype(target_turf)) + if (prob(BSA_CHANCE_TO_BREAK_TILE_TO_PLATING)) + target_turf.break_tile_to_plating() + else + target_turf.break_tile() + + if (target.health <= 1) + target.gib(1, 1) + else + target.adjustBruteLoss(min(BSA_MAX_DAMAGE, target.health - 1)) + target.DefaultCombatKnockdown(BSA_PARALYZE_TIME) + target.stuttering = 20 + +#undef BSA_CHANCE_TO_BREAK_TILE_TO_PLATING +#undef BSA_MAX_DAMAGE +#undef BSA_PARALYZE_TIME +#undef BSA_STUTTER_TIME diff --git a/code/modules/admin/smites/cluwne.dm b/code/modules/admin/smites/cluwne.dm new file mode 100644 index 0000000000..a097a0f16a --- /dev/null +++ b/code/modules/admin/smites/cluwne.dm @@ -0,0 +1,10 @@ +/// Cluwneifies the target +/datum/smite/cluwne + name = "Cluwne" + +/datum/smite/cluwne/effect(client/user, mob/living/carbon/human/target as mob) + . = ..() + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.") + return + target.cluwneify() diff --git a/code/modules/admin/smites/custompie.dm b/code/modules/admin/smites/custompie.dm new file mode 100644 index 0000000000..890907ecfc --- /dev/null +++ b/code/modules/admin/smites/custompie.dm @@ -0,0 +1,18 @@ +/// Throws a custom pie at the target +/datum/smite/custompie + name = "Custom Pie" + +/datum/smite/custompie/effect(client/user, mob/living/target) + . = ..() + var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new() + if(!A.reagents) + var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null + if(amount) + A.create_reagents(amount) + if(A.reagents) + var/chosen_id = choose_reagent_id(usr) + if(chosen_id) + var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null + if(amount) + A.reagents.add_reagent(chosen_id, amount) + A.splat(target) diff --git a/code/modules/admin/smites/dock_pay.dm b/code/modules/admin/smites/dock_pay.dm new file mode 100644 index 0000000000..0ce91bbd4b --- /dev/null +++ b/code/modules/admin/smites/dock_pay.dm @@ -0,0 +1,31 @@ +/// Docks the target's pay +/datum/smite/dock_pay + name = "Dock Pay" + +/datum/smite/dock_pay/effect(client/user, mob/living/target) + . = ..() + if (!iscarbon(target)) + to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE) + return + var/mob/living/carbon/dude = target + var/obj/item/card/id/card = dude.get_idcard(TRUE) + if (!card) + to_chat(user, span_warning("[dude] does not have an ID card on!"), confidential = TRUE) + return + if (!card.registered_account) + to_chat(user, span_warning("[dude] does not have an ID card with an account!"), confidential = TRUE) + return + if (card.registered_account.account_balance == 0) + to_chat(user, span_warning("ID Card lacks any funds. No pay to dock.")) + return + var/new_cost = input("How much pay are we docking? Current balance: [card.registered_account.account_balance] credits.", "BUDGET CUTS") as num|null + if (!new_cost) + return + if (!(card.registered_account.has_money(new_cost))) + to_chat(user, span_warning("ID Card lacked funds. Emptying account.")) + card.registered_account.bank_card_talk("[new_cost] credits deducted from your account based on performance review.") + card.registered_account.account_balance = 0 + else + card.registered_account.account_balance = card.registered_account.account_balance - new_cost + card.registered_account.bank_card_talk("[new_cost] credits deducted from your account based on performance review.") + SEND_SOUND(target, 'sound/machines/buzz-sigh.ogg') diff --git a/code/modules/admin/smites/fake_bwoink.dm b/code/modules/admin/smites/fake_bwoink.dm new file mode 100644 index 0000000000..a4179ff5ce --- /dev/null +++ b/code/modules/admin/smites/fake_bwoink.dm @@ -0,0 +1,7 @@ +/// Sends the target a fake adminhelp sound +/datum/smite/fake_bwoink + name = "Fake bwoink" + +/datum/smite/fake_bwoink/effect(client/user, mob/living/target) + . = ..() + SEND_SOUND(target, 'sound/effects/adminhelp.ogg') diff --git a/code/modules/admin/smites/finalmessage.dm b/code/modules/admin/smites/finalmessage.dm new file mode 100644 index 0000000000..b5fdbfeb0b --- /dev/null +++ b/code/modules/admin/smites/finalmessage.dm @@ -0,0 +1,12 @@ +/// Their Final Message +/datum/smite/finalmessage + name = "Final Message" + +/datum/smite/finalmessage/effect(client/user, mob/living/target) + . = ..() + var/mob/living/C = target + if(C.stat == DEAD) + to_chat(usr, "[C] is dead!") + return + else + C.goodbye() diff --git a/code/modules/admin/smites/fireball.dm b/code/modules/admin/smites/fireball.dm new file mode 100644 index 0000000000..98dad65d82 --- /dev/null +++ b/code/modules/admin/smites/fireball.dm @@ -0,0 +1,7 @@ +/// Throws a fireball down at the target +/datum/smite/fireball + name = "Fireball" + +/datum/smite/fireball/effect(client/user, mob/living/target) + . = ..() + new /obj/effect/temp_visual/target(get_turf(target)) diff --git a/code/modules/admin/smites/fry.dm b/code/modules/admin/smites/fry.dm new file mode 100644 index 0000000000..66a4100f10 --- /dev/null +++ b/code/modules/admin/smites/fry.dm @@ -0,0 +1,7 @@ +/// Fry the target +/datum/smite/fry + name = "Fry" + +/datum/smite/fry/effect(client/user, mob/living/target) + . = ..() + target.fry() diff --git a/code/modules/admin/smites/gib.dm b/code/modules/admin/smites/gib.dm new file mode 100644 index 0000000000..37f1e1c8b4 --- /dev/null +++ b/code/modules/admin/smites/gib.dm @@ -0,0 +1,7 @@ +/// Gibs the target +/datum/smite/gib + name = "Gib" + +/datum/smite/gib/effect(client/user, mob/living/target) + . = ..() + target.gib(FALSE) diff --git a/code/modules/admin/smites/immerse.dm b/code/modules/admin/smites/immerse.dm new file mode 100644 index 0000000000..9cdd8aca95 --- /dev/null +++ b/code/modules/admin/smites/immerse.dm @@ -0,0 +1,9 @@ +/// "Fully immerses" the player, making them manually breathe and blink +/datum/smite/immerse + name = "Fully Immerse" + +/datum/smite/immerse/effect(client/user, mob/living/target) + . = ..() + immerse_player(target) + SEND_SOUND(target, sound('sound/misc/roleplay.ogg')) + to_chat(target, span_boldnotice("Please roleplay appropriately, okay?")) diff --git a/code/modules/admin/smites/knot_shoes.dm b/code/modules/admin/smites/knot_shoes.dm new file mode 100644 index 0000000000..057dbd7436 --- /dev/null +++ b/code/modules/admin/smites/knot_shoes.dm @@ -0,0 +1,15 @@ +/// Ties the target's shoes +/datum/smite/knot_shoes + name = "Knot Shoes" + +/datum/smite/knot_shoes/effect(client/user, mob/living/target) + . = ..() + if (!iscarbon(target)) + to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE) + return + var/mob/living/carbon/dude = target + var/obj/item/clothing/shoes/sick_kicks = dude.shoes + if (!sick_kicks?.can_be_tied) + to_chat(user, span_warning("[dude] does not have knottable shoes!"), confidential = TRUE) + return + sick_kicks.adjust_laces(SHOES_KNOTTED) diff --git a/code/modules/admin/smites/lightning.dm b/code/modules/admin/smites/lightning.dm new file mode 100644 index 0000000000..93527fad8b --- /dev/null +++ b/code/modules/admin/smites/lightning.dm @@ -0,0 +1,20 @@ +/// Strikes the target with a lightning bolt +/datum/smite/lightning + name = "Lightning bolt" + +/datum/smite/lightning/effect(client/user, mob/living/target) + . = ..() + lightningbolt(target) + to_chat(target, "The gods have punished you for your sins!") + +///this is the actual bolt effect and damage, made into its own proc because it is used elsewhere +/proc/lightningbolt(mob/living/user) + playsound(get_turf(user), 'modular_splurt/sound/misc/NOW.ogg', 75, FALSE) + sleep(4 SECONDS) + var/turf/T = get_step(get_step(user, NORTH), NORTH) + T.Beam(user, icon_state="lightning[rand(1,12)]", time = 5) + user.adjustFireLoss(75) + if(ishuman(user)) + var/mob/living/carbon/human/human_target = user + human_target.electrocution_animation(40) + diff --git a/code/modules/admin/smites/nugget.dm b/code/modules/admin/smites/nugget.dm new file mode 100644 index 0000000000..86fd9af9cf --- /dev/null +++ b/code/modules/admin/smites/nugget.dm @@ -0,0 +1,21 @@ +/// Rips off all the limbs of the target +/datum/smite/nugget + name = "Nugget" + +/datum/smite/nugget/effect(client/user, mob/living/target) + . = ..() + + if (!iscarbon(target)) + to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE) + return + + var/mob/living/carbon/carbon_target = target + var/timer = 2 SECONDS + for (var/_limb in carbon_target.bodyparts) + var/obj/item/bodypart/limb = _limb + if (limb.body_part == HEAD || limb.body_part == CHEST) + continue + addtimer(CALLBACK(limb, TYPE_PROC_REF(/obj/item/bodypart/, dismember)), timer) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), carbon_target, 'modular_splurt/sound/effects/cartoon_pop.ogg', 70), timer) + addtimer(CALLBACK(carbon_target, TYPE_PROC_REF(/mob/living/, spin), 4, 1), timer - 0.4 SECONDS) + timer += 2 SECONDS diff --git a/code/modules/admin/smites/phobia_ocky_icky.dm b/code/modules/admin/smites/phobia_ocky_icky.dm new file mode 100644 index 0000000000..8295b062cf --- /dev/null +++ b/code/modules/admin/smites/phobia_ocky_icky.dm @@ -0,0 +1,8 @@ +/// "Immerses" the player, making them unable to use some OOC terms IC +/datum/smite/ocky_icky + name = "Ocky icky phobia" + +/datum/smite/ocky_icky/effect(client/user, mob/living/target) + . = ..() + var/mob/living/carbon/ocker = target + ocker.gain_trauma(/datum/brain_trauma/mild/phobia/ocky_icky, TRAUMA_RESILIENCE_LOBOTOMY) diff --git a/code/modules/admin/smites/pickle.dm b/code/modules/admin/smites/pickle.dm new file mode 100644 index 0000000000..18e370e535 --- /dev/null +++ b/code/modules/admin/smites/pickle.dm @@ -0,0 +1,7 @@ +/// Turns the target into a pickle +/datum/smite/pickle + name = "Pickle" + +/datum/smite/pickle/effect(client/user, mob/living/target) + . = ..() + target.turn_into_pickle() diff --git a/code/modules/admin/smites/pie.dm b/code/modules/admin/smites/pie.dm new file mode 100644 index 0000000000..d21a891dde --- /dev/null +++ b/code/modules/admin/smites/pie.dm @@ -0,0 +1,8 @@ +/// Throws a pie at the target +/datum/smite/pie + name = "Pie" + +/datum/smite/pie/effect(client/user, mob/living/target) + . = ..() + var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target)) + creamy.splat(target) diff --git a/code/modules/admin/smites/puzzle.dm b/code/modules/admin/smites/puzzle.dm new file mode 100644 index 0000000000..ffaee14412 --- /dev/null +++ b/code/modules/admin/smites/puzzle.dm @@ -0,0 +1,8 @@ +/// Turns the user into a sliding puzzle +/datum/smite/puzzle + name = "Puzzle" + +/datum/smite/puzzle/effect(client/user, mob/living/target) + . = ..() + if(!puzzle_imprison(target)) + to_chat(user, "Imprisonment failed!", confidential = TRUE) diff --git a/code/modules/admin/smites/rod.dm b/code/modules/admin/smites/rod.dm new file mode 100644 index 0000000000..8598258e36 --- /dev/null +++ b/code/modules/admin/smites/rod.dm @@ -0,0 +1,17 @@ +/// Throw an immovable rod at the target +/datum/smite/rod + name = "Immovable Rod" + var/force_looping = FALSE + +/datum/smite/rod/configure(client/user) + var/loop_input = tgui_alert(usr,"Would you like this rod to force-loop across space z-levels?", "Loopy McLoopface", list("Yes", "No")) + + force_looping = (loop_input == "Yes") + +/datum/smite/rod/effect(client/user, mob/living/target) + . = ..() + var/turf/target_turf = get_turf(target) + var/startside = pick(GLOB.cardinals) + var/turf/start_turf = spaceDebrisStartLoc(startside, target_turf.z) + var/turf/end_turf = spaceDebrisFinishLoc(startside, target_turf.z) + new /obj/effect/immovablerod(start_turf, end_turf, target, force_looping) diff --git a/code/modules/admin/smites/scarify.dm b/code/modules/admin/smites/scarify.dm new file mode 100644 index 0000000000..fcbe2062e8 --- /dev/null +++ b/code/modules/admin/smites/scarify.dm @@ -0,0 +1,12 @@ +/// Gives the target fake scars +/datum/smite/scarify + name = "Scarify" + +/datum/smite/scarify/effect(client/user, mob/living/target) + . = ..() + if(!iscarbon(target)) + to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE) + return + var/mob/living/carbon/dude = target + dude.generate_fake_scars(rand(1, 4)) + to_chat(dude, span_warning("You feel your body grow jaded and torn...")) diff --git a/code/modules/admin/smites/shoes.dm b/code/modules/admin/smites/shoes.dm new file mode 100644 index 0000000000..ff74e50943 --- /dev/null +++ b/code/modules/admin/smites/shoes.dm @@ -0,0 +1,15 @@ +/// Ties the target's shoes +/datum/smite/shoes + name = "Knot Shoes" + +/datum/smite/shoes/effect(client/user, mob/living/target) + . = ..() + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.") + return + var/mob/living/carbon/C = target + var/obj/item/clothing/shoes/sick_kicks = C.shoes + if(!sick_kicks?.can_be_tied) + to_chat(usr,"[C] does not have knottable shoes!") + return + sick_kicks.adjust_laces(SHOES_KNOTTED) diff --git a/code/modules/admin/smites/smite.dm b/code/modules/admin/smites/smite.dm new file mode 100644 index 0000000000..b767f47f8f --- /dev/null +++ b/code/modules/admin/smites/smite.dm @@ -0,0 +1,17 @@ +/// A smite, used by admins to punish players, or for their own amusement +/datum/smite + /// The name of the smite, shown in the menu + var/name + + /// Should this smite write to logs? + var/should_log = TRUE + +/// Called once after either choosing the option to smite a player, or when selected in smite build mode. +/// Use this to prompt the user configuration options. +/// Return FALSE if the smite should not be used. +/datum/smite/proc/configure(client/user) + +/// The effect of the smite, make sure to call this in your own smites +/datum/smite/proc/effect(client/user, mob/living/target) + if (should_log) + user.punish_log(target, name) diff --git a/code/modules/admin/smites/supply_pod.dm b/code/modules/admin/smites/supply_pod.dm new file mode 100644 index 0000000000..187507e9bb --- /dev/null +++ b/code/modules/admin/smites/supply_pod.dm @@ -0,0 +1,21 @@ +#define SUPPLY_POD_FIRE_RANGE + +/// Throws a supply pod at the target, with no item inside +/datum/smite/supply_pod + name = "Supply Pod" + + // punish_log() is handled by the centcom_podlauncher datum + should_log = FALSE + +/datum/smite/supply_pod/effect(client/user, mob/living/target) + . = ..() + var/datum/centcom_podlauncher/plaunch = new(user) + plaunch.specificTarget = target + plaunch.launchChoice = 0 + plaunch.damageChoice = 1 + plaunch.explosionChoice = 1 + plaunch.temp_pod.damage = 40 // bring the mother fuckin ruckus + plaunch.temp_pod.explosionSize = list(0, 0, 0, SUPPLY_POD_FIRE_RANGE) + plaunch.temp_pod.effectStun = TRUE + +#undef SUPPLY_POD_FIRE_RANGE diff --git a/code/modules/admin/smites/supply_pod_quick.dm b/code/modules/admin/smites/supply_pod_quick.dm new file mode 100644 index 0000000000..ccb04d47ce --- /dev/null +++ b/code/modules/admin/smites/supply_pod_quick.dm @@ -0,0 +1,49 @@ +#define SUPPLY_POD_QUICK_DAMAGE 40 +#define SUPPLY_POD_QUICK_FIRE_RANGE 2 + +/// Quickly throws a supply pod at the target, optionally with an item +/datum/smite/supply_pod_quick + name = "Supply Pod (Quick)" + + /// What is sent down with the pod + var/target_path + +/datum/smite/supply_pod_quick/configure(client/user) + var/attempted_target_path = input( + user, + "Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):", + "Typepath", + "/obj/item/reagent_containers/food/snacks/grown/harebell", + ) as null|text + if (isnull(attempted_target_path)) //The user pressed "Cancel" + return FALSE + + if (attempted_target_path == "empty") + target_path = null + return + + // if you didn't type empty, we want to load the pod with a delivery + var/delivery = text2path(attempted_target_path) + if(!ispath(delivery)) + delivery = pick_closest_path(attempted_target_path) + if(!delivery) + alert(user, "ERROR: Incorrect / improper path given.") + return FALSE + target_path = delivery + +/datum/smite/supply_pod_quick/effect(client/user, mob/living/target) + . = ..() + + var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas + var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area))) + pod.damage = SUPPLY_POD_QUICK_DAMAGE + pod.explosionSize = list(0, 0, 0, SUPPLY_POD_QUICK_FIRE_RANGE) + pod.effectStun = TRUE + + if (!isnull(target_path)) + new target_path(pod) + + new /obj/effect/pod_landingzone(get_turf(target), pod) + +#undef SUPPLY_POD_QUICK_DAMAGE +#undef SUPPLY_POD_QUICK_FIRE_RANGE diff --git a/code/modules/admin/smites/tabletide.dm b/code/modules/admin/smites/tabletide.dm new file mode 100644 index 0000000000..a2c3425840 --- /dev/null +++ b/code/modules/admin/smites/tabletide.dm @@ -0,0 +1,16 @@ +/// Tableslam the target +/datum/smite/tabletide + name = "Table Tideslam" + +/datum/smite/tabletide/effect(client/user, mob/living/target) + . = ..() + priority_announce(html_decode("[target] has brought the wrath of the gods upon themselves and is now being tableslammed across the station. Please stand by."), null, 'sound/misc/announce.ogg', "CentCom") + var/list/areas = list() + for(var/area/A in world) + if(A.z == SSmapping.station_start) + areas += A + SEND_SOUND(target, sound('modular_splurt/sound/misc/slamofthenorthstar.ogg',volume=60)) + for(var/area/A in areas) + for(var/obj/structure/table/T in A) + T.tablepush(target, target) + sleep(1) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index ffe284aa71..eb42828744 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1997,6 +1997,22 @@ to_chat(H, "Your prayers have been answered!! You received the best cookie!") SEND_SOUND(H, sound('sound/effects/pray_chaplain.ogg')) + else if (href_list["adminpopup"]) + if (!check_rights(R_ADMIN)) + return + + var/message = input(owner, "As well as a popup, they'll also be sent a message to reply to. What do you want that to be?", "Message") as text|null + if (!message) + to_chat(owner, span_notice("Popup cancelled.")) + return + + var/client/target = locate(href_list["adminpopup"]) + if (!istype(target)) + to_chat(owner, span_notice("The mob doesn't exist anymore!")) + return + + give_admin_popup(target, owner, message) + else if(href_list["adminsmite"]) if(!check_rights(R_ADMIN|R_FUN)) return diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index a3f6548112..284cdcf5b3 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -249,6 +249,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if(state == AHELP_ACTIVE) . += ClosureLinks(ref_src) + if (CONFIG_GET(flag/popup_admin_pm)) + . += " (POPUP)" + //private /datum/admin_help/proc/ClosureLinks(ref_src) if(!ref_src) @@ -332,6 +335,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if(initiator && initiator.current_ticket == src) initiator.current_ticket = null + SEND_SIGNAL(src, COMSIG_ADMIN_HELP_MADE_INACTIVE) + //Mark open ticket as closed/meme /datum/admin_help/proc/Close(key_name = key_name_admin(usr), silent = FALSE) if(state != AHELP_ACTIVE) diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 950a06b2b9..4969962e4c 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -172,6 +172,7 @@ if(holder && recipient.holder && !current_ticket) //Both are admins, and this is not a reply to our own ticket. badmin = TRUE if(recipient.holder && !badmin) + SEND_SIGNAL(current_ticket, COMSIG_ADMIN_HELP_REPLIED) if(holder) to_chat(recipient, "Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]", confidential = TRUE) to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]", confidential = TRUE) @@ -215,9 +216,6 @@ //always play non-admin recipients the adminhelp sound SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg')) - //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn - if(CONFIG_GET(flag/popup_admin_pm)) - INVOKE_ASYNC(src, PROC_REF(popup_admin_pm), recipient, msg) else //neither are admins to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.", confidential = TRUE) @@ -235,17 +233,6 @@ if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient to_chat(X, "PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]" , confidential = TRUE) -/client/proc/popup_admin_pm(client/recipient, msg) - var/sender = src - var/sendername = key - var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply - if(recipient && reply) - if(sender) - recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them - else - adminhelp(reply) //sender has left, adminhelp instead - - /proc/IrcPm(target,msg,sender) return TgsPm(target,msg,sender) //compatability moment. diff --git a/code/modules/admin/verbs/bluespacearty.dm b/code/modules/admin/verbs/bluespacearty.dm deleted file mode 100644 index 23fff5ece9..0000000000 --- a/code/modules/admin/verbs/bluespacearty.dm +++ /dev/null @@ -1,26 +0,0 @@ -/client/proc/bluespace_artillery(mob/M in GLOB.mob_list) - if(!holder || !check_rights(R_FUN)) - return - - var/mob/living/target = M - - if(!isliving(target)) - to_chat(usr, "This can only be used on instances of type /mob/living", confidential = TRUE) - return - - explosion(target.loc, 0, 0, 0, 0) - - var/turf/open/floor/T = get_turf(target) - if(istype(T)) - if(prob(80)) - T.break_tile_to_plating() - else - T.break_tile() - - if(target.health <= 1) - target.gib(1, 1) - else - target.adjustBruteLoss(min(99,(target.health - 1))) - target.DefaultCombatKnockdown(400) - target.stuttering = 20 - diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index cd8c849c45..c7dcac83df 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -539,6 +539,26 @@ return dresscode +/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list) + set category = "Debug" + set name = "Rejuvenate" + + if(!check_rights(R_ADMIN)) + return + + if(!mob) + return + if(!istype(M)) + alert("Cannot revive a ghost") + return + M.revive(full_heal = 1, admin_revive = 1) + + log_admin("[key_name(usr)] healed / revived [key_name(M)]") + var/msg = "Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!" + message_admins(msg) + admin_ticket_log(M, msg) + SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvinate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /client/proc/startSinglo() set category = "Debug" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 519154c597..3f70ab295f 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -474,26 +474,6 @@ Traitors and the like can also be revived with the previous role mostly intact. SSblackbox.record_feedback("tally", "admin_verb", 1, "Add Custom AI Law") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list) - set category = "Special Verbs" - set name = "Rejuvenate" - - if(!check_rights(R_ADMIN)) - return - - if(!mob) - return - if(!istype(M)) - alert("Cannot revive a ghost") - return - M.revive(full_heal = 1, admin_revive = 1) - - log_admin("[key_name(usr)] healed / revived [key_name(M)]") - var/msg = "Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!" - message_admins(msg) - admin_ticket_log(M, msg) - SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvinate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /client/proc/cmd_admin_create_centcom_report() set category = "Admin.Events" set name = "Create Command Report" @@ -1283,266 +1263,34 @@ Traitors and the like can also be revived with the previous role mostly intact. busy_toggling_fov = FALSE -/client/proc/smite(mob/living/carbon/human/target as mob) +/client/proc/smite(mob/living/target as mob) set name = "Smite" set category = "Admin.Fun" if(!check_rights(R_ADMIN) || !check_rights(R_FUN)) return - var/list/punishment_list = list( - ADMIN_PUNISHMENT_PIE, - ADMIN_PUNISHMENT_CUSTOM_PIE, - ADMIN_PUNISHMENT_FIREBALL, - ADMIN_PUNISHMENT_LIGHTNING, - ADMIN_PUNISHMENT_BRAINDAMAGE, - ADMIN_PUNISHMENT_BSA, - ADMIN_PUNISHMENT_GIB, - ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, - ADMIN_PUNISHMENT_SUPPLYPOD, - ADMIN_PUNISHMENT_MAZING, - ADMIN_PUNISHMENT_ROD, - ADMIN_PUNISHMENT_SHOES, - ADMIN_PUNISHMENT_PICKLE, - ADMIN_PUNISHMENT_FRY, - ADMIN_PUNISHMENT_CRACK, - ADMIN_PUNISHMENT_BLEED, - ADMIN_PUNISHMENT_SCARIFY, - ADMIN_PUNISHMENT_CLUWNE, - ADMIN_PUNISHMENT_GOODBYE, - ADMIN_PUNISHMENT_TABLETIDESTATIONWIDE, - ADMIN_PUNISHMENT_FAKEBWOINK, - ADMIN_PUNISHMENT_NUGGET, - ADMIN_PUNISHMENT_BREADIFY, - ADMIN_PUNISHMENT_BOOKIFY, - ADMIN_PUNISHMENT_BONK) - var/punishment = tgui_input_list(usr, "Choose a punishment", "Divine Smiting", punishment_list) + var/punishment = tgui_input_list(usr, "Choose a punishment", "DIVINE SMITING", GLOB.smites) if(QDELETED(target) || !punishment) return - switch(punishment) - if(ADMIN_PUNISHMENT_LIGHTNING) - if(prob(75)) - playsound(target, 'modular_splurt/sound/misc/NOW.ogg', 75, FALSE) - sleep(4 SECONDS) - var/turf/T = get_step(get_step(target, NORTH), NORTH) - T.Beam(target, icon_state="lightning[rand(1,12)]", time = 5) - target.adjustFireLoss(75) - target.electrocution_animation(40) - to_chat(target, "The gods have punished you for your sins!") - if(ADMIN_PUNISHMENT_BRAINDAMAGE) - target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199) - if(ADMIN_PUNISHMENT_GIB) - target.gib(FALSE) - if(ADMIN_PUNISHMENT_BSA) - bluespace_artillery(target) - if(ADMIN_PUNISHMENT_FIREBALL) - new /obj/effect/temp_visual/target(get_turf(target)) - if(ADMIN_PUNISHMENT_ROD) - var/turf/T = get_turf(target) - var/startside = pick(GLOB.cardinals) - var/turf/startT = spaceDebrisStartLoc(startside, T.z) - var/turf/endT = spaceDebrisFinishLoc(startside, T.z) - new /obj/effect/immovablerod(startT, endT,target) - if(ADMIN_PUNISHMENT_SUPPLYPOD_QUICK) - var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text - var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas - var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets not runtime - pod.damage = 40 - pod.explosionSize = list(0,0,0,2) - pod.effectStun = TRUE - if (isnull(target_path)) //The user pressed "Cancel" - return - if (target_path != "empty")//if you didn't type empty, we want to load the pod with a delivery - var/delivery = text2path(target_path) - if(!ispath(delivery)) - delivery = pick_closest_path(target_path) - if(!delivery) - alert("ERROR: Incorrect / improper path given.") - new delivery(pod) - new /obj/effect/pod_landingzone(get_turf(target), pod) - if(ADMIN_PUNISHMENT_SUPPLYPOD) - var/datum/centcom_podlauncher/plaunch = new(usr) - if(!holder) - return - plaunch.specificTarget = target - plaunch.launchChoice = 0 - plaunch.damageChoice = 1 - plaunch.explosionChoice = 1 - plaunch.temp_pod.damage = 40//bring the mother fuckin ruckus - plaunch.temp_pod.explosionSize = list(0,0,0,2) - plaunch.temp_pod.effectStun = TRUE - return //We return here because punish_log() is handled by the centcom_podlauncher datum + var/smite_path = GLOB.smites[punishment] + var/datum/smite/smite = new smite_path + var/configuration_success = smite.configure(usr) + if (configuration_success == FALSE) + return + smite.effect(src, target) - if(ADMIN_PUNISHMENT_MAZING) - if(!puzzle_imprison(target)) - to_chat(usr,"Imprisonment failed!") - return - if(ADMIN_PUNISHMENT_PIE) - var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target)) - creamy.splat(target) - if(ADMIN_PUNISHMENT_CUSTOM_PIE) - var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new() - if(!A.reagents) - var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null - if(amount) - A.create_reagents(amount) - if(A.reagents) - var/chosen_id = choose_reagent_id(usr) - if(chosen_id) - var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null - if(amount) - A.reagents.add_reagent(chosen_id, amount) - A.splat(target) - if(ADMIN_PUNISHMENT_CRACK) - if(!iscarbon(target)) - to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) - return - var/mob/living/carbon/C = target - for(var/i in C.bodyparts) - var/obj/item/bodypart/squish_part = i - var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate)) - squish_part.force_wound_upwards(type_wound, smited=TRUE) - if(ADMIN_PUNISHMENT_BLEED) - if(!iscarbon(target)) - to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) - return - var/mob/living/carbon/C = target - for(var/i in C.bodyparts) - var/obj/item/bodypart/slice_part = i - var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate)) - slice_part.force_wound_upwards(type_wound, smited=TRUE) - type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate)) - slice_part.force_wound_upwards(type_wound, smited=TRUE) - type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe)) - slice_part.force_wound_upwards(type_wound, smited=TRUE) - if(ADMIN_PUNISHMENT_SCARIFY) - if(!iscarbon(target)) - to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) - return - var/mob/living/carbon/dude = target - dude.generate_fake_scars(rand(1, 4)) - to_chat(dude, "You feel your body grow jaded and torn...") - if(ADMIN_PUNISHMENT_PERFORATE) - if(!iscarbon(target)) - to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) - return - var/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE") - var/hatred = input("How much do you hate this guy?") in how_fucked_is_this_dude - var/repetitions - var/shots_per_limb_per_rep = 2 - var/damage - switch(hatred) - if("A little") - repetitions = 1 - damage = 5 - if("A lot") - repetitions = 2 - - damage = 8 - if("So fucking much") - repetitions = 3 - damage = 10 - if("FUCK THIS DUDE") - repetitions = 4 - damage = 10 - - var/mob/living/carbon/dude = target - var/list/open_adj_turfs = get_adjacent_open_turfs(dude) - var/list/wound_bonuses = list(15, 70, 110, 250) - - var/delay_per_shot = 1 - var/delay_counter = 1 - - dude.Immobilize(5 SECONDS) - for(var/wound_bonus_rep in 1 to repetitions) - for(var/i in dude.bodyparts) - var/obj/item/bodypart/slice_part = i - var/shots_this_limb = 0 - for(var/t in shuffle(open_adj_turfs)) - var/turf/iter_turf = t - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(firing_squad), dude, iter_turf, slice_part.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter) - delay_counter += delay_per_shot - shots_this_limb++ - if(shots_this_limb > shots_per_limb_per_rep) - break - if(ADMIN_PUNISHMENT_PICKLE) - target.turn_into_pickle() - if(ADMIN_PUNISHMENT_FRY) - target.fry() - - if(ADMIN_PUNISHMENT_SHOES) - if(!iscarbon(target)) - to_chat(usr,"This must be used on a carbon mob.") - return - var/mob/living/carbon/C = target - var/obj/item/clothing/shoes/sick_kicks = C.shoes - if(!sick_kicks?.can_be_tied) - to_chat(usr,"[C] does not have knottable shoes!") - return - sick_kicks.adjust_laces(SHOES_KNOTTED) - if(ADMIN_PUNISHMENT_CLUWNE) - if(!iscarbon(target)) - to_chat(usr,"This must be used on a carbon mob.") - return - target.cluwneify() - if(ADMIN_PUNISHMENT_GOODBYE) //sandstorm punish :) it starts here - var/mob/living/C = target - if(C.stat == DEAD) - to_chat(usr, "[C] is dead!") - return - else - C.goodbye() //sandstorm punish and ends here. - if(ADMIN_PUNISHMENT_TABLETIDESTATIONWIDE) //SPLURT punishments start here - priority_announce(html_decode("[target] has brought the wrath of the gods upon themselves and is now being tableslammed across the station. Please stand by."), null, 'sound/misc/announce.ogg', "CentCom") - var/list/areas = list() - for(var/area/A in world) - if(A.z == SSmapping.station_start) - areas += A - SEND_SOUND(target, sound('modular_splurt/sound/misc/slamofthenorthstar.ogg',volume=60)) - for(var/area/A in areas) - for(var/obj/structure/table/T in A) - T.tablepush(target, target) - sleep(1) - if(ADMIN_PUNISHMENT_FAKEBWOINK) - SEND_SOUND(target, 'sound/effects/adminhelp.ogg') - if(ADMIN_PUNISHMENT_NUGGET) - if (!iscarbon(target)) - return - var/mob/living/carbon/carbon_target = target - var/timer = 2 SECONDS - for (var/_limb in carbon_target.bodyparts) - var/obj/item/bodypart/limb = _limb - if (limb.body_part == HEAD || limb.body_part == CHEST) - continue - addtimer(CALLBACK(limb, TYPE_PROC_REF(/obj/item/bodypart, dismember)), timer) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), carbon_target, 'modular_splurt/sound/effects/cartoon_pop.ogg', 70), timer) - addtimer(CALLBACK(carbon_target, TYPE_PROC_REF(/mob/living, spin), 4, 1), timer - 0.4 SECONDS) - timer += 2 SECONDS - if(ADMIN_PUNISHMENT_BREADIFY) - #define BREADIFY_TIME (5 SECONDS) - var/mutable_appearance/bread_appearance = mutable_appearance('icons/obj/food/burgerbread.dmi', "bread") - var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect") - target.transformation_animation(bread_appearance, time = BREADIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE) - addtimer(CALLBACK(src, PROC_REF(breadify), target), BREADIFY_TIME) - #undef BREADIFY_TIME - if(ADMIN_PUNISHMENT_BOOKIFY) - #define BOOKIFY_TIME (2 SECONDS) - var/mutable_appearance/book_appearance = mutable_appearance('icons/obj/library.dmi', "book") - var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect") - target.transformation_animation(book_appearance, time = BOOKIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE) - addtimer(CALLBACK(src, PROC_REF(bookify), target), BOOKIFY_TIME) - playsound(target, 'modular_splurt/sound/misc/bookify.ogg', 60, 1) - #undef BOOKIFY_TIME - if(ADMIN_PUNISHMENT_BONK) - playsound(target, 'modular_splurt/sound/misc/bonk.ogg', 100, 1) - target.AddElement(/datum/element/squish, 60 SECONDS) - to_chat(target, "Bonk.") - - punish_log(target, punishment) +/proc/breadify(atom/movable/target) + var/obj/item/reagent_containers/food/snacks/store/bread/plain/funnyBread = new(get_turf(target)) + target.forceMove(funnyBread) +/proc/bookify(atom/movable/target) + var/obj/item/reagent_containers/food/snacks/store/book/funnyBook = new(get_turf(target)) + target.forceMove(funnyBook) + funnyBook.name = "Book of " + target.name /** * firing_squad is a proc for the :B:erforate smite to shoot each individual bullet at them, so that we can add actual delays without sleep() nonsense * @@ -1569,10 +1317,10 @@ Traitors and the like can also be revived with the previous role mostly intact. divine_wrath.fire() /client/proc/punish_log(var/whom, var/punishment) - var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]." + var/msg = "[key_name_admin(src)] punished [key_name_admin(whom)] with [punishment]." message_admins(msg) admin_ticket_log(whom, msg) - log_admin("[key_name(usr)] punished [key_name(whom)] with [punishment].") + log_admin("[key_name(src)] punished [key_name(whom)] with [punishment].") /client/proc/trigger_centcom_recall() if(!check_rights(R_ADMIN)) @@ -1747,3 +1495,19 @@ Traitors and the like can also be revived with the previous role mostly intact. log_admin("[key_name(usr)] spawned floor cluwne.") message_admins("[key_name(usr)] spawned floor cluwne.") */ + +/// "Immerse", or how I made the entire playerbase quit the game. +/proc/immerse_player(mob/living/carbon/target, toggle=TRUE, remove=FALSE) + var/list/immersion_components = list(/datum/component/manual_breathing, /datum/component/manual_blinking) + + for(var/immersies in immersion_components) + var/has_component = target.GetComponent(immersies) + + if(has_component && (toggle || remove)) + qdel(has_component) + else if(toggle || !remove) + target.AddComponent(immersies) + +/proc/mass_immerse(remove=FALSE) + for(var/mob/living/carbon/M in GLOB.mob_list) + immerse_player(M, toggle=FALSE, remove=remove) diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index c7b3523906..84a91113bc 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -567,20 +567,21 @@ message_admins("[key_name_admin(holder)] has removed everyone from \ purrbation.") log_admin("[key_name(holder)] has removed everyone from purrbation.") - // if("massimmerse") // my immursion is ruinned :( - // if(!is_funmin) - // return - // mass_immerse() - // message_admins("[key_name_admin(holder)] has Fully Immersed - // everyone!") - // log_admin("[key_name(holder)] has Fully Immersed everyone.") - // if("unmassimmerse") - // if(!is_funmin) - // return - // mass_immerse(remove=TRUE) - // message_admins("[key_name_admin(holder)] has Un-Fully Immersed - // everyone!") - // log_admin("[key_name(holder)] has Un-Fully Immersed everyone.") + // Shh!! Don't let badmins know this isn't actually a button! + if("massimmerse") + if(!is_funmin) + return + mass_immerse() + message_admins("[key_name_admin(holder)] has Fully Immersed \ + everyone!") + log_admin("[key_name(holder)] has Fully Immersed everyone.") + if("unmassimmerse") + if(!is_funmin) + return + mass_immerse(remove=TRUE) + message_admins("[key_name_admin(holder)] has Un-Fully Immersed \ + everyone!") + log_admin("[key_name(holder)] has Un-Fully Immersed everyone.") if(E) E.processing = FALSE if(E.announce_when>0) diff --git a/code/modules/buildmode/submodes/smite.dm b/code/modules/buildmode/submodes/smite.dm new file mode 100644 index 0000000000..5f5050b41f --- /dev/null +++ b/code/modules/buildmode/submodes/smite.dm @@ -0,0 +1,40 @@ +/datum/buildmode_mode/smite + key = "smite" + var/datum/smite/selected_smite + +/datum/buildmode_mode/smite/Destroy() + selected_smite = null + return ..() + +/datum/buildmode_mode/smite/show_help(client/user) + to_chat(user, "***********************************************************\n\ + Right Mouse Button on buildmode button = Select smite to use.\n\ + Left Mouse Button on mob/living = Smite the mob.\n\ + ***********************************************************") + +/datum/buildmode_mode/smite/change_settings(client/user) + var/punishment = input(user, "Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites + var/smite_path = GLOB.smites[punishment] + var/datum/smite/picking_smite = new smite_path + var/configuration_success = picking_smite.configure(user) + if (configuration_success == FALSE) + return + selected_smite = picking_smite + +/datum/buildmode_mode/smite/handle_click(client/user, params_string, object) + var/list/params = params2list(params_string) + + if (!check_rights(R_ADMIN | R_FUN)) + return + + if (!params.Find("left")) + return + + if (!isliving(object)) + return + + if (selected_smite == null) + to_chat(user, "No smite selected.") + return + + selected_smite.effect(user, object) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 1652997149..bfee6b87c0 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -11,7 +11,9 @@ for(var/datum/emote/emote in key_emotes) if(!emote.can_run_emote(src, TRUE, intentional, param)) continue - emote.run_emote(src, param, m_type, intentional) + if(emote.run_emote(src, param, m_type, intentional)) + SEND_SIGNAL(src, COMSIG_MOB_EMOTE, emote, act, m_type, message, intentional) + return TRUE if(!key_emotes) to_chat(src, span_notice("Unusable emote '[act]'. Say *help for a list.")) return diff --git a/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm b/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm index c9af50de9d..d63f4e8af7 100644 --- a/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm +++ b/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm @@ -2,7 +2,7 @@ name = "Anthropomorph" id = SPECIES_MAMMAL default_color = "4B4B4B" - species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,FACEHAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None", "mam_body_markings" = list(), "taur" = "None", "horns" = "None", "legs" = "Plantigrade", "meat_type" = "Mammalian") diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index f7b82f9428..ead41dab4f 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -593,3 +593,12 @@ var/mob/living/carbon/C = user if(isjellyperson(C)) pick(playsound(C, 'sound/effects/meatslap.ogg', 50, 1),playsound(C, 'sound/effects/gib_step.ogg', 50, 1)) + +/datum/emote/inhale + key = "inhale" + key_third_person = "inhales" + message = "breathes in." +/datum/emote/exhale + key = "exhale" + key_third_person = "exhales" + message = "breathes out." diff --git a/config/entries/admin.txt b/config/entries/admin.txt index d7932bbe13..75fc08f99e 100644 --- a/config/entries/admin.txt +++ b/config/entries/admin.txt @@ -30,9 +30,9 @@ MENTOR_LEGACY_SYSTEM ## Uncomment this to forbid admins from possessing the singularity. #FORBID_SINGULO_POSSESSION -## Uncomment to show a popup 'reply to' window to every non-admin that receives an adminPM. -## The intention is to make adminPMs more visible. (although I fnd popups annoying so this defaults to off) -#POPUP_ADMIN_PM +## Uncomment to give admins the ability to send a maptext popup to players. +## Only fires when an admin requests it, not every ahelp. +POPUP_ADMIN_PM ## Uncomment this to let players see their own notes (they can still be set by admins only) #SEE_OWN_NOTES diff --git a/html/changelogs/archive/2024-10.yml b/html/changelogs/archive/2024-10.yml index 5632d98a06..32714dd786 100644 --- a/html/changelogs/archive/2024-10.yml +++ b/html/changelogs/archive/2024-10.yml @@ -11,3 +11,11 @@ - bugfix: Crop top - bugfix: HOP parade - bugfix: explorer suit (fukin spaget code) +2024-10-08: + Just-Sim: + - rscadd: popup notices + - rscadd: the ocky icky + - code_imp: added rejuvenation to the admin context menu + - refactor: refactored smites + cyfause: + - bugfix: allow facial hair on anthromorph species diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi index f0de428b6c..45ff81ba2d 100644 Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ diff --git a/modular_splurt/code/modules/admin/verbs/randomverbs.dm b/modular_splurt/code/modules/admin/verbs/randomverbs.dm index a0c81e3f19..157cb66883 100644 --- a/modular_splurt/code/modules/admin/verbs/randomverbs.dm +++ b/modular_splurt/code/modules/admin/verbs/randomverbs.dm @@ -1,12 +1,3 @@ -/client/proc/breadify(atom/movable/target) - var/obj/item/reagent_containers/food/snacks/store/bread/plain/funnyBread = new(get_turf(target)) - target.forceMove(funnyBread) - -/client/proc/bookify(atom/movable/target) - var/obj/item/reagent_containers/food/snacks/store/book/funnyBook = new(get_turf(target)) - target.forceMove(funnyBook) - funnyBook.name = "Book of " + target.name - /client/proc/cmd_admin_subtle_headset_message(mob/M, sender = null) if(!ismob(M)) return diff --git a/sound/misc/roleplay.ogg b/sound/misc/roleplay.ogg new file mode 100644 index 0000000000..e9ec545500 Binary files /dev/null and b/sound/misc/roleplay.ogg differ diff --git a/strings/phobia.json b/strings/phobia.json index ee25cc62fa..d442e9f979 100644 --- a/strings/phobia.json +++ b/strings/phobia.json @@ -38,7 +38,7 @@ "brig", "gulag" ], - + "conspiracies": [ "central command", "command", @@ -296,7 +296,7 @@ "i'll catch you", "slip" ], - + "syndicate": [ "syndicate", "changeling", @@ -315,7 +315,7 @@ "enemy corporation", "agent" ], - + "anime": [ "anime", "manga", @@ -342,5 +342,59 @@ "neet", "ora", "~" + ], + "ocky icky": [ + "admeme", + "admin", + "ahelp", + "amogus", + "antag", + "antagonist", + "ban", + "banned", + "chat", + "click", + "c*der", + "coder", + "coders", + "discord", + "erp", + "forum", + "ick ock", + "joever", + "k", + "kek", + "kys", + "leddit", + "lmao", + "lol", + "mapper", + "moderator", + "mods", + "muderbone", + "murderboning", + "ocky", + "ooc", + "owo", + "pwn", + "powergame", + "reddit", + "round", + "rule", + "rp", + "self antag", + "selfantag", + "sprite", + "spriter", + "splurt", + "sus", + "tide", + "u", + "ur", + "uwa", + "uwu", + "valid", + "y", + "5head" ] } diff --git a/tgstation.dme b/tgstation.dme index e40eaa411e..b747134eac 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -318,6 +318,7 @@ #include "code\_globalvars\tgui.dm" #include "code\_globalvars\traits.dm" #include "code\_globalvars\lists\achievements.dm" +#include "code\_globalvars\lists\admin.dm" #include "code\_globalvars\lists\client.dm" #include "code\_globalvars\lists\flavor_misc.dm" #include "code\_globalvars\lists\keybindings.dm" @@ -597,6 +598,7 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\acid.dm" #include "code\datums\components\activity.dm" +#include "code\datums\components\admin_popup.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\area_sound_manager.dm" #include "code\datums\components\armor_plate.dm" @@ -631,6 +633,8 @@ #include "code\datums\components\lifesteal.dm" #include "code\datums\components\lockon_aiming.dm" #include "code\datums\components\magnetic_catch.dm" +#include "code\datums\components\manual_blinking.dm" +#include "code\datums\components\manual_breathing.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\mirage_border.dm" #include "code\datums\components\mirv.dm" @@ -1579,13 +1583,43 @@ #include "code\modules\admin\whitelist.dm" #include "code\modules\admin\callproc\callproc.dm" #include "code\modules\admin\DB_ban\functions.dm" +#include "code\modules\admin\smites\berforate.dm" +#include "code\modules\admin\smites\bloodless.dm" +#include "code\modules\admin\smites\boneless.dm" +#include "code\modules\admin\smites\bonk.dm" +#include "code\modules\admin\smites\bookify.dm" +#include "code\modules\admin\smites\brain_damage.dm" +#include "code\modules\admin\smites\bread.dm" +#include "code\modules\admin\smites\bsa.dm" +#include "code\modules\admin\smites\cluwne.dm" +#include "code\modules\admin\smites\custompie.dm" +#include "code\modules\admin\smites\dock_pay.dm" +#include "code\modules\admin\smites\fake_bwoink.dm" +#include "code\modules\admin\smites\finalmessage.dm" +#include "code\modules\admin\smites\fireball.dm" +#include "code\modules\admin\smites\fry.dm" +#include "code\modules\admin\smites\gib.dm" +#include "code\modules\admin\smites\immerse.dm" +#include "code\modules\admin\smites\knot_shoes.dm" +#include "code\modules\admin\smites\lightning.dm" +#include "code\modules\admin\smites\nugget.dm" +#include "code\modules\admin\smites\phobia_ocky_icky.dm" +#include "code\modules\admin\smites\pickle.dm" +#include "code\modules\admin\smites\pie.dm" +#include "code\modules\admin\smites\puzzle.dm" +#include "code\modules\admin\smites\rod.dm" +#include "code\modules\admin\smites\scarify.dm" +#include "code\modules\admin\smites\shoes.dm" +#include "code\modules\admin\smites\smite.dm" +#include "code\modules\admin\smites\supply_pod.dm" +#include "code\modules\admin\smites\supply_pod_quick.dm" +#include "code\modules\admin\smites\tabletide.dm" #include "code\modules\admin\verbs\adminhelp.dm" #include "code\modules\admin\verbs\adminjump.dm" #include "code\modules\admin\verbs\adminpm.dm" #include "code\modules\admin\verbs\adminsay.dm" #include "code\modules\admin\verbs\ak47s.dm" #include "code\modules\admin\verbs\atmosdebug.dm" -#include "code\modules\admin\verbs\bluespacearty.dm" #include "code\modules\admin\verbs\borgpanel.dm" #include "code\modules\admin\verbs\BrokenInhands.dm" #include "code\modules\admin\verbs\cinematic.dm" @@ -2072,6 +2106,7 @@ #include "code\modules\buildmode\submodes\fill.dm" #include "code\modules\buildmode\submodes\mapgen.dm" #include "code\modules\buildmode\submodes\save_area.dm" +#include "code\modules\buildmode\submodes\smite.dm" #include "code\modules\buildmode\submodes\throwing.dm" #include "code\modules\buildmode\submodes\variable_edit.dm" #include "code\modules\cargo\bounty.dm"