diff --git a/.github/max_required_byond_client.txt b/.github/max_required_byond_client.txt index faf8058076a..bd10125cce9 100644 --- a/.github/max_required_byond_client.txt +++ b/.github/max_required_byond_client.txt @@ -5,4 +5,4 @@ # (Requiring clients update to connect to the game server is not something we like to spring on them with no notice, # especially for beta builds where the pager/updater won't let them update without additional configuration.) -514 +515 diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index 38463d849ea..b36684a2dab 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -668,23 +668,6 @@ }, /turf/open/floor/iron/cafeteria, /area/station/medical/medbay) -"cK" = ( -/obj/machinery/light/directional/south, -/obj/structure/table/glass, -/obj/item/disk/surgery/debug, -/obj/item/storage/box/monkeycubes{ - pixel_x = 6; - pixel_y = 1 - }, -/obj/item/storage/box/monkeycubes{ - pixel_x = -6; - pixel_y = 2 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/iron/white/corner, -/area/station/medical/medbay) "cL" = ( /obj/item/surgery_tray/full/advanced, /obj/structure/table/glass, @@ -1751,16 +1734,19 @@ /obj/effect/mapping_helpers/airalarm/unlocked, /turf/open/floor/plating, /area/station/engineering/atmos) +"hv" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/item/storage/part_replacer/bluespace/tier4, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "hD" = ( /obj/structure/closet/secure_closet/chemical/heisenberg{ locked = 0 }, /turf/open/floor/iron, /area/station/medical/chemistry) -"ib" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/cargo/bitrunning/den) "ii" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -1819,13 +1805,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) -"lE" = ( -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/obj/machinery/airalarm/directional/east, -/obj/machinery/computer/quantum_console, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) "lH" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 6 @@ -1849,11 +1828,6 @@ /obj/machinery/chem_mass_spec, /turf/open/floor/iron, /area/station/medical/chemistry) -"mV" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) "nn" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 @@ -1871,6 +1845,12 @@ /obj/item/storage/toolbox/syndicate, /turf/open/floor/iron, /area/station/commons/storage/primary) +"nI" = ( +/obj/machinery/door/airlock, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "od" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -1899,9 +1879,6 @@ /obj/machinery/door/airlock/external/glass/ruin, /turf/open/floor/plating, /area/station/medical/medbay) -"pK" = ( -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) "qb" = ( /obj/machinery/door/airlock, /turf/open/floor/plating, @@ -1932,23 +1909,34 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/central) -"rM" = ( -/obj/machinery/quantum_server, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) -"rS" = ( +"rT" = ( /turf/open/floor/circuit/green, /area/station/cargo/bitrunning/den) "sr" = ( /obj/machinery/door/airlock/shell, /turf/open/floor/iron/dark, /area/station/construction) -"sH" = ( -/obj/structure/table, -/obj/item/storage/box/shipping, -/obj/item/boulder_beacon, -/turf/open/floor/iron, -/area/station/commons/storage/primary) +"tz" = ( +/obj/machinery/light/directional/south, +/obj/structure/table/glass, +/obj/item/disk/surgery/debug, +/obj/item/storage/box/monkeycubes{ + pixel_x = 6; + pixel_y = 1 + }, +/obj/item/storage/box/monkeycubes{ + pixel_x = -6; + pixel_y = 2 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/item/disk/data/debug{ + pixel_y = 9; + pixel_x = 7 + }, +/turf/open/floor/iron/white/corner, +/area/station/medical/medbay) "tE" = ( /obj/machinery/door/airlock/research, /turf/open/floor/iron/dark, @@ -2006,6 +1994,11 @@ }, /turf/open/floor/iron/dark, /area/station/science/explab) +"vb" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "vm" = ( /mob/living/circuit_drone, /turf/open/floor/iron/dark, @@ -2079,16 +2072,16 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron, /area/station/science) +"Aj" = ( +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "AP" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 8 }, /turf/open/floor/iron, /area/station/science) -"Ba" = ( -/obj/machinery/netpod, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) "BD" = ( /obj/structure/closet/secure_closet/chief_medical{ locked = 0 @@ -2109,10 +2102,6 @@ /obj/structure/closet/syndicate/resources/everything, /turf/open/floor/iron, /area/station/science) -"Cz" = ( -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) "CQ" = ( /obj/machinery/light/directional/south, /obj/effect/turf_decal/stripes/line{ @@ -2230,6 +2219,13 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron, /area/station/command/bridge) +"IF" = ( +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/machinery/airalarm/directional/east, +/obj/machinery/computer/quantum_console, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "IH" = ( /obj/structure/closet/secure_closet/engineering_welding{ locked = 0 @@ -2263,13 +2259,6 @@ /obj/effect/mapping_helpers/airalarm/unlocked, /turf/open/floor/iron, /area/station/hallway/primary/central) -"Kf" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/obj/item/storage/part_replacer/bluespace/tier4, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) "Kx" = ( /obj/structure/table, /obj/item/analyzer, @@ -2277,15 +2266,6 @@ /obj/machinery/light/directional/south, /turf/open/floor/plating, /area/station/engineering/atmos) -"Lb" = ( -/obj/structure/table/reinforced, -/obj/machinery/light/directional/south, -/obj/item/bitrunning_debug, -/turf/open/floor/iron, -/area/station/cargo/bitrunning/den) -"Le" = ( -/turf/closed/wall/r_wall, -/area/station/cargo/bitrunning/den) "Ly" = ( /obj/machinery/chem_dispenser/chem_synthesizer, /turf/open/floor/iron/dark, @@ -2298,6 +2278,10 @@ /obj/machinery/door/airlock/research, /turf/open/floor/iron/dark, /area/station/science/explab) +"LS" = ( +/obj/machinery/quantum_server, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "LW" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, @@ -2329,10 +2313,6 @@ /obj/machinery/chem_recipe_debug, /turf/open/floor/iron, /area/station/medical/chemistry) -"Nj" = ( -/obj/machinery/byteforge, -/turf/open/floor/circuit/green, -/area/station/cargo/bitrunning/den) "Ns" = ( /obj/machinery/door/airlock/public/glass, /obj/structure/cable, @@ -2404,11 +2384,9 @@ }, /turf/open/floor/engine, /area/station/cargo/miningoffice) -"QU" = ( -/obj/machinery/door/airlock, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, -/turf/open/floor/iron, +"QY" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, /area/station/cargo/bitrunning/den) "Rb" = ( /obj/effect/spawner/structure/window/reinforced, @@ -2420,6 +2398,10 @@ }, /turf/open/floor/plating, /area/station/hallway/secondary/entry) +"Rp" = ( +/obj/machinery/byteforge, +/turf/open/floor/circuit/green, +/area/station/cargo/bitrunning/den) "RM" = ( /obj/structure/closet/secure_closet/hop{ locked = 0 @@ -2442,6 +2424,12 @@ }, /turf/open/floor/iron/white/corner, /area/station/medical/medbay) +"SC" = ( +/obj/structure/table/reinforced, +/obj/machinery/light/directional/south, +/obj/item/bitrunning_debug, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "Td" = ( /obj/machinery/light/directional/east, /obj/effect/turf_decal/stripes/line{ @@ -2456,11 +2444,18 @@ "Tt" = ( /turf/open/floor/plating, /area/station/maintenance/aft) +"TR" = ( +/obj/machinery/netpod, +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "TV" = ( /obj/machinery/door/airlock, /obj/structure/cable, /turf/open/floor/iron, /area/station/construction) +"Ue" = ( +/turf/closed/wall/r_wall, +/area/station/cargo/bitrunning/den) "Ut" = ( /obj/structure/closet/secure_closet/medical3{ locked = 0 @@ -2468,6 +2463,16 @@ /obj/item/healthanalyzer/advanced, /turf/open/floor/iron, /area/station/medical/medbay) +"Va" = ( +/obj/machinery/power/smes/full, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/structure/cable, +/obj/machinery/airalarm/directional/north, +/obj/effect/mapping_helpers/airalarm/unlocked, +/turf/open/floor/iron, +/area/station/engineering/gravity_generator) "Vg" = ( /obj/machinery/light/directional/south, /obj/structure/cable, @@ -2512,16 +2517,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/gravity_generator) -"Wy" = ( -/obj/machinery/power/smes/full, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/obj/structure/cable, -/obj/machinery/airalarm/directional/north, -/obj/effect/mapping_helpers/airalarm/unlocked, -/turf/open/floor/iron, -/area/station/engineering/gravity_generator) "WK" = ( /obj/structure/money_bot, /turf/open/floor/iron/dark, @@ -2581,6 +2576,9 @@ /obj/effect/landmark/blobstart, /turf/open/floor/iron, /area/station/commons/storage/primary) +"Yd" = ( +/turf/open/floor/iron, +/area/station/cargo/bitrunning/den) "Ym" = ( /obj/structure/table, /obj/item/storage/toolbox/electrical, @@ -2623,6 +2621,12 @@ /obj/machinery/suit_storage_unit/ce, /turf/open/floor/iron, /area/station/engineering/atmos) +"ZK" = ( +/obj/structure/table, +/obj/item/storage/box/shipping, +/obj/item/boulder_beacon, +/turf/open/floor/iron, +/area/station/commons/storage/primary) "ZP" = ( /turf/open/floor/iron/dark, /area/station/science/explab) @@ -3200,12 +3204,12 @@ aa aa aa aa -Le -Le -Le -Le -Le -Le +Ue +Ue +Ue +Ue +Ue +Ue aa aa aa @@ -3292,12 +3296,12 @@ aa aa aa aa -Le -rS -Nj -pK -Ba -Le +Ue +rT +Rp +Yd +TR +Ue aa aa aa @@ -3384,12 +3388,12 @@ aa aa aa aa -Le -rM -pK -Kf -Ba -Le +Ue +LS +Yd +hv +TR +Ue aa aa aa @@ -3476,12 +3480,12 @@ aa aa aa aa -Le -lE -Cz -mV -Lb -Le +Ue +IF +Aj +vb +SC +Ue aa aa aa @@ -3568,12 +3572,12 @@ em em em em -Le -Le -Le -QU -ib -Le +Ue +Ue +Ue +nI +QY +Ue Tj Tj Tj @@ -7611,7 +7615,7 @@ aa ad af ak -Wy +Va aG aV bg @@ -7820,7 +7824,7 @@ dJ dJ dJ dJ -sH +ZK cS fP fO @@ -8267,7 +8271,7 @@ is cy Ut cm -cK +tz by dB dx diff --git a/_maps/shuttles/skyrat/arrivals_skyrat.dmm b/_maps/shuttles/skyrat/arrivals_skyrat.dmm index 8968c17261b..35bc8135425 100644 --- a/_maps/shuttles/skyrat/arrivals_skyrat.dmm +++ b/_maps/shuttles/skyrat/arrivals_skyrat.dmm @@ -218,6 +218,7 @@ /area/shuttle/arrival) "U" = ( /obj/machinery/door/airlock/external, +/obj/structure/fans/tiny, /turf/open/floor/iron/shuttle/arrivals, /area/shuttle/arrival) "V" = ( diff --git a/code/__DEFINES/construction/structures.dm b/code/__DEFINES/construction/structures.dm index 1b4ea8aa112..e48dc078ca4 100644 --- a/code/__DEFINES/construction/structures.dm +++ b/code/__DEFINES/construction/structures.dm @@ -48,9 +48,11 @@ #define AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS 1 #define AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER 2 -//blast door (de)construction states +///The blast door is missing wires, first step of construction. #define BLASTDOOR_NEEDS_WIRES 0 +///The blast door needs electronics, second step of construction. #define BLASTDOOR_NEEDS_ELECTRONICS 1 +///The blast door is fully constructed. #define BLASTDOOR_FINISHED 2 //floodlights because apparently we use defines now diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index cc9e4d2e966..5a328a62ef7 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -146,6 +146,8 @@ #define COMPONENT_LIVING_BLOCK_PRE_MOB_BUMP (1<<0) ///From base of mob/living/MobBump() (mob/living) #define COMSIG_LIVING_MOB_BUMP "living_mob_bump" +///From base of mob/living/MobBump() (mob/living) +#define COMSIG_LIVING_MOB_BUMPED "living_mob_bumped" ///From base of mob/living/Bump() (turf/closed) #define COMSIG_LIVING_WALL_BUMP "living_wall_bump" ///From base of turf/closed/Exited() (turf/closed) diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 43e3a09a028..f628df0e964 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -448,7 +448,10 @@ /// Prevents click from happening. #define COMPONENT_CANCEL_EQUIPMENT_CLICK (1<<0) +///from base of /obj/item/attack(): (mob/living, mob/living, params) #define COMSIG_ITEM_ATTACK "item_attack" +///from base of /obj/item/attack(): (mob/living, mob/living, params) +#define COMSIG_ITEM_POST_ATTACK "item_post_attack" // called only if the attack was executed ///from base of obj/item/attack_self(): (/mob) #define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self_secondary(): (/mob) diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 08993ad56de..5bb2c89d4ef 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -19,8 +19,8 @@ ///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume) #define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf" -///from base of [/datum/system/materials/proc/InitializeMaterial]: (/datum/material) -#define COMSIG_MATERIALS_INIT_MAT "DSmaterials_init_mat" +///from base of [/datum/materials_controller/proc/InitializeMaterial]: (/datum/material) +#define COMSIG_MATERIALS_INIT_MAT "SSmaterials_init_mat" ///from base of [/datum/component/multiple_lives/proc/respawn]: (mob/respawned_mob, gibbed, lives_left) #define COMSIG_ON_MULTIPLE_LIVES_RESPAWN "on_multiple_lives_respawn" diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 4281fba00cb..402b104cabf 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -353,3 +353,6 @@ #define VOTE_WINNER_METHOD_WEIGHTED_RANDOM "Weighted Random" /// There is no winner for this vote. #define VOTE_WINNER_METHOD_NONE "None" + +/// Returned by [/datum/vote/proc/can_be_initiated] to denote the vote is valid and can be initiated. +#define VOTE_AVAILABLE "Vote Available" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 4f67591f13c..371f6da37b0 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -952,6 +952,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define STATION_TRAIT_BIGGER_PODS "station_trait_bigger_pods" #define STATION_TRAIT_BIRTHDAY "station_trait_birthday" #define STATION_TRAIT_BOTS_GLITCHED "station_trait_bot_glitch" +#define STATION_TRAIT_BRIGHT_DAY "station_trait_bright_day" #define STATION_TRAIT_CARP_INFESTATION "station_trait_carp_infestation" #define STATION_TRAIT_CYBERNETIC_REVOLUTION "station_trait_cybernetic_revolution" #define STATION_TRAIT_EMPTY_MAINT "station_trait_empty_maint" diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 7af30c8d972..6811a31284a 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -417,7 +417,7 @@ **/ /proc/list_clear_nulls(list/list_to_clear) return (list_to_clear.RemoveAll(null) > 0) - + /** * Removes any empty weakrefs from the list @@ -473,17 +473,23 @@ * You should only pass integers in. */ /proc/pick_weight(list/list_to_pick) + if(length(list_to_pick) == 0) + return null + var/total = 0 - var/item - for(item in list_to_pick) + for(var/item in list_to_pick) if(!list_to_pick[item]) list_to_pick[item] = 0 total += list_to_pick[item] total = rand(1, total) - for(item in list_to_pick) - total -= list_to_pick[item] - if(total <= 0 && list_to_pick[item]) + for(var/item in list_to_pick) + var/item_weight = list_to_pick[item] + if(item_weight == 0) + continue + + total -= item_weight + if(total <= 0) return item return null diff --git a/code/__HELPERS/construction.dm b/code/__HELPERS/construction.dm index cf38f690c26..f7b0ece13f8 100644 --- a/code/__HELPERS/construction.dm +++ b/code/__HELPERS/construction.dm @@ -2,7 +2,7 @@ #define OPTIMAL_COST(cost)(max(1, round(cost))) /// Wrapper for fetching material references. Exists exclusively so that people don't need to wrap everything in a list every time. -#define GET_MATERIAL_REF(arguments...) DSmaterials._GetMaterialRef(list(##arguments)) +#define GET_MATERIAL_REF(arguments...) SSmaterials._GetMaterialRef(list(##arguments)) // Wrapper to convert material name into its source name #define MATERIAL_SOURCE(mat) "[mat.name]_material" diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 89a666093ee..7ae0feadea7 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -172,8 +172,8 @@ GLOB.crafting_recipes += recipe var/list/material_stack_recipes = list( - DSmaterials.base_stack_recipes, - DSmaterials.rigid_stack_recipes, + SSmaterials.base_stack_recipes, + SSmaterials.rigid_stack_recipes, ) for(var/list/recipe_list in material_stack_recipes) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index a6b23e08b49..9a2de31ea53 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -288,7 +288,7 @@ GLOBAL_LIST_EMPTY(species_list) var/atom/target_loc = target?.loc var/drifting = FALSE - if(DSmove_manager.processing_on(user, SSspacedrift)) + if(GLOB.move_manager.processing_on(user, SSspacedrift)) drifting = TRUE var/holding = user.get_active_held_item() @@ -317,7 +317,7 @@ GLOBAL_LIST_EMPTY(species_list) if(!QDELETED(progbar)) progbar.update(world.time - starttime) - if(drifting && !DSmove_manager.processing_on(user, SSspacedrift)) + if(drifting && !GLOB.move_manager.processing_on(user, SSspacedrift)) drifting = FALSE user_loc = user.loc diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index 380a8707fbe..b9964b9be93 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -107,7 +107,7 @@ message.title = title message.content = text - DScommunications.send_message(message) + GLOB.communications_controller.send_message(message) /** * Sends a minor annoucement to players. diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 469cbcee76d..ba4f8e802e8 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -80,6 +80,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "STATION_TRAIT_BIGGER_PODS" = STATION_TRAIT_BIGGER_PODS, "STATION_TRAIT_BIRTHDAY" = STATION_TRAIT_BIRTHDAY, "STATION_TRAIT_BOTS_GLITCHED" = STATION_TRAIT_BOTS_GLITCHED, + "STATION_TRAIT_BRIGHT_DAY" = STATION_TRAIT_BRIGHT_DAY, "STATION_TRAIT_CARP_INFESTATION" = STATION_TRAIT_CARP_INFESTATION, "STATION_TRAIT_CYBERNETIC_REVOLUTION" = STATION_TRAIT_CYBERNETIC_REVOLUTION, "STATION_TRAIT_EMPTY_MAINT" = STATION_TRAIT_EMPTY_MAINT, diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index d5ba848fc8d..1d05ccc16c0 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -236,6 +236,8 @@ user.do_attack_animation(target_mob) target_mob.attacked_by(src, user) + SEND_SIGNAL(src, COMSIG_ITEM_POST_ATTACK, target_mob, user, params) + log_combat(user, target_mob, "attacked", src.name, "(COMBAT MODE: [uppertext(user.combat_mode)]) (DAMTYPE: [uppertext(damtype)])") add_fingerprint(user) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 368ae3a3840..068f857c8cb 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -347,6 +347,16 @@ min_val = 0 integer = FALSE +/datum/config_entry/number/events_frequency_lower + default = 2.5 MINUTES + min_val = 0 + protection = CONFIG_ENTRY_LOCKED + +/datum/config_entry/number/events_frequency_upper + default = 7 MINUTES + min_val = 0 + protection = CONFIG_ENTRY_LOCKED + /datum/config_entry/number/mice_roundstart default = 10 min_val = 0 diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 09e4dec760c..b3ff39ef1fe 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -188,13 +188,13 @@ /// minimum time between voting sessions (deciseconds, 10 minute default) /datum/config_entry/number/vote_delay - default = 6000 + default = 10 MINUTES integer = FALSE min_val = 0 /// length of voting period (deciseconds, default 1 minute) /datum/config_entry/number/vote_period - default = 600 + default = 1 MINUTES integer = FALSE min_val = 0 diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index 549d33ac7b3..254034af08c 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -317,7 +317,7 @@ SUBSYSTEM_DEF(dynamic) SSticker.news_report = SSshuttle.emergency?.is_hijacked() ? SHUTTLE_HIJACK : STATION_EVACUATED /datum/controller/subsystem/dynamic/proc/send_intercept() - if(DScommunications.block_command_report) //If we don't want the report to be printed just yet, we put it off until it's ready + if(GLOB.communications_controller.block_command_report) //If we don't want the report to be printed just yet, we put it off until it's ready addtimer(CALLBACK(src, PROC_REF(send_intercept)), 10 SECONDS) return @@ -349,10 +349,10 @@ SUBSYSTEM_DEF(dynamic) if(trait_list_strings.len > 0) . += "
Identified shift divergencies:
" + trait_list_strings.Join() - if(length(DScommunications.command_report_footnotes)) + if(length(GLOB.communications_controller.command_report_footnotes)) var/footnote_pile = "" - for(var/datum/command_footnote/footnote in DScommunications.command_report_footnotes) + for(var/datum/command_footnote/footnote in GLOB.communications_controller.command_report_footnotes) footnote_pile += "[footnote.message]
" footnote_pile += "[footnote.signature]
" footnote_pile += "
" diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index 241622509af..23b36eb994e 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -25,6 +25,10 @@ SUBSYSTEM_DEF(events) if(!event.typepath || !event.valid_for_map()) continue //don't want this one! leave it for the garbage collector control += event //add it to the list of all events (controls) + + frequency_lower = CONFIG_GET(number/events_frequency_lower) + frequency_upper = CONFIG_GET(number/events_frequency_upper) + reschedule() // Instantiate our holidays list if it hasn't been already if(isnull(GLOB.holidays)) @@ -91,7 +95,8 @@ SUBSYSTEM_DEF(events) event_roster[event_to_check] = event_to_check.weight var/datum/round_event_control/event_to_run = pick_weight(event_roster) - TriggerEvent(event_to_run) + if(event_to_run) + TriggerEvent(event_to_run) ///Does the last pre-flight checks for the passed event, and runs it if the event is ready. /datum/controller/subsystem/events/proc/TriggerEvent(datum/round_event_control/event_to_trigger) @@ -109,8 +114,8 @@ SUBSYSTEM_DEF(events) ///Sets the event frequency bounds back to their initial value. /datum/controller/subsystem/events/proc/resetFrequency() - frequency_lower = initial(frequency_lower) - frequency_upper = initial(frequency_upper) + frequency_lower = CONFIG_GET(number/events_frequency_lower) + frequency_upper = CONFIG_GET(number/events_frequency_upper) /** * HOLIDAYS diff --git a/code/datums/systems/ds/materials.dm b/code/controllers/subsystem/materials.dm similarity index 92% rename from code/datums/systems/ds/materials.dm rename to code/controllers/subsystem/materials.dm index 527c1a3d642..b4664323eeb 100644 --- a/code/datums/systems/ds/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -1,12 +1,12 @@ /*! How material datums work -Materials are now instanced datums, with an associative list of them being kept in DSmaterials. We only instance the materials once and then re-use these instances for everything. +Materials are now instanced datums, with an associative list of them being kept in SSmaterials. We only instance the materials once and then re-use these instances for everything. These materials call on_applied() on whatever item they are applied to, common effects are adding components, changing color and changing description. This allows us to differentiate items based on the material they are made out of.area */ - -DATASYSTEM_DEF(materials) +SUBSYSTEM_DEF(materials) name = "Materials" + flags = SS_NO_FIRE | SS_NO_INIT ///Dictionary of material.id || material ref var/list/materials ///Dictionary of type || list of material refs @@ -36,7 +36,7 @@ DATASYSTEM_DEF(materials) var/list/datum/dimension_theme/dimensional_themes ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) -/datum/system/materials/proc/InitializeMaterials() +/datum/controller/subsystem/materials/proc/InitializeMaterials() materials = list() materials_by_type = list() materialids_by_type = list() @@ -57,7 +57,7 @@ DATASYSTEM_DEF(materials) * - [arguments][/list]: The arguments to use to create the material datum * - The first element is the type of material to initialize. */ -/datum/system/materials/proc/InitializeMaterial(list/arguments) +/datum/controller/subsystem/materials/proc/InitializeMaterial(list/arguments) var/datum/material/mat_type = arguments[1] if(initial(mat_type.init_flags) & MATERIAL_INIT_BESPOKE) arguments[1] = GetIdFromArguments(arguments) @@ -89,13 +89,13 @@ DATASYSTEM_DEF(materials) * - If the material type is bespoke a text ID is generated from the arguments list and used to load a material datum from the cache. * - The following elements are used to generate bespoke IDs */ -/datum/system/materials/proc/_GetMaterialRef(list/arguments) +/datum/controller/subsystem/materials/proc/_GetMaterialRef(list/arguments) if(!materials) InitializeMaterials() var/datum/material/key = arguments[1] if(istype(key)) - return key // We are assuming here that the only thing allowed to create material datums is [/datum/system/materials/proc/InitializeMaterial] + return key // We are assuming here that the only thing allowed to create material datums is [/datum/controller/subsystem/materials/proc/InitializeMaterial] if(istext(key)) // Handle text id . = materials[key] @@ -123,7 +123,7 @@ DATASYSTEM_DEF(materials) * Named arguments can appear in any order and we need them to appear after ordered arguments * We assume that no one will pass in a named argument with a value of null **/ -/datum/system/materials/proc/GetIdFromArguments(list/arguments) +/datum/controller/subsystem/materials/proc/GetIdFromArguments(list/arguments) var/datum/material/mattype = arguments[1] var/list/fullid = list("[initial(mattype.id) || mattype]") var/list/named_arguments = list() @@ -149,7 +149,7 @@ DATASYSTEM_DEF(materials) /// Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters. -/datum/system/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier) +/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier) if(!LAZYLEN(materials_declaration)) return null // If we get a null we pass it right back, we don't want to generate stack traces just because something is clearing out its materials list. diff --git a/code/controllers/subsystem/movement/cliff_falling.dm b/code/controllers/subsystem/movement/cliff_falling.dm index 65089f0ea1b..b3d7f114dfb 100644 --- a/code/controllers/subsystem/movement/cliff_falling.dm +++ b/code/controllers/subsystem/movement/cliff_falling.dm @@ -10,7 +10,7 @@ MOVEMENT_SUBSYSTEM_DEF(cliff_falling) /datum/controller/subsystem/movement/cliff_falling/proc/start_falling(atom/movable/faller, turf/open/cliff/cliff) // Make them move - var/mover = DSmove_manager.move(moving = faller, direction = cliff.fall_direction, delay = cliff.fall_speed, subsystem = src, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_OUTSIDE_CONTROL | MOVEMENT_LOOP_NO_DIR_UPDATE) + var/mover = GLOB.move_manager.move(moving = faller, direction = cliff.fall_direction, delay = cliff.fall_speed, subsystem = src, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_OUTSIDE_CONTROL | MOVEMENT_LOOP_NO_DIR_UPDATE) cliff_grinders[faller] = mover diff --git a/code/controllers/subsystem/movement/movement_types.dm b/code/controllers/subsystem/movement/movement_types.dm index 3567e881b14..50864f731e2 100644 --- a/code/controllers/subsystem/movement/movement_types.dm +++ b/code/controllers/subsystem/movement/movement_types.dm @@ -162,7 +162,7 @@ status &= ~MOVELOOP_STATUS_PAUSED ///Removes the atom from some movement subsystem. Defaults to SSmovement -/datum/system/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement) +/datum/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement) var/datum/movement_packet/our_info = moving.move_packet if(!our_info) return FALSE @@ -183,7 +183,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/move, priority, flags, extra_info, delay, timeout, direction) ///Replacement for walk() @@ -224,7 +224,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/force_move_dir(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/force_move_dir(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/move/force, priority, flags, extra_info, delay, timeout, direction) /datum/move_loop/move/force @@ -281,7 +281,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/force_move(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/force_move(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/force_move, priority, flags, extra_info, delay, timeout, chasing) ///Used for force-move loops @@ -315,7 +315,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/jps_move(moving, +/datum/move_manager/proc/jps_move(moving, chasing, delay, timeout, @@ -493,7 +493,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_to(moving, chasing, min_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_to(moving, chasing, min_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/dist_bound/move_to, priority, flags, extra_info, delay, timeout, chasing, min_dist) ///Wrapper around walk_to() @@ -527,7 +527,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_away(moving, chasing, max_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_away(moving, chasing, max_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/dist_bound/move_away, priority, flags, extra_info, delay, timeout, chasing, max_dist) ///Wrapper around walk_away() @@ -562,7 +562,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_towards(moving, chasing, delay, home, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_towards(moving, chasing, delay, home, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/move_towards, priority, flags, extra_info, delay, timeout, chasing, home) /** @@ -581,7 +581,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/home_onto(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/home_onto(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) return move_towards(moving, chasing, delay, TRUE, timeout, subsystem, priority, flags, extra_info) ///Used as a alternative to walk_towards @@ -717,7 +717,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_towards_legacy(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_towards_legacy(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/move_towards_budget, priority, flags, extra_info, delay, timeout, chasing) ///The actual implementation of walk_towards() @@ -743,7 +743,7 @@ * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm */ -/datum/system/move_manager/proc/freeze(moving, halted_turf, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/freeze(moving, halted_turf, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/freeze, priority, flags, extra_info, delay, timeout, halted_turf) /// As close as you can get to a "do-nothing" move loop, the pure intention of this is to absolutely resist all and any automated movement until the move loop times out. @@ -767,7 +767,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info) if(!directions) directions = GLOB.alldirs return add_to_loop(moving, subsystem, /datum/move_loop/move_rand, priority, flags, extra_info, delay, timeout, directions) @@ -819,7 +819,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_to_rand(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_to_rand(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/move_to_rand, priority, flags, extra_info, delay, timeout) ///Wrapper around step_rand @@ -845,7 +845,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/system/move_manager/proc/move_disposals(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/move_manager/proc/move_disposals(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/disposal_holder, priority, flags, extra_info, delay, timeout) /// Disposal holders need to move through a chain of pipes diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index dcca82fe6d8..733b94d582a 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -192,7 +192,6 @@ SUBSYSTEM_DEF(statpanels) list("World Time:", "[world.time]"), list("Globals:", GLOB.stat_entry(), text_ref(GLOB)), list("[config]:", config.stat_entry(), text_ref(config)), - list("Datasystem Manager:", "Edit", text_ref(SysMgr)), list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), list("Master Controller:", Master.stat_entry(), text_ref(Master)), list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)), diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index b73d190b30a..14d4b7ed293 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -18,6 +18,8 @@ SUBSYSTEM_DEF(vote) var/list/voted = list() /// A list of all ckeys currently voting for the current vote. var/list/voting = list() + /// World.time we started our last vote + var/last_vote_time = -INFINITY /datum/controller/subsystem/vote/Initialize() for(var/vote_type in subtypesof(/datum/vote)) @@ -30,16 +32,20 @@ SUBSYSTEM_DEF(vote) return SS_INIT_SUCCESS - // Called by master_controller /datum/controller/subsystem/vote/fire() if(!current_vote) return current_vote.time_remaining = round((current_vote.started_time + CONFIG_GET(number/vote_period) - world.time) / 10) if(current_vote.time_remaining < 0) - process_vote_result() - SStgui.close_uis(src) - reset() + end_vote() + +/// Ends the current vote. +/datum/controller/subsystem/vote/proc/end_vote() + ASSERT(current_vote) + process_vote_result() + SStgui.close_uis(src) + reset() /// Resets all of our vars after votes conclude / are cancelled. /datum/controller/subsystem/vote/proc/reset() @@ -175,24 +181,10 @@ SUBSYSTEM_DEF(vote) * * vote_type - The type of vote to initiate. Can be a [/datum/vote] typepath, a [/datum/vote] instance, or the name of a vote datum. * * vote_initiator_name - The ckey (if player initiated) or name that initiated a vote. Ex: "UristMcAdmin", "the server" * * vote_initiator - If a person / mob initiated the vote, this is the mob that did it - * * forced - Whether we're forcing the vote to go through regardless of existing votes or other circumstances. Note: If the vote is admin created, forced becomes true regardless. + * * forced - Whether we're forcing the vote to go through regardless of existing votes or other circumstances. */ /datum/controller/subsystem/vote/proc/initiate_vote(vote_type, vote_initiator_name, mob/vote_initiator, forced = FALSE) - - // Even if it's forced we can't vote before we're set up - if(!MC_RUNNING(init_stage)) - if(vote_initiator) - to_chat(vote_initiator, span_warning("You cannot start vote now, the server is not done initializing.")) - return FALSE - - // Check if we have unlimited voting power. - // Admin started (or forced) voted will go through even if there's an ongoing vote, - // if voting is on cooldown, or regardless if a vote is config disabled (in some cases) - var/unlimited_vote_power = forced || !!GLOB.admin_datums[vote_initiator?.ckey] - - if(current_vote && !unlimited_vote_power) - if(vote_initiator) - to_chat(vote_initiator, span_warning("There is already a vote in progress! Please wait for it to finish.")) + if(!can_vote_start(vote_initiator, forced)) return FALSE // Get our actual datum @@ -219,7 +211,7 @@ SUBSYSTEM_DEF(vote) return FALSE // Vote can't be initiated in our circumstances? No vote - if(!to_vote.can_be_initiated(vote_initiator, unlimited_vote_power)) + if(to_vote.can_be_initiated(forced) != VOTE_AVAILABLE) return FALSE // Okay, we're ready to actually create a vote - @@ -230,8 +222,12 @@ SUBSYSTEM_DEF(vote) if(!to_vote.create_vote(vote_initiator)) return FALSE + if(!vote_initiator_name && vote_initiator) + vote_initiator_name = vote_initiator.key + // Okay, the vote's happening now, for real. Set it up. current_vote = to_vote + last_vote_time = world.time var/duration = CONFIG_GET(number/vote_period) var/to_display = current_vote.initiate_vote(vote_initiator_name, duration) @@ -255,6 +251,36 @@ SUBSYSTEM_DEF(vote) return TRUE +/** + * Checks if we can start a vote. + * + * * vote_initiator - The mob that initiated the vote. + * * forced - Whether we're forcing the vote to go through regardless of existing votes or other circumstances. + * + * Returns TRUE if we can start a vote, FALSE if we can't. + */ +/datum/controller/subsystem/vote/proc/can_vote_start(mob/vote_initiator, forced) + // Even if it's forced we can't vote before we're set up + if(!MC_RUNNING(init_stage)) + if(vote_initiator) + to_chat(vote_initiator, span_warning("You cannot start a vote now, the server is not done initializing.")) + return FALSE + + if(forced) + return TRUE + + var/next_allowed_time = last_vote_time + CONFIG_GET(number/vote_delay) + if(next_allowed_time > world.time) + if(vote_initiator) + to_chat(vote_initiator, span_warning("A vote was initiated recently. You must wait [DisplayTimeText(next_allowed_time - world.time)] before a new vote can be started!")) + return FALSE + + if(current_vote) + if(vote_initiator) + to_chat(vote_initiator, span_warning("There is already a vote in progress! Please wait for it to finish.")) + return FALSE + + return TRUE /datum/controller/subsystem/vote/ui_state() return GLOB.always_state @@ -289,11 +315,12 @@ SUBSYSTEM_DEF(vote) if(!istype(vote)) continue + var/can_vote = vote.can_be_initiated(is_lower_admin) var/list/vote_data = list( "name" = vote_name, - "canBeInitiated" = vote.can_be_initiated(forced = is_lower_admin), + "canBeInitiated" = can_vote == VOTE_AVAILABLE, "config" = vote.is_config_enabled(), - "message" = vote.message, + "message" = can_vote == VOTE_AVAILABLE ? vote.default_message : can_vote, ) if(vote == current_vote) @@ -317,9 +344,15 @@ SUBSYSTEM_DEF(vote) all_vote_data += list(vote_data) data["possibleVotes"] = all_vote_data + data["LastVoteTime"] = last_vote_time - world.time return data +/datum/controller/subsystem/vote/ui_static_data(mob/user) + var/list/data = list() + data["VoteCD"] = CONFIG_GET(number/vote_delay) + return data + /datum/controller/subsystem/vote/ui_act(action, params) . = ..() if(.) @@ -330,19 +363,37 @@ SUBSYSTEM_DEF(vote) switch(action) if("cancel") if(!voter.client?.holder) + message_admins("[key_name(voter)] tried to cancel the current vote while having no admin holder, \ + this is potentially a malicious exploit and worth noting.") return voter.log_message("cancelled a vote.", LOG_ADMIN) message_admins("[key_name_admin(voter)] has cancelled the current vote.") + SStgui.close_uis(src) reset() return TRUE + if("endNow") + if(!voter.client?.holder) + message_admins("[key_name(voter)] tried to end the current vote while having no admin holder, \ + this is potentially a malicious exploit and worth noting.") + return + + voter.log_message("ended the current vote early", LOG_ADMIN) + message_admins("[key_name_admin(voter)] has ended the current vote.") + end_vote() + return TRUE + if("toggleVote") var/datum/vote/selected = possible_votes[params["voteName"]] if(!istype(selected)) return + if(!check_rights_for(voter.client, R_ADMIN)) + message_admins("[key_name(voter)] tried to toggle vote availability while having improper rights, \ + this is potentially a malicious exploit and worth noting.") + return - return selected.toggle_votable(voter) + return selected.toggle_votable() if("callVote") var/datum/vote/selected = possible_votes[params["voteName"]] @@ -351,7 +402,12 @@ SUBSYSTEM_DEF(vote) // Whether the user actually can initiate this vote is checked in initiate_vote, // meaning you can't spoof initiate a vote you're not supposed to be able to - return initiate_vote(selected, voter.key, voter) + return initiate_vote( + vote_type = selected, + vote_initiator_name = voter.key, + vote_initiator = voter, + forced = !!GLOB.admin_datums[voter.ckey], + ) if("voteSingle") return submit_single_vote(voter, params["voteOption"]) @@ -359,6 +415,15 @@ SUBSYSTEM_DEF(vote) if("voteMulti") return submit_multi_vote(voter, params["voteOption"]) + if("resetCooldown") + if(!voter.client.holder) + message_admins("[key_name(voter)] tried to reset the vote cooldown while having no admin holder, \ + this is potentially a malicious exploit and worth noting.") + return + + last_vote_time = -INFINITY + return TRUE + /datum/controller/subsystem/vote/ui_close(mob/user) voting -= user.client?.ckey @@ -367,6 +432,10 @@ SUBSYSTEM_DEF(vote) set category = "OOC" set name = "Vote" + if(!SSvote.initialized) + to_chat(usr, span_notice("Voting is not set up yet!")) + return + SSvote.ui_interact(usr) /// Datum action given to mobs that allows players to vote on the current vote. diff --git a/code/datums/actions/mobs/charge.dm b/code/datums/actions/mobs/charge.dm index 07c6330c71a..9aee4cd8345 100644 --- a/code/datums/actions/mobs/charge.dm +++ b/code/datums/actions/mobs/charge.dm @@ -44,7 +44,7 @@ if(charger in charging) // Stop any existing charging, this'll clean things up properly - DSmove_manager.stop_looping(charger) + GLOB.move_manager.stop_looping(charger) charging += charger actively_moving = FALSE @@ -60,7 +60,7 @@ var/time_to_hit = min(get_dist(charger, target), charge_distance) * charge_speed - var/datum/move_loop/new_loop = DSmove_manager.home_onto(charger, target, delay = charge_speed, timeout = time_to_hit, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/new_loop = GLOB.move_manager.home_onto(charger, target, delay = charge_speed, timeout = time_to_hit, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) if(!new_loop) return RegisterSignal(new_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move), override = TRUE) @@ -96,7 +96,7 @@ /datum/action/cooldown/mob_cooldown/charge/update_status_on_signal(mob/source, new_stat, old_stat) . = ..() if(new_stat == DEAD) - DSmove_manager.stop_looping(source) //This will cause the loop to qdel, triggering an end to our charging + GLOB.move_manager.stop_looping(source) //This will cause the loop to qdel, triggering an end to our charging /datum/action/cooldown/mob_cooldown/charge/proc/do_charge_indicator(atom/charger, atom/charge_target) var/turf/target_turf = get_turf(charge_target) diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index c5717ceb044..35615c6704c 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -172,9 +172,13 @@ multiple modular subtrees with behaviors return FALSE return TRUE -/datum/ai_controller/proc/recalculate_idle() +/datum/ai_controller/proc/recalculate_idle(datum/exited) if(ai_status == AI_STATUS_OFF) return + + if(exited && (get_dist(pawn, (islist(exited) ? exited[1] : exited)) <= interesting_dist)) //is our target in between interesting cells? + return + if(should_idle()) set_ai_status(AI_STATUS_IDLE) @@ -187,7 +191,7 @@ multiple modular subtrees with behaviors /datum/ai_controller/proc/on_client_exit(datum/source, datum/exited) SIGNAL_HANDLER - recalculate_idle() + recalculate_idle(exited) /// Sets the AI on or off based on current conditions, call to reset after you've manually disabled it somewhere /datum/ai_controller/proc/reset_ai_status() @@ -279,7 +283,7 @@ multiple modular subtrees with behaviors /datum/ai_controller/process(seconds_per_tick) if(!able_to_run()) - DSmove_manager.stop_looping(pawn) //stop moving + GLOB.move_manager.stop_looping(pawn) //stop moving return //this should remove them from processing in the future through event-based stuff. if(!LAZYLEN(current_behaviors) && idle_behavior) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm index f0ee4bb9bba..4cf04039e85 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm @@ -7,6 +7,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ /datum/ai_behavior/find_potential_targets action_cooldown = 2 SECONDS + behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /// How far can we see stuff? var/vision_range = 9 /// Blackboard key for aggro range, uses vision range if not specified @@ -34,7 +35,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ // If we're using a field rn, just don't do anything yeah? if(controller.blackboard[BB_FIND_TARGETS_FIELD(type)]) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/list/potential_targets = hearers(aggro_range, get_turf(controller.pawn)) - living_mob //Remove self, so we don't suicide diff --git a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm index a4fc49facc0..52b19036b9a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm @@ -21,6 +21,7 @@ return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED pawn.visible_message(span_notice("[pawn] calms down.")) // We can blackboard key this if anyone else actually wants to customise it controller.clear_blackboard_key(BB_BASIC_MOB_RETALIATE_LIST) + controller.clear_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET) controller.CancelActions() // Otherwise they will try and get one last kick in return AI_BEHAVIOR_DELAY diff --git a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm index d327b1047cf..042ccb2310c 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -11,7 +11,6 @@ var/check_faction = FALSE /datum/ai_planning_subtree/target_retaliate/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - . = ..() controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list, BB_BASIC_MOB_RETALIATE_LIST, target_key, targeting_strategy_key, hiding_place_key, check_faction) /datum/ai_planning_subtree/target_retaliate/check_faction @@ -35,7 +34,6 @@ var/vision_range = 9 /datum/ai_behavior/target_from_retaliate_list/perform(seconds_per_tick, datum/ai_controller/controller, shitlist_key, target_key, targeting_strategy_key, hiding_location_key, check_faction) - . = ..() var/mob/living/living_mob = controller.pawn var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if(!targeting_strategy) @@ -58,7 +56,6 @@ enemies_list += potential_target if(!length(enemies_list)) - controller.clear_blackboard_key(target_key) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/atom/new_target = pick_final_target(controller, enemies_list) @@ -75,7 +72,7 @@ /datum/ai_behavior/target_from_retaliate_list/proc/pick_final_target(datum/ai_controller/controller, list/enemies_list) return pick(enemies_list) -/datum/ai_behavior/target_from_retaliate_list/finish_action(datum/ai_controller/controller, succeeded, check_faction) +/datum/ai_behavior/target_from_retaliate_list/finish_action(datum/ai_controller/controller, succeeded, shitlist_key, target_key, targeting_strategy_key, hiding_location_key, check_faction) . = ..() if (succeeded || check_faction) return diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index 10a23acdabe..af9091db2dd 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -120,7 +120,7 @@ break if(target) - DSmove_manager.move_away(living_pawn, target, max_dist=MONKEY_ENEMY_VISION, delay=5) + GLOB.move_manager.move_away(living_pawn, target, max_dist=MONKEY_ENEMY_VISION, delay=5) return AI_BEHAVIOR_DELAY return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED @@ -161,7 +161,7 @@ controller.clear_blackboard_key(target_key) if(QDELETED(living_pawn)) // pawn can be null at this point return - DSmove_manager.stop_looping(living_pawn) + GLOB.move_manager.stop_looping(living_pawn) /// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little /datum/ai_behavior/monkey_attack_mob/proc/monkey_attack(datum/ai_controller/controller, mob/living/target, seconds_per_tick, disarm) diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm index 29250d16125..ca8acb49040 100644 --- a/code/datums/ai/movement/_ai_movement.dm +++ b/code/datums/ai/movement/_ai_movement.dm @@ -17,7 +17,7 @@ moving_controllers -= controller // We got deleted as we finished an action if(!QDELETED(controller.pawn)) - DSmove_manager.stop_looping(controller.pawn, SSai_movement) + GLOB.move_manager.stop_looping(controller.pawn, SSai_movement) /datum/ai_movement/proc/increment_pathing_failures(datum/ai_controller/controller) controller.consecutive_pathing_attempts++ diff --git a/code/datums/ai/movement/ai_movement_basic_avoidance.dm b/code/datums/ai/movement/ai_movement_basic_avoidance.dm index bcfe6833a8d..ac231e075ed 100644 --- a/code/datums/ai/movement/ai_movement_basic_avoidance.dm +++ b/code/datums/ai/movement/ai_movement_basic_avoidance.dm @@ -9,7 +9,7 @@ var/atom/movable/moving = controller.pawn var/min_dist = controller.blackboard[BB_CURRENT_MIN_MOVE_DISTANCE] var/delay = controller.movement_delay - var/datum/move_loop/loop = DSmove_manager.move_to(moving, current_movement_target, min_dist, delay, flags = move_flags, subsystem = SSai_movement, extra_info = controller) + var/datum/move_loop/loop = GLOB.move_manager.move_to(moving, current_movement_target, min_dist, delay, flags = move_flags, subsystem = SSai_movement, extra_info = controller) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) diff --git a/code/datums/ai/movement/ai_movement_complete_stop.dm b/code/datums/ai/movement/ai_movement_complete_stop.dm index 31309256a67..2b39e162719 100644 --- a/code/datums/ai/movement/ai_movement_complete_stop.dm +++ b/code/datums/ai/movement/ai_movement_complete_stop.dm @@ -8,7 +8,7 @@ var/stopping_time = controller.blackboard[BB_STATIONARY_SECONDS] var/delay_time = (stopping_time * 0.5) // no real reason to fire any more often than this really // assume that the current_movement_target is our location - var/datum/move_loop/loop = DSmove_manager.freeze(moving, current_movement_target, delay = delay_time, timeout = stopping_time, subsystem = SSai_movement, extra_info = controller) + var/datum/move_loop/loop = GLOB.move_manager.freeze(moving, current_movement_target, delay = delay_time, timeout = stopping_time, subsystem = SSai_movement, extra_info = controller) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) /datum/ai_movement/complete_stop/allowed_to_move(datum/move_loop/source) diff --git a/code/datums/ai/movement/ai_movement_dumb.dm b/code/datums/ai/movement/ai_movement_dumb.dm index a64a7539eec..2de85046a94 100644 --- a/code/datums/ai/movement/ai_movement_dumb.dm +++ b/code/datums/ai/movement/ai_movement_dumb.dm @@ -7,7 +7,7 @@ . = ..() var/atom/movable/moving = controller.pawn var/delay = controller.movement_delay - var/datum/move_loop/loop = DSmove_manager.move_towards_legacy(moving, current_movement_target, delay, subsystem = SSai_movement, extra_info = controller) + var/datum/move_loop/loop = GLOB.move_manager.move_towards_legacy(moving, current_movement_target, delay, subsystem = SSai_movement, extra_info = controller) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) diff --git a/code/datums/ai/movement/ai_movement_jps.dm b/code/datums/ai/movement/ai_movement_jps.dm index ac16b0aaa23..d6f37c2a956 100644 --- a/code/datums/ai/movement/ai_movement_jps.dm +++ b/code/datums/ai/movement/ai_movement_jps.dm @@ -12,7 +12,7 @@ var/atom/movable/moving = controller.pawn var/delay = controller.movement_delay - var/datum/move_loop/has_target/jps/loop = DSmove_manager.jps_move(moving, + var/datum/move_loop/has_target/jps/loop = GLOB.move_manager.jps_move(moving, current_movement_target, delay, repath_delay = 0.5 SECONDS, diff --git a/code/datums/systems/ds/communications.dm b/code/datums/communications.dm similarity index 86% rename from code/datums/systems/ds/communications.dm rename to code/datums/communications.dm index 7c9cee61509..79f660a4cfa 100644 --- a/code/datums/systems/ds/communications.dm +++ b/code/datums/communications.dm @@ -2,9 +2,9 @@ #define COMMUNICATION_COOLDOWN_AI (30 SECONDS) #define COMMUNICATION_COOLDOWN_MEETING (5 MINUTES) -DATASYSTEM_DEF(communications) - name = "Communications" +GLOBAL_DATUM_INIT(communications_controller, /datum/communciations_controller, new) +/datum/communciations_controller COOLDOWN_DECLARE(silicon_message_cooldown) COOLDOWN_DECLARE(nonsilicon_message_cooldown) @@ -20,7 +20,7 @@ DATASYSTEM_DEF(communications) /// The location where the special xenomorph egg was planted var/area/captivity_area -/datum/system/communications/proc/can_announce(mob/living/user, is_silicon) +/datum/communciations_controller/proc/can_announce(mob/living/user, is_silicon) if(is_silicon && COOLDOWN_FINISHED(src, silicon_message_cooldown)) return TRUE else if(!is_silicon && COOLDOWN_FINISHED(src, nonsilicon_message_cooldown)) @@ -28,7 +28,7 @@ DATASYSTEM_DEF(communications) else return FALSE -/datum/system/communications/proc/make_announcement(mob/living/user, is_silicon, input, syndicate, list/players) +/datum/communciations_controller/proc/make_announcement(mob/living/user, is_silicon, input, syndicate, list/players) if(!can_announce(user, is_silicon)) return FALSE if(is_silicon) @@ -44,7 +44,7 @@ DATASYSTEM_DEF(communications) user.log_talk(input, LOG_SAY, tag="priority announcement") message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.") -/datum/system/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE) +/datum/communciations_controller/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE) for(var/obj/machinery/computer/communications/C in GLOB.shuttle_caller_list) if(!(C.machine_stat & (BROKEN|NOPOWER)) && is_station_level(C.z)) if(unique) diff --git a/code/datums/components/conveyor_movement.dm b/code/datums/components/conveyor_movement.dm index 61a0066ff4a..dd16e6874ea 100644 --- a/code/datums/components/conveyor_movement.dm +++ b/code/datums/components/conveyor_movement.dm @@ -15,7 +15,7 @@ if(!start_delay) start_delay = speed var/atom/movable/moving_parent = parent - var/datum/move_loop/loop = DSmove_manager.move(moving_parent, direction, delay = start_delay, subsystem = SSconveyors, flags=MOVEMENT_LOOP_IGNORE_PRIORITY|MOVEMENT_LOOP_OUTSIDE_CONTROL) + var/datum/move_loop/loop = GLOB.move_manager.move(moving_parent, direction, delay = start_delay, subsystem = SSconveyors, flags=MOVEMENT_LOOP_IGNORE_PRIORITY|MOVEMENT_LOOP_OUTSIDE_CONTROL) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(should_move)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(loop_ended)) diff --git a/code/datums/components/drift.dm b/code/datums/components/drift.dm index f8ad46e3ec3..7fba50d3151 100644 --- a/code/datums/components/drift.dm +++ b/code/datums/components/drift.dm @@ -23,7 +23,7 @@ if(instant) flags |= MOVEMENT_LOOP_START_FAST var/atom/movable/movable_parent = parent - drifting_loop = DSmove_manager.move(moving = parent, direction = direction, delay = movable_parent.inertia_move_delay, subsystem = SSspacedrift, priority = MOVEMENT_SPACE_PRIORITY, flags = flags) + drifting_loop = GLOB.move_manager.move(moving = parent, direction = direction, delay = movable_parent.inertia_move_delay, subsystem = SSspacedrift, priority = MOVEMENT_SPACE_PRIORITY, flags = flags) if(!drifting_loop) //Really want to qdel here but can't return COMPONENT_INCOMPATIBLE diff --git a/code/datums/components/force_move.dm b/code/datums/components/force_move.dm index 6c1c1e38e5f..62fe26d71f7 100644 --- a/code/datums/components/force_move.dm +++ b/code/datums/components/force_move.dm @@ -9,7 +9,7 @@ var/mob/mob_parent = parent var/dist = get_dist(mob_parent, target) - var/datum/move_loop/loop = DSmove_manager.move_towards(mob_parent, target, delay = 1, timeout = dist) + var/datum/move_loop/loop = GLOB.move_manager.move_towards(mob_parent, target, delay = 1, timeout = dist) RegisterSignal(mob_parent, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE, PROC_REF(stop_move)) RegisterSignal(mob_parent, COMSIG_ATOM_PRE_PRESSURE_PUSH, PROC_REF(stop_pressure)) if(spin) diff --git a/code/datums/components/jousting.dm b/code/datums/components/jousting.dm index 56b65c6f758..9c3dab3c8fb 100644 --- a/code/datums/components/jousting.dm +++ b/code/datums/components/jousting.dm @@ -44,7 +44,7 @@ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(on_attack)) + RegisterSignal(parent, COMSIG_ITEM_POST_ATTACK, PROC_REF(on_successful_attack)) RegisterSignal(parent, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform)) /datum/component/jousting/UnregisterFromParent() @@ -53,7 +53,7 @@ COMSIG_ATOM_EXAMINE, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, - COMSIG_ITEM_ATTACK, + COMSIG_ITEM_POST_ATTACK, COMSIG_TRANSFORMING_ON_TRANSFORM, )) @@ -94,7 +94,7 @@ * We deduct the minimum tile charge from the current tile charge to get what will actually be buffed * So your charge will only get benefits from each extra tile after the minimum (and before the maximum). */ -/datum/component/jousting/proc/on_attack(datum/source, mob/living/target, mob/user) +/datum/component/jousting/proc/on_successful_attack(datum/source, mob/living/target, mob/user) SIGNAL_HANDLER if(user != current_holder || !user.buckled) return diff --git a/code/datums/components/material/remote_materials.dm b/code/datums/components/material/remote_materials.dm index 695a02bcb96..568b018e58b 100644 --- a/code/datums/components/material/remote_materials.dm +++ b/code/datums/components/material/remote_materials.dm @@ -86,7 +86,7 @@ handles linking back and forth. mat_container = parent.AddComponent( \ /datum/component/material_container, \ - DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ local_size, \ mat_container_flags, \ container_signals = mat_container_signals, \ diff --git a/code/datums/components/shuttle_cling.dm b/code/datums/components/shuttle_cling.dm index 724060c9cbe..cef7c1f94dd 100644 --- a/code/datums/components/shuttle_cling.dm +++ b/code/datums/components/shuttle_cling.dm @@ -51,7 +51,7 @@ update_state(parent) //otherwise we'll get moved 1 tile before we can correct ourselves, which isnt super bad but just looks jank /datum/component/shuttle_cling/proc/initialize_loop() - hyperloop = DSmove_manager.move(moving = parent, direction = direction, delay = not_clinging_move_delay, subsystem = SShyperspace_drift, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_NO_DIR_UPDATE|MOVEMENT_LOOP_OUTSIDE_CONTROL) + hyperloop = GLOB.move_manager.move(moving = parent, direction = direction, delay = not_clinging_move_delay, subsystem = SShyperspace_drift, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_NO_DIR_UPDATE|MOVEMENT_LOOP_OUTSIDE_CONTROL) update_state() /datum/component/shuttle_cling/proc/clear_loop() diff --git a/code/datums/components/singularity.dm b/code/datums/components/singularity.dm index 56a6723f21f..14aaedff717 100644 --- a/code/datums/components/singularity.dm +++ b/code/datums/components/singularity.dm @@ -286,7 +286,7 @@ if (STAGE_ONE) steps = 1 if (STAGE_TWO) - steps = 3//Yes this is right + steps = 2 if (STAGE_THREE) steps = 3 if (STAGE_FOUR) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 163de4867d5..d62414a862b 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -266,7 +266,7 @@ /datum/component/uplink/ui_assets(mob/user) return list( - get_asset_datum(/datum/asset/json/uplink) + get_asset_datum(/datum/asset/json/uplink), ) /datum/component/uplink/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) diff --git a/code/datums/elements/backblast.dm b/code/datums/elements/backblast.dm index 8952afbfeaa..f5e73977159 100644 --- a/code/datums/elements/backblast.dm +++ b/code/datums/elements/backblast.dm @@ -38,6 +38,9 @@ /// For firing an actual backblast pellet /datum/element/backblast/proc/pew(obj/item/gun/weapon, mob/living/user, atom/target) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + return + var/turf/origin = get_turf(weapon) var/backblast_angle = get_angle(target, origin) explosion(weapon, devastation_range = dev_range, heavy_impact_range = heavy_range, light_impact_range = light_range, flame_range = flame_range, adminlog = FALSE, protect_epicenter = TRUE, explosion_direction = backblast_angle, explosion_arc = blast_angle) diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 9d6b8674728..da5a15b8d31 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -10,7 +10,7 @@ Simple datum which is instanced once per type and is used for every object of sa var/name = "material" /// A short description of the material. Not used anywhere, yet... var/desc = "its..stuff." - /// What the material is indexed by in the DSmaterials.materials list. Defaults to the type of the material. + /// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material. var/id ///Base color of the material, is used for greyscale. Item isn't changed in color if this is null. @@ -23,7 +23,7 @@ Simple datum which is instanced once per type and is used for every object of sa ///Starlight color of the material ///This is the color of light it'll emit if its turf is transparent and over space. Defaults to COLOR_STARLIGHT if not set var/starlight_color - ///Bitflags that influence how DSmaterials handles this material. + ///Bitflags that influence how SSmaterials handles this material. var/init_flags = MATERIAL_INIT_MAPLOAD ///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for var/list/categories = list() diff --git a/code/datums/systems/ds/move_handler.dm b/code/datums/move_manager.dm similarity index 92% rename from code/datums/systems/ds/move_handler.dm rename to code/datums/move_manager.dm index dc3458627ef..23ddcbecdb7 100644 --- a/code/datums/systems/ds/move_handler.dm +++ b/code/datums/move_manager.dm @@ -17,14 +17,15 @@ * * You can find the logic for this control in this file * - * Specifics of how different loops operate can be found in the movement_types.dm file, alongside the [add to loop][/datum/system/move_manager/proc/add_to_loop] helper procs that use them + * Specifics of how different loops operate can be found in the movement_types.dm file, alongside the [add to loop][/datum/move_manager/proc/add_to_loop] helper procs that use them * **/ -DATASYSTEM_DEF(move_manager) - name = "Movement Handler" +/datum/move_manager + +GLOBAL_DATUM_INIT(move_manager, /datum/move_manager, new) ///Adds a movable thing to a movement subsystem. Returns TRUE if it all worked, FALSE if it failed somehow -/datum/system/move_manager/proc/add_to_loop(atom/movable/thing_to_add, datum/controller/subsystem/movement/subsystem = SSmovement, datum/move_loop/loop_type, priority = MOVEMENT_DEFAULT_PRIORITY, flags, datum/extra_info) +/datum/move_manager/proc/add_to_loop(atom/movable/thing_to_add, datum/controller/subsystem/movement/subsystem = SSmovement, datum/move_loop/loop_type, priority = MOVEMENT_DEFAULT_PRIORITY, flags, datum/extra_info) var/datum/movement_packet/our_data = thing_to_add.move_packet if(!our_data) our_data = new(thing_to_add) @@ -33,7 +34,7 @@ DATASYSTEM_DEF(move_manager) return our_data.add_loop(arglist(arguments)) ///Returns the subsystem's loop if we're processing on it, null otherwise -/datum/system/move_manager/proc/processing_on(atom/movable/packet_owner, datum/controller/subsystem/movement/subsystem) +/datum/move_manager/proc/processing_on(atom/movable/packet_owner, datum/controller/subsystem/movement/subsystem) var/datum/movement_packet/packet = packet_owner.move_packet if(!packet) return diff --git a/code/datums/proximity_monitor/fields/timestop.dm b/code/datums/proximity_monitor/fields/timestop.dm index 91e13c79142..79996dee2dd 100644 --- a/code/datums/proximity_monitor/fields/timestop.dm +++ b/code/datums/proximity_monitor/fields/timestop.dm @@ -214,7 +214,7 @@ frozen_mobs += victim victim.Stun(20, ignore_canstun = TRUE) victim.add_traits(list(TRAIT_MUTE, TRAIT_EMOTEMUTE), TIMESTOP_TRAIT) - DSmove_manager.stop_looping(victim) //stops them mid pathing even if they're stunimmune //This is really dumb + GLOB.move_manager.stop_looping(victim) //stops them mid pathing even if they're stunimmune //This is really dumb if(isanimal(victim)) var/mob/living/simple_animal/animal_victim = victim animal_victim.toggle_ai(AI_OFF) diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index cc2c49f1b86..22d5fb04339 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -304,6 +304,15 @@ weight_multiplier = 3 max_occurrences_modifier = 10 //lotta cows +/datum/station_trait/bright_day + name = "Bright Day" + report_message = "The stars shine bright and the clouds are scarcer than usual. It's a bright day here on the Ice Moon's surface." + trait_type = STATION_TRAIT_POSITIVE + weight = 5 + show_in_report = TRUE + trait_flags = STATION_TRAIT_PLANETARY + trait_to_give = STATION_TRAIT_BRIGHT_DAY + /datum/station_trait/shuttle_sale name = "Shuttle Firesale" report_message = "The Nanotrasen Emergency Dispatch team is celebrating a record number of shuttle calls in the recent quarter. Some of your emergency shuttle options have been discounted!" diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index b1bacfbceab..9b661688258 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -113,6 +113,10 @@ /// If TRUE, shows the contents of the storage in open_storage var/display_contents = TRUE + /// Switch this off if you want to handle click_alt in the parent atom + var/click_alt_open = TRUE + + /datum/storage/New( atom/parent, max_slots = src.max_slots, @@ -198,7 +202,7 @@ RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(on_preattack)) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(mass_empty)) - RegisterSignals(parent, list(COMSIG_CLICK_ALT, COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_ATTACK_HAND_SECONDARY), PROC_REF(open_storage_on_signal)) + RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_ATTACK_HAND_SECONDARY), PROC_REF(open_storage_on_signal)) RegisterSignal(parent, COMSIG_ATOM_ATTACKBY_SECONDARY, PROC_REF(open_storage_attackby_secondary)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(close_distance)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(update_actions)) @@ -208,6 +212,7 @@ RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, PROC_REF(on_deconstruct)) RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) RegisterSignal(parent, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(contents_changed_w_class)) + RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_click_alt)) /** * Sets where items are physically being stored in the case it shouldn't be on the parent. @@ -919,6 +924,17 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) if(display_contents) return COMPONENT_NO_AFTERATTACK + +/// Alt click on the storage item. Default: Open the storage. +/datum/storage/proc/on_click_alt(datum/source, mob/user) + SIGNAL_HANDLER + + if(!click_alt_open) + return + + return open_storage_on_signal(source, user) + + /// Opens the storage to the mob, showing them the contents to their UI. /datum/storage/proc/open_storage(mob/to_show) if(isobserver(to_show)) diff --git a/code/datums/storage/subtypes/pockets.dm b/code/datums/storage/subtypes/pockets.dm index 5b1eceff8e9..b07635a6773 100644 --- a/code/datums/storage/subtypes/pockets.dm +++ b/code/datums/storage/subtypes/pockets.dm @@ -45,6 +45,7 @@ /datum/storage/pockets/small/fedora/detective attack_hand_interact = TRUE // so the detectives would discover pockets in their hats + click_alt_open = FALSE /datum/storage/pockets/chefhat attack_hand_interact = TRUE diff --git a/code/datums/systems/_system.dm b/code/datums/systems/_system.dm deleted file mode 100644 index fe3271048ab..00000000000 --- a/code/datums/systems/_system.dm +++ /dev/null @@ -1,16 +0,0 @@ -#define NEW_DS_GLOBAL(varname) if(varname != src){if(istype(varname)){qdel(varname);}varname = src;} - -#define DATASYSTEM_DEF(X) GLOBAL_REAL(DS##X, /datum/system/##X);\ -/datum/system/##X/New(){\ - NEW_DS_GLOBAL(DS##X);\ -}\ -/datum/system/##X - - -/** - * Global systems which are distinct from subsystems in that they do not process by the MC. - * Data systems or "DS" are used to store round information and procs to interface with that data, if needed. - */ -/datum/system - /// Name of the system - var/name = "Datum System" diff --git a/code/datums/systems/ds/battle_royale.dm b/code/datums/systems/ds/battle_royale.dm deleted file mode 100644 index 1cdc7358a56..00000000000 --- a/code/datums/systems/ds/battle_royale.dm +++ /dev/null @@ -1,229 +0,0 @@ -/// Global list of areas which are considered to be inside the same department for our purposes -GLOBAL_LIST_INIT(battle_royale_regions, list( - "Medical Bay" = list( - /area/station/command/heads_quarters/cmo, - /area/station/medical, - /area/station/security/checkpoint/medical, - ), - "Research Division" = list( - /area/station/command/heads_quarters/rd, - /area/station/security/checkpoint/science, - /area/station/science, - ), - "Engineering Bay" = list( - /area/station/command/heads_quarters/ce, - /area/station/engineering, - /area/station/maintenance/disposal/incinerator, - /area/station/security/checkpoint/engineering, - ), - "Cargo Bay" = list( - /area/station/cargo, - /area/station/command/heads_quarters/qm, - /area/station/security/checkpoint/supply, - ), -)) - -/// Basically just exists to hold references to datums so that they don't GC -DATASYSTEM_DEF(battle_royale) - name = "Battle Royale" - /// List of battle royale datums currently running - var/list/active_battles - -/// Start a new battle royale using a passed list of implants -/datum/system/battle_royale/proc/start_battle(list/competitors) - var/datum/battle_royale_controller/controller = new() - if (!controller.start(competitors)) - return FALSE - LAZYADD(active_battles, controller) - if (LAZYLEN(active_battles) == 1) - start_broadcasting_network(BATTLE_ROYALE_CAMERA_NET) - RegisterSignal(controller, COMSIG_QDELETING, PROC_REF(battle_ended)) - return TRUE - -/// Drop reference when it kills itself -/datum/system/battle_royale/proc/battle_ended(datum/source) - SIGNAL_HANDLER - LAZYREMOVE(active_battles, source) - if (!LAZYLEN(active_battles)) - stop_broadcasting_network(BATTLE_ROYALE_CAMERA_NET) - - -/// Datum which controls the conflict -/datum/battle_royale_controller - /// Where is our battle taking place? - var/chosen_area - /// Is the battle currently in progress? - var/battle_running = TRUE - /// Should we let everyone know that someone has died? - var/announce_deaths = TRUE - /// List of implants involved - var/list/contestant_implants = list() - /// Ways to describe that someone has died - var/static/list/euphemisms = list( - "cashed their last paycheque.", - "didn't make it...", - "didn't make the cut.", - "had their head blown clean off!", - "has been killed!", - "has failed the challenge!", - "has passed away.", - "has died.", - "is in a better place now.", - "isn't going to be clocking in tomorrow!", - "just flatlined.", - "isn't today's winner.", - "seems to have exploded!", - "was just murdered on live tv!", - "won't be making it to retirement.", - "won't be getting back up after that one.", - ) - /// Ways to tell people not to salt in deadchat, surely effective - var/static/list/condolences = list( - "Better luck next time!", - "But stay tuned, there's still everything to play for!", - "Did you catch who did it?", - "It looked like that one really hurt...", - "Let's get that one on action replay!", - "Let's have a moment of silence, please.", - "Let's hope the next one does better.", - "Someone please notify their next of kin.", - "They had a good run.", - "Too bad!", - "What a shame!", - "What an upset!", - "What's going to happen next?", - "Who could have seen that coming?", - "Who will be next?", - ) - -/datum/battle_royale_controller/Destroy(force) - contestant_implants = null - return ..() - -/// Start a battle royale with the list of provided implants -/datum/battle_royale_controller/proc/start(list/implants, battle_time = 10 MINUTES) - chosen_area = pick(GLOB.battle_royale_regions) - for (var/obj/item/implant/explosive/battle_royale/contestant_implant in implants) - contestant_implant.start_battle(chosen_area, GLOB.battle_royale_regions[chosen_area]) - if (isnull(contestant_implant)) - continue // Might have exploded if it was removed from a person - RegisterSignal(contestant_implant, COMSIG_QDELETING, PROC_REF(implant_destroyed)) - contestant_implants |= contestant_implant - - if (length(contestant_implants) <= 1) - return FALSE // Well there's not much point is there - - priority_announce( - text = "Congratulations [station_name()], you have been chosen as the next site of the Rumble Royale! \n\ - Viewers across the sector will watch our [convert_integer_to_words(length(contestant_implants))] lucky contestants battle their way into your [chosen_area] and fight until only one is left standing! \n\ - If they don't make it in five minutes, they'll be disqualified. If you see one of our players struggling to get in, do lend them a hand... or don't, if you can live with the consequences! \n\ - As a gesture of gratitude, we will be providing our premium broadcast to your entertainment monitors at no cost so that you can watch the excitement. \n\ - Bystanders are advised not to intervene... but if you do, make it look good for the camera!", - title = "Rumble Royale Beginning", - sound = 'sound/machines/alarm.ogg', - has_important_message = TRUE, - sender_override = "Rumble Royale Pirate Broadcast Station", - color_override = "red", - ) - - for (var/obj/item/implant/explosive/battle_royale/contestant_implant as anything in contestant_implants) - contestant_implant.announce() - addtimer(CALLBACK(src, PROC_REF(limit_area)), battle_time / 2, TIMER_DELETE_ME) - addtimer(CALLBACK(src, PROC_REF(finish)), battle_time, TIMER_DELETE_ME) - return TRUE - -/// An implant was destroyed, hopefully because it exploded. Count how many competitors remain. -/datum/battle_royale_controller/proc/implant_destroyed(obj/item/implant/implant) - SIGNAL_HANDLER - contestant_implants -= implant - if (!battle_running) - return - - if (length(contestant_implants) <= 1) - announce_winner(implant) - else if (announce_deaths) - var/message = "" - if (isnull(implant.imp_in)) - message = "Looks like someone removed and destroyed their implant, that's cheating!" - else - message = "[implant.imp_in.real_name] [pick(euphemisms)] [pick(condolences)]" - priority_announce( - text = message, - title = "Rumble Royale Casualty Report", - sound = 'sound/misc/notice1.ogg', - has_important_message = TRUE, - sender_override = "Rumble Royale Pirate Broadcast Station", - color_override = "red", - ) - -/// There's only one person left, we have a winner! -/datum/battle_royale_controller/proc/announce_winner(obj/item/implant/losing_implant) - battle_running = FALSE - if (length(contestant_implants) > 1) - return - - var/message = "" - var/mob/living/loser = losing_implant.imp_in - var/obj/item/implant/winning_implant = pop(contestant_implants) - var/mob/living/winner = winning_implant?.imp_in - - if (isnull(winner) && isnull(loser)) - message = "Somehow, it seems like there's no winner tonight. What a disappointment!" - else - var/loser_text = isnull(loser) ? "With the disqualification of the other remaining contestant" : "With the death of [loser.real_name]" - var/winner_text = isnull(winner) ? "we must sadly announce that the would-be winner has also been disqualified. Such bad showmanship!" : "only [winner.real_name] remains. Congratulations, we have a winner!" - message = "[loser_text], [winner_text]" - - if (!isnull(winner)) - podspawn(list( - "target" = get_turf(winner), - "style" = STYLE_SYNDICATE, - "spawn" = /obj/item/food/roast_dinner, - )) - - priority_announce( - text = message, - title = "Rumble Royale Winner", - sound = 'sound/misc/notice1.ogg', - has_important_message = TRUE, - sender_override = "Rumble Royale Pirate Broadcast Station", - color_override = "red", - ) - - qdel(winning_implant) // You get to live! - winner?.mind?.remove_antag_datum(/datum/antagonist/survivalist/battle_royale) - qdel(src) - -/// Called halfway through the battle, if you've not made it to the designated battle zone we kill you -/datum/battle_royale_controller/proc/limit_area() - priority_announce( - text = "We're halfway done folks! And bad news to anyone who hasn't made it to the [chosen_area]... you're out!", - title = "Rumble Royale Update", - sound = 'sound/misc/notice1.ogg', - has_important_message = TRUE, - sender_override = "Rumble Royale Pirate Broadcast Station", - color_override = "red", - ) - - for (var/obj/item/implant/explosive/battle_royale/contestant_implant as anything in contestant_implants) - contestant_implant.limit_areas() - -/// Well you're out of time, bad luck -/datum/battle_royale_controller/proc/finish() - battle_running = FALSE - - priority_announce( - text = "Sorry remaining contestants, your time is up. \ - We're sorry to announce that this edition of Royal Rumble has no winner. \n\ - Better luck next time!", - title = "Rumble Royale Concluded", - sound = 'sound/misc/notice1.ogg', - has_important_message = TRUE, - sender_override = "Rumble Royale Pirate Broadcast Station", - color_override = "red", - ) - - for (var/obj/item/implant/explosive/battle_royale/contestant_implant as anything in contestant_implants) - contestant_implant.explode() - - qdel(src) diff --git a/code/datums/systems/manager.dm b/code/datums/systems/manager.dm deleted file mode 100644 index 0d5fdb8b839..00000000000 --- a/code/datums/systems/manager.dm +++ /dev/null @@ -1,14 +0,0 @@ -// See initialization order in /code/game/world.dm -GLOBAL_REAL(SysMgr, /datum/system_manager) - - -/** - * Initializes all data systems and keeps track of them. - */ -/datum/system_manager - /// List of managed data systems, post initialization. - var/list/datum/system/managed = list() - - -/datum/system_manager/New() - init_subtypes(/datum/system, managed) diff --git a/code/datums/votes/_vote_datum.dm b/code/datums/votes/_vote_datum.dm index 3f821a7129a..76833f73ff5 100644 --- a/code/datums/votes/_vote_datum.dm +++ b/code/datums/votes/_vote_datum.dm @@ -15,19 +15,8 @@ var/list/default_choices /// Does the name of this vote contain the word "vote"? var/contains_vote_in_name = FALSE - /// What message do we want to pass to the player-side vote panel as a tooltip? - var/message = "Click to initiate a vote." - - // Internal values used when tracking ongoing votes. - // Don't mess with these, change the above values / override procs for subtypes. - /// An assoc list of [all choices] to [number of votes in the current running vote]. - var/list/choices = list() - /// A assoc list of [ckey] to [what they voted for in the current running vote]. - var/list/choices_by_ckey = list() - /// The world time this vote was started. - var/started_time - /// The time remaining in this vote's run. - var/time_remaining + /// What message do we show as the tooltip of this vote if the vote can be initiated? + var/default_message = "Click to initiate a vote." /// The counting method we use for votes. var/count_method = VOTE_COUNT_METHOD_SINGLE /// The method for selecting a winner. @@ -35,6 +24,17 @@ /// Should we show details about the number of votes submitted for each option? var/display_statistics = TRUE + // Internal values used when tracking ongoing votes. + // Don't mess with these, change the above values / override procs for subtypes. + /// An assoc list of [all choices] to [number of votes in the current running vote]. + VAR_FINAL/list/choices = list() + /// A assoc list of [ckey] to [what they voted for in the current running vote]. + VAR_FINAL/list/choices_by_ckey = list() + /// The world time this vote was started. + VAR_FINAL/started_time = -1 + /// The time remaining in this vote's run. + VAR_FINAL/time_remaining = -1 + /** * Used to determine if this vote is a possible * vote type for the vote subsystem. @@ -55,14 +55,13 @@ choices.Cut() choices_by_ckey.Cut() started_time = null - time_remaining = null + time_remaining = -1 /** * If this vote has a config associated, toggles it between enabled and disabled. - * Returns TRUE on a successful toggle, FALSE otherwise */ -/datum/vote/proc/toggle_votable(mob/toggler) - return FALSE +/datum/vote/proc/toggle_votable() + return /** * If this vote has a config associated, returns its value (True or False, usually). @@ -74,20 +73,18 @@ /** * Checks if the passed mob can initiate this vote. * - * Return TRUE if the mob can begin the vote, allowing anyone to actually vote on it. - * Return FALSE if the mob cannot initiate the vote. + * * forced - if being invoked by someone who is an admin + * + * Return VOTE_AVAILABLE if the mob can initiate the vote. + * Return a string with the reason why the mob can't initiate the vote. */ -/datum/vote/proc/can_be_initiated(mob/by_who, forced = FALSE) +/datum/vote/proc/can_be_initiated(forced = FALSE) SHOULD_CALL_PARENT(TRUE) - if(started_time) - var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay)) - if(next_allowed_time > world.time && !forced) - message = "A vote was initiated recently. You must wait [DisplayTimeText(next_allowed_time - world.time)] before a new vote can be started!" - return FALSE + if(!forced && !is_config_enabled()) + return "This vote is currently disabled by the server configuration." - message = initial(message) - return TRUE + return VOTE_AVAILABLE /** * Called prior to the vote being initiated. diff --git a/code/datums/votes/custom_vote.dm b/code/datums/votes/custom_vote.dm index d67eb0281c6..78eb6d3b876 100644 --- a/code/datums/votes/custom_vote.dm +++ b/code/datums/votes/custom_vote.dm @@ -1,14 +1,9 @@ /// The max amount of options someone can have in a custom vote. #define MAX_CUSTOM_VOTE_OPTIONS 10 -/datum/vote/custom_vote/single - name = "Custom Standard" - message = "Click here to start a custom vote (one selection per voter)" - -/datum/vote/custom_vote/multi - name = "Custom Multi" - message = "Click here to start a custom multi vote (multiple selections per voter)" - count_method = VOTE_COUNT_METHOD_MULTI +/datum/vote/custom_vote + name = "Custom" + default_message = "Click here to start a custom vote." // Custom votes ares always accessible. /datum/vote/custom_vote/is_accessible_vote() @@ -17,23 +12,45 @@ /datum/vote/custom_vote/reset() default_choices = null override_question = null + count_method = VOTE_COUNT_METHOD_SINGLE return ..() -/datum/vote/custom_vote/can_be_initiated(mob/by_who, forced = FALSE) +/datum/vote/custom_vote/can_be_initiated(forced) . = ..() - if(!.) - return FALSE + if(. != VOTE_AVAILABLE) + return . + if(forced) + return . // Custom votes can only be created if they're forced to be made. // (Either an admin makes it, or otherwise.) - return forced + return "Only admins can create custom votes." /datum/vote/custom_vote/create_vote(mob/vote_creator) + var/custom_count_method = tgui_input_list( + user = vote_creator, + message = "Single or multiple choice?", + title = "Choice Method", + items = list("Single", "Multiple"), + default = "Single", + ) + switch(custom_count_method) + if("Single") + count_method = VOTE_COUNT_METHOD_SINGLE + if("Multiple") + count_method = VOTE_COUNT_METHOD_MULTI + if(null) + return FALSE + else + stack_trace("Got '[custom_count_method]' in create_vote() for custom voting.") + to_chat(vote_creator, span_boldwarning("Unknown choice method. Contact a coder.")) + return FALSE + var/custom_win_method = tgui_input_list( - vote_creator, - "How should the vote winner be determined?", - "Winner Method", - list("Simple", "Weighted Random", "No Winner"), + user = vote_creator, + message = "How should the vote winner be determined?", + title = "Winner Method", + items = list("Simple", "Weighted Random", "No Winner"), default = "Simple", ) switch(custom_win_method) @@ -43,7 +60,10 @@ winner_method = VOTE_WINNER_METHOD_WEIGHTED_RANDOM if("No Winner") winner_method = VOTE_WINNER_METHOD_NONE + if(null) + return FALSE else + stack_trace("Got '[custom_win_method]' in create_vote() for custom voting.") to_chat(vote_creator, span_boldwarning("Unknown winner method. Contact a coder.")) return FALSE @@ -54,7 +74,7 @@ list("Yes", "No"), ) - if(display_stats == null) + if(isnull(display_stats)) return FALSE display_statistics = display_stats == "Yes" @@ -74,6 +94,9 @@ if(!length(default_choices)) return FALSE + // Sanity for all the tgui input stalling we are doing + if(isnull(vote_creator.client?.holder)) + return FALSE return ..() diff --git a/code/datums/votes/map_vote.dm b/code/datums/votes/map_vote.dm index 301af610096..7b1794da93e 100644 --- a/code/datums/votes/map_vote.dm +++ b/code/datums/votes/map_vote.dm @@ -1,6 +1,6 @@ /datum/vote/map_vote name = "Map" - message = "Vote for next round's map!" + default_message = "Vote for next round's map!" count_method = VOTE_COUNT_METHOD_SINGLE winner_method = VOTE_WINNER_METHOD_WEIGHTED_RANDOM display_statistics = FALSE @@ -30,44 +30,26 @@ SSmapping.map_voted = TRUE // voted by not voting, very sad. return FALSE -/datum/vote/map_vote/toggle_votable(mob/toggler) - if(!toggler) - CRASH("[type] wasn't passed a \"toggler\" mob to toggle_votable.") - if(!check_rights_for(toggler.client, R_ADMIN)) - return FALSE - +/datum/vote/map_vote/toggle_votable() CONFIG_SET(flag/allow_vote_map, !CONFIG_GET(flag/allow_vote_map)) - return TRUE /datum/vote/map_vote/is_config_enabled() return CONFIG_GET(flag/allow_vote_map) -/datum/vote/map_vote/can_be_initiated(mob/by_who, forced = FALSE) +/datum/vote/map_vote/can_be_initiated(forced) . = ..() - if(!.) - return FALSE - + if(. != VOTE_AVAILABLE) + return . if(forced) - return TRUE - + return VOTE_AVAILABLE var/number_of_choices = length(check_population()) if(number_of_choices < 2) - message = "There [number_of_choices == 1 ? "is only one map" : "are no maps"] to choose from." - return FALSE - + return "There [number_of_choices == 1 ? "is only one map" : "are no maps"] to choose from." if(SSmapping.map_vote_rocked) - return TRUE - - if(!CONFIG_GET(flag/allow_vote_map)) - message = "Map voting is disabled by server configuration settings." - return FALSE - + return VOTE_AVAILABLE if(SSmapping.map_voted) - message = "The next map has already been selected." - return FALSE - - message = initial(message) - return TRUE + return "The next map has already been selected." + return VOTE_AVAILABLE /// Before we create a vote, remove all maps from our choices that are outside of our population range. /// Note that this can result in zero remaining choices for our vote, which is not ideal (but ultimately okay). diff --git a/code/datums/votes/restart_vote.dm b/code/datums/votes/restart_vote.dm index 987d5b87eb3..3c74d7e518e 100644 --- a/code/datums/votes/restart_vote.dm +++ b/code/datums/votes/restart_vote.dm @@ -7,7 +7,8 @@ CHOICE_RESTART, CHOICE_CONTINUE, ) - message = "Vote to restart the ongoing round." + default_message = "Vote to restart the ongoing round. \ + Only works if there are no non-AFK admins online." /// This proc checks to see if any admins are online for the purposes of this vote to see if it can pass. Returns TRUE if there are valid admins online (Has +SERVER and is not AFK), FALSE otherwise. /datum/vote/restart_vote/proc/admins_present() @@ -19,36 +20,24 @@ return FALSE -/datum/vote/restart_vote/toggle_votable(mob/toggler) - if(!toggler) - CRASH("[type] wasn't passed a \"toggler\" mob to toggle_votable.") - - if(!check_rights_for(toggler.client, R_ADMIN)) - return FALSE - +/datum/vote/restart_vote/toggle_votable() CONFIG_SET(flag/allow_vote_restart, !CONFIG_GET(flag/allow_vote_restart)) - return TRUE /datum/vote/restart_vote/is_config_enabled() return CONFIG_GET(flag/allow_vote_restart) -/datum/vote/restart_vote/can_be_initiated(mob/by_who, forced) +/datum/vote/restart_vote/create_vote(mob/vote_creator) . = ..() if(!.) - return FALSE + return + if(!admins_present()) + return + async_alert_about_admins(vote_creator) - if(!forced && !CONFIG_GET(flag/allow_vote_restart)) - message = "Restart voting is disabled by server configuration settings." - return FALSE - - // We still want players to be able to vote to restart even if valid admins are online. Let's update the message just so that the player is aware of this fact. - // We don't want to lock-out the vote though, so we'll return TRUE. - if(admins_present()) - message = "Regardless of the results of this vote, the round will not automatically restart because an admin is online." - return TRUE - - message = initial(message) - return TRUE +/datum/vote/restart_vote/proc/async_alert_about_admins(mob/vote_creator) + set waitfor = FALSE + tgui_alert(vote_creator, "Note: Regardless of the results of this vote, \ + the round will not automatically restart because an active admin is online.") /datum/vote/restart_vote/get_vote_result(list/non_voters) if(!CONFIG_GET(flag/default_no_vote)) diff --git a/code/datums/votes/rock_the_vote.dm b/code/datums/votes/rock_the_vote.dm index 6cffeb5ad67..6c7ac4ff257 100644 --- a/code/datums/votes/rock_the_vote.dm +++ b/code/datums/votes/rock_the_vote.dm @@ -10,58 +10,40 @@ CHOICE_TO_ROCK, CHOICE_NOT_TO_ROCK, ) - message = "Override the current map vote." + default_message = "Override the current map vote." /// The number of times we have rocked the vote thus far. var/rocking_votes = 0 -/datum/vote/rock_the_vote/toggle_votable(mob/toggler) - if(!toggler) - CRASH("[type] wasn't passed a \"toggler\" mob to toggle_votable.") - if(!check_rights_for(toggler.client, R_ADMIN)) - return FALSE - +/datum/vote/rock_the_vote/toggle_votable() CONFIG_SET(flag/allow_rock_the_vote, !CONFIG_GET(flag/allow_rock_the_vote)) - return TRUE /datum/vote/rock_the_vote/is_config_enabled() return CONFIG_GET(flag/allow_rock_the_vote) -/datum/vote/rock_the_vote/can_be_initiated(mob/by_who, forced) +/datum/vote/rock_the_vote/can_be_initiated(forced) . = ..() - - if(!.) - return FALSE - - if(!forced && !CONFIG_GET(flag/allow_rock_the_vote)) - message = "Rocking the vote is disabled by this server's configuration settings." - return FALSE + if(. != VOTE_AVAILABLE) + return . if(SSticker.current_state == GAME_STATE_FINISHED) - message = "The game is finished, no map votes can be initiated." - return FALSE + return "The game is finished, no map votes can be initiated." if(rocking_votes >= CONFIG_GET(number/max_rocking_votes)) - message = "The maximum number of times to rock the vote has been reached." - return FALSE + return "The maximum number of times to rock the vote has been reached." if(SSmapping.map_vote_rocked) - message = "The vote has already been rocked! Initiate a map vote!" - return FALSE + return "The vote has already been rocked! Initiate a map vote!" if(!SSmapping.map_voted) - message = "Rocking the vote is disabled because no map has been voted on yet!" - return FALSE + return "Rocking the vote is disabled because no map has been voted on yet!" if(SSmapping.map_force_chosen) - message = "Rocking the vote is disabled because an admin has forcibly set the map!" - return FALSE + return "Rocking the vote is disabled because an admin has forcibly set the map!" if(EMERGENCY_ESCAPED_OR_ENDGAMED && SSmapping.map_voted) - message = "The emergency shuttle has already left the station and the next map has already been chosen!" - return FALSE + return "The emergency shuttle has already left the station and the next map has already been chosen!" - message = initial(message) - return TRUE + return VOTE_AVAILABLE /datum/vote/rock_the_vote/finalize_vote(winning_option) rocking_votes++ diff --git a/code/game/area/areas/mining.dm b/code/game/area/areas/mining.dm index 1582f7390cf..38855de366f 100644 --- a/code/game/area/areas/mining.dm +++ b/code/game/area/areas/mining.dm @@ -209,6 +209,11 @@ name = "Icemoon Wastes" outdoors = TRUE +/area/icemoon/surface/outdoors/Initialize(mapload) + if(HAS_TRAIT(SSstation, STATION_TRAIT_BRIGHT_DAY)) + base_lighting_alpha = 145 + return ..() + /area/icemoon/surface/outdoors/nospawn // this is the area you use for stuff to not spawn, but if you still want weather. /area/icemoon/surface/outdoors/nospawn/New() // unless you roll forested trait lol diff --git a/code/game/atom/atom_materials.dm b/code/game/atom/atom_materials.dm index deb27140257..345a8486dd6 100644 --- a/code/game/atom/atom_materials.dm +++ b/code/game/atom/atom_materials.dm @@ -23,7 +23,7 @@ var/datum/material/custom_material = GET_MATERIAL_REF(current_material) custom_material.on_applied(src, OPTIMAL_COST(materials[current_material] * multiplier * material_modifier), material_flags) - custom_materials = DSmaterials.FindOrCreateMaterialCombo(materials, multiplier) + custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) /** * Returns the material composition of the atom. diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 02dfa624d35..296a9031ae2 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -32,7 +32,7 @@ /obj/machinery/autolathe/Initialize(mapload) materials = AddComponent( \ /datum/component/material_container, \ - DSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ + SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ 0, \ MATCONTAINER_EXAMINE, \ container_signals = list(COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/autolathe, AfterMaterialInsert)) \ @@ -252,7 +252,7 @@ var/amount_needed = design.materials[material] if(istext(material)) // category var/list/choices = list() - for(var/datum/material/valid_candidate as anything in DSmaterials.materials_by_category[material]) + for(var/datum/material/valid_candidate as anything in SSmaterials.materials_by_category[material]) if(materials.get_material_amount(valid_candidate) < amount_needed) continue choices[valid_candidate.name] = valid_candidate diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm index 1cb7ee1477e..792c1ba22eb 100644 --- a/code/game/machinery/civilian_bounties.dm +++ b/code/game/machinery/civilian_bounties.dm @@ -184,6 +184,9 @@ data["id_bounty_names"] = list(inserted_scan_id.registered_account.bounties[1].name, inserted_scan_id.registered_account.bounties[2].name, inserted_scan_id.registered_account.bounties[3].name) + data["id_bounty_infos"] = list(inserted_scan_id.registered_account.bounties[1].description, + inserted_scan_id.registered_account.bounties[2].description, + inserted_scan_id.registered_account.bounties[3].description) data["id_bounty_values"] = list(inserted_scan_id.registered_account.bounties[1].reward * (CIV_BOUNTY_SPLIT/100), inserted_scan_id.registered_account.bounties[2].reward * (CIV_BOUNTY_SPLIT/100), inserted_scan_id.registered_account.bounties[3].reward * (CIV_BOUNTY_SPLIT/100)) diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm index 63d2808c773..b97dac9e15d 100644 --- a/code/game/machinery/computer/arcade/battle.dm +++ b/code/game/machinery/computer/arcade/battle.dm @@ -531,7 +531,8 @@ return player_turn = TRUE ui_panel = UI_PANEL_WORLD_MAP - player_gold /= 2 + if(player_gold) + player_gold = max(round(player_gold /= 2, 1), 0) return TRUE //they pressed something but it wasn't in the menu, we'll be nice and give them back their turn anyway. player_turn = TRUE diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index f5695dd6284..45bfeb9fcef 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -339,3 +339,12 @@ to_chat(owner, span_notice("You move downwards.")) else to_chat(owner, span_notice("You couldn't move downwards!")) + +/obj/machinery/computer/camera_advanced/human_ai/screwdriver_act(mob/living/user, obj/item/tool) + balloon_alert(user, "repackaging...") + if(!do_after(user, 5 SECONDS, src)) + return ITEM_INTERACT_BLOCKING + tool.play_tool_sound(src, 40) + new /obj/item/secure_camera_console_pod(get_turf(src)) + qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index c71d80ccfba..6117966207c 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -335,7 +335,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) if (!message) return - DScommunications.soft_filtering = FALSE + GLOB.communications_controller.soft_filtering = FALSE var/list/hard_filter_result = is_ic_filtered(message) if(hard_filter_result) tgui_alert(usr, "Your message contains: (\"[hard_filter_result[CHAT_FILTER_INDEX_WORD]]\"), which is not allowed on this server.") @@ -347,7 +347,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) return message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". They may be using a disallowed term for a cross-station message. Increasing delay time to reject.\n\n Message: \"[html_encode(message)]\"") log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". They may be using a disallowed term for a cross-station message. Increasing delay time to reject.\n\n Message: \"[message]\"") - DScommunications.soft_filtering = TRUE + GLOB.communications_controller.soft_filtering = TRUE playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) @@ -358,13 +358,13 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) GLOB.admins, span_adminnotice( \ "CROSS-SECTOR MESSAGE (OUTGOING): [ADMIN_LOOKUPFLW(usr)] is about to send \ - the following message to [destination] (will autoapprove in [DScommunications.soft_filtering ? DisplayTimeText(EXTENDED_CROSS_SECTOR_CANCEL_TIME) : DisplayTimeText(CROSS_SECTOR_CANCEL_TIME)]): \ + the following message to [destination] (will autoapprove in [GLOB.communications_controller.soft_filtering ? DisplayTimeText(EXTENDED_CROSS_SECTOR_CANCEL_TIME) : DisplayTimeText(CROSS_SECTOR_CANCEL_TIME)]): \ REJECT
\ [html_encode(message)]" \ ) ) - send_cross_comms_message_timer = addtimer(CALLBACK(src, PROC_REF(send_cross_comms_message), usr, destination, message), DScommunications.soft_filtering ? EXTENDED_CROSS_SECTOR_CANCEL_TIME : CROSS_SECTOR_CANCEL_TIME, TIMER_STOPPABLE) + send_cross_comms_message_timer = addtimer(CALLBACK(src, PROC_REF(send_cross_comms_message), usr, destination, message), GLOB.communications_controller.soft_filtering ? EXTENDED_CROSS_SECTOR_CANCEL_TIME : CROSS_SECTOR_CANCEL_TIME, TIMER_STOPPABLE) COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) if ("setState") @@ -552,7 +552,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) var/network_name = CONFIG_GET(string/cross_comms_network) if(network_name) payload["network"] = network_name - if(DScommunications.soft_filtering) + if(GLOB.communications_controller.soft_filtering) payload["is_filtered"] = TRUE var/name_to_send = "[CONFIG_GET(string/cross_comms_name)]([station_name()])" //SKYRAT EDIT ADDITION @@ -562,7 +562,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) usr.log_talk(message, LOG_SAY, tag = "message to the other server") message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server\[s].") deadchat_broadcast(" has sent an outgoing message to the other station(s).", "[usr.real_name]", usr, message_type = DEADCHAT_ANNOUNCEMENT) - DScommunications.soft_filtering = FALSE // set it to false at the end of the proc to ensure that everything prior reads as intended + GLOB.communications_controller.soft_filtering = FALSE // set it to false at the end of the proc to ensure that everything prior reads as intended /obj/machinery/computer/communications/ui_data(mob/user) var/list/data = list( @@ -727,7 +727,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) return deltimer(send_cross_comms_message_timer) - DScommunications.soft_filtering = FALSE + GLOB.communications_controller.soft_filtering = FALSE send_cross_comms_message_timer = null log_admin("[key_name(usr)] has cancelled the outgoing cross-comms message.") @@ -800,7 +800,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) /obj/machinery/computer/communications/proc/make_announcement(mob/living/user) var/is_ai = HAS_SILICON_ACCESS(user) - if(!DScommunications.can_announce(user, is_ai)) + if(!GLOB.communications_controller.can_announce(user, is_ai)) to_chat(user, span_alert("Intercomms recharging. Please stand by.")) return var/input = tgui_input_text(user, "Message to announce to the station crew", "Announcement") @@ -821,7 +821,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) ) var/list/players = get_communication_players() - DScommunications.make_announcement(user, is_ai, input, syndicate || (obj_flags & EMAGGED), players) + GLOB.communications_controller.make_announcement(user, is_ai, input, syndicate || (obj_flags & EMAGGED), players) deadchat_broadcast(" made a priority announcement from [span_name("[get_area_name(usr, TRUE)]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT) /obj/machinery/computer/communications/proc/get_communication_players() diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index d2a432688c1..deb8341b0ba 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -35,6 +35,72 @@ /obj/machinery/door/poddoor/get_save_vars() return ..() + NAMEOF(src, id) +/obj/machinery/door/poddoor/examine(mob/user) + . = ..() + if(panel_open) + if(deconstruction == BLASTDOOR_FINISHED) + . += span_notice("The maintenance panel is opened and the electronics could be pried out.") + . += span_notice("\The [src] could be calibrated to a blast door controller ID with a multitool.") + else if(deconstruction == BLASTDOOR_NEEDS_ELECTRONICS) + . += span_notice("The electronics are missing and there are some wires sticking out.") + else if(deconstruction == BLASTDOOR_NEEDS_WIRES) + . += span_notice("The wires have been removed and it's ready to be sliced apart.") + +/obj/machinery/door/poddoor/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(isnull(held_item)) + return NONE + if(deconstruction == BLASTDOOR_NEEDS_WIRES && istype(held_item, /obj/item/stack/cable_coil)) + context[SCREENTIP_CONTEXT_LMB] = "Wire assembly" + return CONTEXTUAL_SCREENTIP_SET + if(deconstruction == BLASTDOOR_NEEDS_ELECTRONICS && istype(held_item, /obj/item/electronics/airlock)) + context[SCREENTIP_CONTEXT_LMB] = "Add electronics" + return CONTEXTUAL_SCREENTIP_SET + //we do not check for special effects like if they can actually perform the action because they will be told they can't do it when they try, + //with feedback on what they have to do in order to do so. + switch(held_item.tool_behaviour) + if(TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "Open panel" + return CONTEXTUAL_SCREENTIP_SET + if(TOOL_MULTITOOL) + context[SCREENTIP_CONTEXT_LMB] = "Calibrate ID" + return CONTEXTUAL_SCREENTIP_SET + if(TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Remove electronics" + return CONTEXTUAL_SCREENTIP_SET + if(TOOL_WIRECUTTER) + context[SCREENTIP_CONTEXT_LMB] = "Remove wires" + return CONTEXTUAL_SCREENTIP_SET + if(TOOL_WELDER) + context[SCREENTIP_CONTEXT_LMB] = "Disassemble" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/door/poddoor/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(deconstruction == BLASTDOOR_NEEDS_WIRES && istype(tool, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = tool + var/datum/crafting_recipe/recipe = locate(recipe_type) in GLOB.crafting_recipes + var/amount_needed = recipe.reqs[/obj/item/stack/cable_coil] + if(coil.get_amount() < amount_needed) + balloon_alert(user, "not enough cable!") + return ITEM_INTERACT_SUCCESS + balloon_alert(user, "adding cables...") + if(!do_after(user, 5 SECONDS, src)) + return ITEM_INTERACT_SUCCESS + coil.use(amount_needed) + deconstruction = BLASTDOOR_NEEDS_ELECTRONICS + balloon_alert(user, "cables added") + return ITEM_INTERACT_SUCCESS + + if(deconstruction == BLASTDOOR_NEEDS_ELECTRONICS && istype(tool, /obj/item/electronics/airlock)) + balloon_alert(user, "adding electronics...") + if(!do_after(user, 10 SECONDS, src)) + return ITEM_INTERACT_SUCCESS + qdel(tool) + balloon_alert(user, "electronics added") + deconstruction = BLASTDOOR_FINISHED + return ITEM_INTERACT_SUCCESS + return NONE + /obj/machinery/door/poddoor/screwdriver_act(mob/living/user, obj/item/tool) . = ..() if (density) @@ -49,7 +115,8 @@ balloon_alert(user, "open the door first!") return ITEM_INTERACT_SUCCESS if (!panel_open) - return + balloon_alert(user, "open the panel first!") + return ITEM_INTERACT_SUCCESS if (deconstruction != BLASTDOOR_FINISHED) return var/change_id = tgui_input_number(user, "Set the door controllers ID (Current: [id])", "Door Controller ID", isnum(id) ? id : null, 100) @@ -69,7 +136,8 @@ balloon_alert(user, "open the door first!") return ITEM_INTERACT_SUCCESS if (!panel_open) - return + balloon_alert(user, "open the panel first!") + return ITEM_INTERACT_SUCCESS if (deconstruction != BLASTDOOR_FINISHED) return balloon_alert(user, "removing airlock electronics...") @@ -86,7 +154,8 @@ balloon_alert(user, "open the door first!") return ITEM_INTERACT_SUCCESS if (!panel_open) - return + balloon_alert(user, "open the panel first!") + return ITEM_INTERACT_SUCCESS if (deconstruction != BLASTDOOR_NEEDS_ELECTRONICS) return balloon_alert(user, "removing internal cables...") @@ -104,7 +173,8 @@ balloon_alert(user, "open the door first!") return ITEM_INTERACT_SUCCESS if (!panel_open) - return + balloon_alert(user, "open the panel first!") + return ITEM_INTERACT_SUCCESS if (deconstruction != BLASTDOOR_NEEDS_WIRES) return balloon_alert(user, "tearing apart...") //You're tearing me apart, Lisa! @@ -116,17 +186,6 @@ qdel(src) return ITEM_INTERACT_SUCCESS -/obj/machinery/door/poddoor/examine(mob/user) - . = ..() - if(panel_open) - if(deconstruction == BLASTDOOR_FINISHED) - . += span_notice("The maintenance panel is opened and the electronics could be pried out.") - . += span_notice("\The [src] could be calibrated to a blast door controller ID with a multitool.") - else if(deconstruction == BLASTDOOR_NEEDS_ELECTRONICS) - . += span_notice("The electronics are missing and there are some wires sticking out.") - else if(deconstruction == BLASTDOOR_NEEDS_WIRES) - . += span_notice("The wires have been removed and it's ready to be sliced apart.") - /obj/machinery/door/poddoor/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) id = "[port.shuttle_id]_[id]" diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index eca8d88da4b..0df6024ca82 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -16,6 +16,9 @@ density = FALSE opacity = FALSE +/obj/machinery/door/poddoor/shutters/preopen/deconstructed + deconstruction = BLASTDOOR_NEEDS_WIRES + /obj/machinery/door/poddoor/shutters/indestructible name = "hardened shutters" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 9df7d584f42..28aae488866 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -21,7 +21,7 @@ /obj/machinery/recycler/Initialize(mapload) materials = AddComponent( /datum/component/material_container, \ - DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_NO_INSERT \ ) diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 154b03e0f98..693668e9e89 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -606,7 +606,7 @@ var/datum/radial_menu_choice/null_choice = new null_choice.name = DIMENSION_CHOICE_RANDOM choosable_dimensions[DIMENSION_CHOICE_RANDOM] = null_choice - for(var/datum/dimension_theme/theme as anything in DSmaterials.dimensional_themes) + for(var/datum/dimension_theme/theme as anything in SSmaterials.dimensional_themes) var/datum/radial_menu_choice/theme_choice = new theme_choice.image = image(initial(theme.icon), initial(theme.icon_state)) theme_choice.name = initial(theme.name) @@ -628,14 +628,14 @@ /obj/item/bombcore/dimensional/detonate() var/list/affected_turfs = circle_range_turfs(src, range_heavy) - var/theme_count = length(DSmaterials.dimensional_themes) + var/theme_count = length(SSmaterials.dimensional_themes) var/num_affected = 0 for(var/turf/affected as anything in affected_turfs) var/datum/dimension_theme/theme_to_use if(isnull(chosen_theme)) - theme_to_use = DSmaterials.dimensional_themes[DSmaterials.dimensional_themes[rand(1, theme_count)]] + theme_to_use = SSmaterials.dimensional_themes[SSmaterials.dimensional_themes[rand(1, theme_count)]] else - theme_to_use = DSmaterials.dimensional_themes[chosen_theme] + theme_to_use = SSmaterials.dimensional_themes[chosen_theme] if(!theme_to_use.can_convert(affected)) continue num_affected++ diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm index a4ebfc21f1a..026c5974d5f 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm @@ -51,7 +51,7 @@ /obj/effect/anomaly/dimensional/proc/prepare_area(new_theme_path) if (!new_theme_path) new_theme_path = pick(subtypesof(/datum/dimension_theme)) - theme = DSmaterials.dimensional_themes[new_theme_path] + theme = SSmaterials.dimensional_themes[new_theme_path] apply_theme_icon() target_turfs = list() diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index fb87f788036..bf826e207db 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -47,7 +47,7 @@ break return - var/datum/move_loop/loop = DSmove_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) /obj/effect/decal/cleanable/xenoblood/xgibs/proc/spread_movement_effects(datum/move_loop/has_target/source) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 7812ba789b5..8c0788e2fd7 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -163,7 +163,7 @@ break return - var/datum/move_loop/loop = DSmove_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) /obj/effect/decal/cleanable/blood/gibs/proc/spread_movement_effects(datum/move_loop/has_target/source) @@ -376,7 +376,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) /// Set the splatter up to fly through the air until it rounds out of steam or hits something /obj/effect/decal/cleanable/blood/hitsplatter/proc/fly_towards(turf/target_turf, range) var/delay = 2 - var/datum/move_loop/loop = DSmove_manager.move_towards(src, target_turf, delay, timeout = delay * range, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_START_FAST) + var/datum/move_loop/loop = GLOB.move_manager.move_towards(src, target_turf, delay, timeout = delay * range, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_START_FAST) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(loop_done)) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index f21bfc47884..0af1e402ee1 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -412,9 +412,7 @@ . += emissive_appearance(icon, "[icon_state]_light", src, alpha = src.alpha) /obj/effect/decal/cleanable/ants/fire_act(exposed_temperature, exposed_volume) - var/obj/effect/decal/cleanable/ants/fire/fire_ants = new(loc) - fire_ants.reagents.clear_reagents() - reagents.trans_to(fire_ants, fire_ants.reagents.maximum_volume) + new /obj/effect/decal/cleanable/ants/fire(loc) qdel(src) /obj/effect/decal/cleanable/ants/fire diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index 77034850a0b..808a68d6f5e 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -32,7 +32,7 @@ break return - var/datum/move_loop/loop = DSmove_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) /obj/effect/decal/cleanable/robot_debris/proc/spread_movement_effects(datum/move_loop/has_target/source) diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index 9e5418a94f4..4fdd4ac598e 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -67,7 +67,7 @@ would spawn and follow the beaker, even if it is carried or thrown. var/step_amt = pick(1,2,3) var/step_delay = 5 - var/datum/move_loop/loop = DSmove_manager.move(effect, direction, step_delay, timeout = step_delay * step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move(effect, direction, step_delay, timeout = step_delay * step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(decrement_total_effect)) /datum/effect_system/proc/decrement_total_effect(datum/source) diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index 9153d4151b3..a8a3431ef9c 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -11,7 +11,7 @@ /obj/effect/particle_effect/expl_particles/LateInitialize() var/step_amt = pick(25;1,50;2,100;3,200;4) - var/datum/move_loop/loop = DSmove_manager.move(src, pick(GLOB.alldirs), 1, timeout = step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move(src, pick(GLOB.alldirs), 1, timeout = step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(end_particle)) /obj/effect/particle_effect/expl_particles/proc/end_particle(datum/source) diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm index 6444cf3d0ee..f94e5d0e31c 100644 --- a/code/game/objects/effects/effect_system/effects_water.dm +++ b/code/game/objects/effects/effect_system/effects_water.dm @@ -38,7 +38,7 @@ /// Starts the effect moving at a target with a delay in deciseconds, and a lifetime in moves /// Returns the created loop /obj/effect/particle_effect/water/extinguisher/proc/move_at(atom/target, delay, lifetime) - var/datum/move_loop/loop = DSmove_manager.move_towards_legacy(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move_towards_legacy(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_forcemove)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(movement_stopped)) return loop @@ -63,7 +63,7 @@ // Stomach acid doesn't use legacy because it's not "targeted", and we instead want the circular sorta look /obj/effect/particle_effect/water/extinguisher/stomach_acid/move_at(atom/target, delay, lifetime) - var/datum/move_loop/loop = DSmove_manager.move_towards(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move_towards(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_forcemove)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(movement_stopped)) return loop diff --git a/code/game/objects/effects/spawners/xeno_egg_delivery.dm b/code/game/objects/effects/spawners/xeno_egg_delivery.dm index e87b27e0913..eb5bb62df5c 100644 --- a/code/game/objects/effects/spawners/xeno_egg_delivery.dm +++ b/code/game/objects/effects/spawners/xeno_egg_delivery.dm @@ -25,5 +25,5 @@ /obj/structure/alien/egg/delivery/Initialize(mapload) . = ..() - DScommunications.xenomorph_egg_delivered = TRUE - DScommunications.captivity_area = get_area(src) + GLOB.communications_controller.xenomorph_egg_delivered = TRUE + GLOB.communications_controller.captivity_area = get_area(src) diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm index 874104c9202..1467a7854be 100644 --- a/code/game/objects/effects/step_triggers.dm +++ b/code/game/objects/effects/step_triggers.dm @@ -70,7 +70,7 @@ ADD_TRAIT(AM, TRAIT_IMMOBILIZED, REF(src)) affecting[AM] = AM.dir - var/datum/move_loop/loop = DSmove_manager.move(AM, direction, speed, tiles ? tiles * speed : INFINITY) + var/datum/move_loop/loop = GLOB.move_manager.move(AM, direction, speed, tiles ? tiles * speed : INFINITY) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(set_to_normal)) diff --git a/code/game/objects/effects/temporary_visuals/effect_trail.dm b/code/game/objects/effects/temporary_visuals/effect_trail.dm index 2fd7d41d22c..9b28dcf909d 100644 --- a/code/game/objects/effects/temporary_visuals/effect_trail.dm +++ b/code/game/objects/effects/temporary_visuals/effect_trail.dm @@ -29,7 +29,7 @@ AddElement(/datum/element/floor_loving) AddComponent(/datum/component/spawner, spawn_types = list(spawned_effect), max_spawned = max_spawned, spawn_time = spawn_interval) src.target = target - movement = DSmove_manager.move_towards(src, chasing = target, delay = move_speed, home = homing, timeout = duration, flags = MOVEMENT_LOOP_START_FAST) + movement = GLOB.move_manager.move_towards(src, chasing = target, delay = move_speed, home = homing, timeout = duration, flags = MOVEMENT_LOOP_START_FAST) RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_invalid)) if (isliving(target)) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 7e67b23c3b7..19d3d273337 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -14,12 +14,11 @@ else deploy_bodybag(user, get_turf(src)) -/obj/item/bodybag/afterattack(atom/target, mob/user, proximity) - . = ..() - if(proximity) - if(isopenturf(target)) - deploy_bodybag(user, target) - +/obj/item/bodybag/interact_with_atom(atom/interacting_with, mob/living/user, flags) + if(isopenturf(interacting_with)) + deploy_bodybag(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/bodybag/attempt_pickup(mob/user) // can't pick ourselves up if we are inside of the bodybag, else very weird things may happen if(contains(user)) diff --git a/code/game/objects/items/devices/battle_royale.dm b/code/game/objects/items/devices/battle_royale.dm index 4a47b164f43..ab871520465 100644 --- a/code/game/objects/items/devices/battle_royale.dm +++ b/code/game/objects/items/devices/battle_royale.dm @@ -1,3 +1,28 @@ +/// Global list of areas which are considered to be inside the same department for our purposes +GLOBAL_LIST_INIT(battle_royale_regions, list( + "Medical Bay" = list( + /area/station/command/heads_quarters/cmo, + /area/station/medical, + /area/station/security/checkpoint/medical, + ), + "Research Division" = list( + /area/station/command/heads_quarters/rd, + /area/station/security/checkpoint/science, + /area/station/science, + ), + "Engineering Bay" = list( + /area/station/command/heads_quarters/ce, + /area/station/engineering, + /area/station/maintenance/disposal/incinerator, + /area/station/security/checkpoint/engineering, + ), + "Cargo Bay" = list( + /area/station/cargo, + /area/station/command/heads_quarters/qm, + /area/station/security/checkpoint/supply, + ), +)) + /// Quietly implants people with battle royale implants /obj/item/royale_implanter name = "royale implanter" @@ -78,7 +103,7 @@ balloon_alert(user, "[required_contestants - contestant_count] contestants needed!") return - DSbattle_royale.start_battle(implanted_implants) + GLOB.battle_royale_master.start_battle(implanted_implants) for (var/obj/implanter as anything in linked_implanters) do_sparks(3, cardinal_only = FALSE, source = implanter) @@ -115,3 +140,208 @@ /obj/item/royale_remote/proc/implant_destroyed(obj/item/implant) SIGNAL_HANDLER implanted_implants -= implant + +GLOBAL_DATUM_INIT(battle_royale_master, /datum/battle_royale_master, new) + +/// Basically just exists to hold references to datums so that they don't GC +/datum/battle_royale_master + /// List of battle royale datums currently running + var/list/active_battles + +/// Start a new battle royale using a passed list of implants +/datum/battle_royale_master/proc/start_battle(list/competitors) + var/datum/battle_royale_controller/controller = new() + if (!controller.start(competitors)) + return FALSE + LAZYADD(active_battles, controller) + if (LAZYLEN(active_battles) == 1) + start_broadcasting_network(BATTLE_ROYALE_CAMERA_NET) + RegisterSignal(controller, COMSIG_QDELETING, PROC_REF(battle_ended)) + return TRUE + +/// Drop reference when it kills itself +/datum/battle_royale_master/proc/battle_ended(datum/source) + SIGNAL_HANDLER + LAZYREMOVE(active_battles, source) + if (!LAZYLEN(active_battles)) + stop_broadcasting_network(BATTLE_ROYALE_CAMERA_NET) + +/// Datum which controls the conflict +/datum/battle_royale_controller + /// Where is our battle taking place? + var/chosen_area + /// Is the battle currently in progress? + var/battle_running = TRUE + /// Should we let everyone know that someone has died? + var/announce_deaths = TRUE + /// List of implants involved + var/list/contestant_implants = list() + /// Ways to describe that someone has died + var/static/list/euphemisms = list( + "cashed their last paycheque.", + "didn't make it...", + "didn't make the cut.", + "had their head blown clean off!", + "has been killed!", + "has failed the challenge!", + "has passed away.", + "has died.", + "is in a better place now.", + "isn't going to be clocking in tomorrow!", + "just flatlined.", + "isn't today's winner.", + "seems to have exploded!", + "was just murdered on live tv!", + "won't be making it to retirement.", + "won't be getting back up after that one.", + ) + /// Ways to tell people not to salt in deadchat, surely effective + var/static/list/condolences = list( + "Better luck next time!", + "But stay tuned, there's still everything to play for!", + "Did you catch who did it?", + "It looked like that one really hurt...", + "Let's get that one on action replay!", + "Let's have a moment of silence, please.", + "Let's hope the next one does better.", + "Someone please notify their next of kin.", + "They had a good run.", + "Too bad!", + "What a shame!", + "What an upset!", + "What's going to happen next?", + "Who could have seen that coming?", + "Who will be next?", + ) + +/datum/battle_royale_controller/Destroy(force) + contestant_implants = null + return ..() + +/// Start a battle royale with the list of provided implants +/datum/battle_royale_controller/proc/start(list/implants, battle_time = 10 MINUTES) + chosen_area = pick(GLOB.battle_royale_regions) + for (var/obj/item/implant/explosive/battle_royale/contestant_implant in implants) + contestant_implant.start_battle(chosen_area, GLOB.battle_royale_regions[chosen_area]) + if (isnull(contestant_implant)) + continue // Might have exploded if it was removed from a person + RegisterSignal(contestant_implant, COMSIG_QDELETING, PROC_REF(implant_destroyed)) + contestant_implants |= contestant_implant + + if (length(contestant_implants) <= 1) + return FALSE // Well there's not much point is there + + priority_announce( + text = "Congratulations [station_name()], you have been chosen as the next site of the Rumble Royale! \n\ + Viewers across the sector will watch our [convert_integer_to_words(length(contestant_implants))] lucky contestants battle their way into your [chosen_area] and fight until only one is left standing! \n\ + If they don't make it in five minutes, they'll be disqualified. If you see one of our players struggling to get in, do lend them a hand... or don't, if you can live with the consequences! \n\ + As a gesture of gratitude, we will be providing our premium broadcast to your entertainment monitors at no cost so that you can watch the excitement. \n\ + Bystanders are advised not to intervene... but if you do, make it look good for the camera!", + title = "Rumble Royale Beginning", + sound = 'sound/machines/alarm.ogg', + has_important_message = TRUE, + sender_override = "Rumble Royale Pirate Broadcast Station", + color_override = "red", + ) + + for (var/obj/item/implant/explosive/battle_royale/contestant_implant as anything in contestant_implants) + contestant_implant.announce() + addtimer(CALLBACK(src, PROC_REF(limit_area)), battle_time / 2, TIMER_DELETE_ME) + addtimer(CALLBACK(src, PROC_REF(finish)), battle_time, TIMER_DELETE_ME) + return TRUE + +/// An implant was destroyed, hopefully because it exploded. Count how many competitors remain. +/datum/battle_royale_controller/proc/implant_destroyed(obj/item/implant/implant) + SIGNAL_HANDLER + contestant_implants -= implant + if (!battle_running) + return + + if (length(contestant_implants) <= 1) + announce_winner(implant) + else if (announce_deaths) + var/message = "" + if (isnull(implant.imp_in)) + message = "Looks like someone removed and destroyed their implant, that's cheating!" + else + message = "[implant.imp_in.real_name] [pick(euphemisms)] [pick(condolences)]" + priority_announce( + text = message, + title = "Rumble Royale Casualty Report", + sound = 'sound/misc/notice1.ogg', + has_important_message = TRUE, + sender_override = "Rumble Royale Pirate Broadcast Station", + color_override = "red", + ) + +/// There's only one person left, we have a winner! +/datum/battle_royale_controller/proc/announce_winner(obj/item/implant/losing_implant) + battle_running = FALSE + if (length(contestant_implants) > 1) + return + + var/message = "" + var/mob/living/loser = losing_implant.imp_in + var/obj/item/implant/winning_implant = pop(contestant_implants) + var/mob/living/winner = winning_implant?.imp_in + + if (isnull(winner) && isnull(loser)) + message = "Somehow, it seems like there's no winner tonight. What a disappointment!" + else + var/loser_text = isnull(loser) ? "With the disqualification of the other remaining contestant" : "With the death of [loser.real_name]" + var/winner_text = isnull(winner) ? "we must sadly announce that the would-be winner has also been disqualified. Such bad showmanship!" : "only [winner.real_name] remains. Congratulations, we have a winner!" + message = "[loser_text], [winner_text]" + + if (!isnull(winner)) + podspawn(list( + "target" = get_turf(winner), + "style" = STYLE_SYNDICATE, + "spawn" = /obj/item/food/roast_dinner, + )) + + priority_announce( + text = message, + title = "Rumble Royale Winner", + sound = 'sound/misc/notice1.ogg', + has_important_message = TRUE, + sender_override = "Rumble Royale Pirate Broadcast Station", + color_override = "red", + ) + + qdel(winning_implant) // You get to live! + winner?.mind?.remove_antag_datum(/datum/antagonist/survivalist/battle_royale) + qdel(src) + +/// Called halfway through the battle, if you've not made it to the designated battle zone we kill you +/datum/battle_royale_controller/proc/limit_area() + priority_announce( + text = "We're halfway done folks! And bad news to anyone who hasn't made it to the [chosen_area]... you're out!", + title = "Rumble Royale Update", + sound = 'sound/misc/notice1.ogg', + has_important_message = TRUE, + sender_override = "Rumble Royale Pirate Broadcast Station", + color_override = "red", + ) + + for (var/obj/item/implant/explosive/battle_royale/contestant_implant as anything in contestant_implants) + contestant_implant.limit_areas() + +/// Well you're out of time, bad luck +/datum/battle_royale_controller/proc/finish() + battle_running = FALSE + + priority_announce( + text = "Sorry remaining contestants, your time is up. \ + We're sorry to announce that this edition of Royal Rumble has no winner. \n\ + Better luck next time!", + title = "Rumble Royale Concluded", + sound = 'sound/misc/notice1.ogg', + has_important_message = TRUE, + sender_override = "Rumble Royale Pirate Broadcast Station", + color_override = "red", + ) + + for (var/obj/item/implant/explosive/battle_royale/contestant_implant as anything in contestant_implants) + contestant_implant.explode() + + qdel(src) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index cfa3bafbc64..1a2817340f6 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -164,9 +164,13 @@ if(HAS_TRAIT(target, TRAIT_HUSK)) if(advanced) if(HAS_TRAIT_FROM(target, TRAIT_HUSK, BURN)) - render_list += "Subject has been husked by severe burns.\n" + /* SKYRAT EDIT START: More unhusking information */ + render_list += "Subject has been husked by severe burns. Proceed by repairing burn damage and following up with \ + application of [SYNTHFLESH_UNHUSK_AMOUNT]u synthflesh or injection of rezadone as treatment.\n" else if (HAS_TRAIT_FROM(target, TRAIT_HUSK, CHANGELING_DRAIN)) - render_list += "Subject has been husked by dessication.\n" + render_list += "Subject has been husked by dessication. Use application of [SYNTHFLESH_LING_UNHUSK_AMOUNT]u \ + of synthflesh or injection of rezadone as treatment.\n" + /* SKYRAT EDIT END */ else render_list += "Subject has been husked by mysterious causes.\n" @@ -225,6 +229,17 @@ render_list += "Subject is extremely allergic to the following chemicals:\n" render_list += "[allergies]\n" // BUBBER EDIT END + // SKYRAT EDIT ADDITION START -- Show increased/decreased brute/burn mods, to "leave a paper trail" for the fragility quirk + if(ishuman(target)) + var/mob/living/carbon/human/humantarget = target + + var/datum/physiology/physiology = humantarget.physiology + if (physiology.brute_mod != 1) + render_list += "Subject takes [(physiology.brute_mod) * 100]% brute damage.\n" + if (physiology.burn_mod != 1) + render_list += "Subject takes [(physiology.burn_mod) * 100]% burn damage.\n" + // SKYRAT EDIT ADDITION END + if (HAS_TRAIT(target, TRAIT_IRRADIATED)) render_list += "Subject is irradiated. Supply toxin healing.\n" diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 0132cc0f0d8..f7a177f322c 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -258,7 +258,7 @@ //Chair movement loop /obj/item/extinguisher/proc/move_chair(obj/buckled_object, movementdirection) - var/datum/move_loop/loop = DSmove_manager.move(buckled_object, movementdirection, 1, timeout = 9, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move(buckled_object, movementdirection, 1, timeout = 9, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) //This means the chair slowing down is dependant on the extinguisher existing, which is weird //Couldn't figure out a better way though RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(manage_chair_speed)) diff --git a/code/game/objects/items/machine_wand.dm b/code/game/objects/items/machine_wand.dm index 7ce94b9ad40..bc5eb8583f9 100644 --- a/code/game/objects/items/machine_wand.dm +++ b/code/game/objects/items/machine_wand.dm @@ -150,7 +150,7 @@ CRASH("a moving bug has been created but isn't moving towards anything!") src.controller = controller src.thing_moving_towards = thing_moving_towards - var/datum/move_loop/loop = DSmove_manager.home_onto(src, thing_moving_towards, delay = 5, flags = MOVEMENT_LOOP_NO_DIR_UPDATE) + var/datum/move_loop/loop = GLOB.move_manager.home_onto(src, thing_moving_towards, delay = 5, flags = MOVEMENT_LOOP_NO_DIR_UPDATE) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(reached_destination_check)) RegisterSignal(thing_moving_towards, COMSIG_QDELETING, PROC_REF(on_machine_del)) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 4591edfb2a6..887561b1043 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -263,6 +263,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ new/datum/stack_recipe("AI core", /obj/structure/ai_core, 4, time = 5 SECONDS, one_per_turf = TRUE, check_density = FALSE, category = CAT_ROBOT), new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 5 SECONDS, check_density = FALSE, category = CAT_CHEMISTRY), new/datum/stack_recipe("Large Gas Tank", /obj/structure/tank_frame, 4, time=1 SECONDS, one_per_turf=TRUE, check_density = FALSE, category = CAT_ATMOSPHERIC), + new/datum/stack_recipe("shutter assembly", /obj/machinery/door/poddoor/shutters/preopen/deconstructed, 5, time = 5 SECONDS, one_per_turf = TRUE, check_density = FALSE, category = CAT_DOORS), null, new /datum/stack_recipe_list("airlock assemblies", list( \ new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_DOORS), diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 83235796a45..18a95cd77d3 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -110,9 +110,9 @@ for(var/category in what_are_we_made_of.categories) switch(category) if(MAT_CATEGORY_BASE_RECIPES) - recipes |= DSmaterials.base_stack_recipes.Copy() + recipes |= SSmaterials.base_stack_recipes.Copy() if(MAT_CATEGORY_RIGID) - recipes |= DSmaterials.rigid_stack_recipes.Copy() + recipes |= SSmaterials.rigid_stack_recipes.Copy() update_weight() update_appearance() @@ -131,7 +131,7 @@ * - multiplier: The amount to multiply the mats per unit by. Defaults to 1. */ /obj/item/stack/proc/set_mats_per_unit(list/mats, multiplier=1) - mats_per_unit = DSmaterials.FindOrCreateMaterialCombo(mats, multiplier) + mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats, multiplier) update_custom_materials() /** Updates the custom materials list of this stack. diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index dd4fb325858..e6c221793d6 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -406,7 +406,7 @@ /obj/item/storage/bag/tray/proc/do_scatter(obj/item/tray_item) var/delay = rand(2,4) - var/datum/move_loop/loop = DSmove_manager.move_rand(tray_item, list(NORTH,SOUTH,EAST,WEST), delay, timeout = rand(1, 2) * delay, flags = MOVEMENT_LOOP_START_FAST) + var/datum/move_loop/loop = GLOB.move_manager.move_rand(tray_item, list(NORTH,SOUTH,EAST,WEST), delay, timeout = rand(1, 2) * delay, flags = MOVEMENT_LOOP_START_FAST) //This does mean scattering is tied to the tray. Not sure how better to handle it RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(change_speed)) diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index 5cef642634a..e90dd08d938 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -309,7 +309,7 @@ user.log_message("used Resin Launcher", LOG_GAME) playsound(src,'sound/items/syringeproj.ogg',40,TRUE) var/delay = 2 - var/datum/move_loop/loop = DSmove_manager.move_towards(resin, target, delay, timeout = delay * 5, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move_towards(resin, target, delay, timeout = delay * 5, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(resin_stop_check)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(resin_landed)) return diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 0e3845d2efa..e037043cc91 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -218,13 +218,12 @@ /obj/item/emergency_bed/attack_self(mob/user) deploy_bed(user, user.loc) -/obj/item/emergency_bed/afterattack(obj/target, mob/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/emergency_bed/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isopenturf(interacting_with)) + deploy_bed(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE - if(isopenturf(target)) - deploy_bed(user, target) /obj/item/emergency_bed/proc/deploy_bed(mob/user, atom/location) var/obj/structure/bed/medical/emergency/deployed = new /obj/structure/bed/medical/emergency(location) diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 48848df0fd5..f88aadc0463 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -94,7 +94,7 @@ moving = TRUE current_tube = tube - var/datum/move_loop/engine = DSmove_manager.force_move_dir(src, dir, 0, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/engine = GLOB.move_manager.force_move_dir(src, dir, 0, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(engine, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(before_pipe_transfer)) RegisterSignal(engine, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(after_pipe_transfer)) RegisterSignal(engine, COMSIG_QDELETING, PROC_REF(engine_finish)) diff --git a/code/game/world.dm b/code/game/world.dm index e8b99157465..d456a32b8d5 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -17,7 +17,6 @@ GLOBAL_VAR(restart_counter) * - world.init_byond_tracy() * - (Start native profiling) * - world.init_debugger() - * - SysMgr (all data systems) * - Master => * - config *unloaded * - (all subsystems) PreInit() @@ -85,9 +84,6 @@ GLOBAL_VAR(restart_counter) // Create the logger logger = new - // Initialize all the data systems - SysMgr = new - // THAT'S IT, WE'RE DONE, THE. FUCKING. END. Master = new diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm index fe62bb97d81..d6120962fd1 100644 --- a/code/modules/admin/verbs/adminevents.dm +++ b/code/modules/admin/verbs/adminevents.dm @@ -253,11 +253,11 @@ ADMIN_VERB(run_weather, R_FUN, "Run Weather", "Triggers specific weather on the ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a footnote to the roundstart command report.", ADMIN_CATEGORY_EVENTS) var/datum/command_footnote/command_report_footnote = new /datum/command_footnote() - DScommunications.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done. + GLOB.communications_controller.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done. command_report_footnote.message = tgui_input_text(user, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.") if(!command_report_footnote.message) - DScommunications.block_command_report -= 1 + GLOB.communications_controller.block_command_report -= 1 qdel(command_report_footnote) return @@ -266,8 +266,8 @@ ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a if(!command_report_footnote.signature) command_report_footnote.signature = "Classified" - DScommunications.command_report_footnotes += command_report_footnote - DScommunications.block_command_report-- + GLOB.communications_controller.command_report_footnotes += command_report_footnote + GLOB.communications_controller.block_command_report-- message_admins("[user] has added a footnote to the command report: [command_report_footnote.message], signed [command_report_footnote.signature]") @@ -276,5 +276,5 @@ ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a var/signature ADMIN_VERB(delay_command_report, R_FUN, "Delay Command Report", "Prevents the roundstart command report from being sent; or forces it to send it delayed.", ADMIN_CATEGORY_EVENTS) - DScommunications.block_command_report = !DScommunications.block_command_report - message_admins("[key_name_admin(user)] has [(DScommunications.block_command_report ? "delayed" : "sent")] the roundstart command report.") + GLOB.communications_controller.block_command_report = !GLOB.communications_controller.block_command_report + message_admins("[key_name_admin(user)] has [(GLOB.communications_controller.block_command_report ? "delayed" : "sent")] the roundstart command report.") diff --git a/code/modules/antagonists/pirate/pirate_event.dm b/code/modules/antagonists/pirate/pirate_event.dm index 40cf038a214..5ecefa3094d 100644 --- a/code/modules/antagonists/pirate/pirate_event.dm +++ b/code/modules/antagonists/pirate/pirate_event.dm @@ -42,7 +42,7 @@ priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", SSstation.announcer.get_rand_report_sound()) threat.answer_callback = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(pirates_answered), threat, chosen_gang, payoff, world.time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(spawn_pirates), threat, chosen_gang), RESPONSE_MAX_TIME) - DScommunications.send_message(threat, unique = TRUE) + GLOB.communications_controller.send_message(threat, unique = TRUE) /proc/pirates_answered(datum/comm_message/threat, datum/pirate_gang/chosen_gang, payoff, initial_send_time) if(world.time > initial_send_time + RESPONSE_MAX_TIME) diff --git a/code/modules/antagonists/space_dragon/carp_rift.dm b/code/modules/antagonists/space_dragon/carp_rift.dm index 8a74d4b63da..4b8a20acba8 100644 --- a/code/modules/antagonists/space_dragon/carp_rift.dm +++ b/code/modules/antagonists/space_dragon/carp_rift.dm @@ -160,7 +160,7 @@ newcarp.faction = dragon.owner.current.faction.Copy() if(SPT_PROB(1.5, seconds_per_tick)) var/rand_dir = pick(GLOB.cardinals) - DSmove_manager.move_to(src, get_step(src, rand_dir), 1) + GLOB.move_manager.move_to(src, get_step(src, rand_dir), 1) return // Increase time trackers and check for any updated states. diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 222fcb39d16..40b15248413 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -362,7 +362,7 @@ qdel(src) return RegisterSignal(src, COMSIG_MOVABLE_CROSS_OVER, PROC_REF(check_teleport)) - DSmove_manager.move_towards(src, get_turf(whistle.whistler)) + GLOB.move_manager.move_towards(src, get_turf(whistle.whistler)) /// Check if anything the tornado crosses is the creator. /obj/effect/temp_visual/teleporting_tornado/proc/check_teleport(datum/source, atom/movable/crossed) diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm index d2e0bddd0dd..59c83fd52ed 100644 --- a/code/modules/antagonists/xeno/xeno.dm +++ b/code/modules/antagonists/xeno/xeno.dm @@ -87,7 +87,7 @@ explanation_text = "Escape from captivity." /datum/objective/escape_captivity/check_completion() - if(!istype(get_area(owner), DScommunications.captivity_area)) + if(!istype(get_area(owner), GLOB.communications_controller.captivity_area)) return TRUE /datum/objective/advance_hive @@ -146,7 +146,7 @@ if(!captive_alien || captive_alien.stat == DEAD) return CAPTIVE_XENO_DEAD - if(istype(get_area(captive_alien), DScommunications.captivity_area)) + if(istype(get_area(captive_alien), GLOB.communications_controller.captivity_area)) return CAPTIVE_XENO_FAIL return CAPTIVE_XENO_PASS @@ -155,7 +155,7 @@ /mob/living/carbon/alien/mind_initialize() ..() if(!mind.has_antag_datum(/datum/antagonist/xeno)) - if(DScommunications.xenomorph_egg_delivered && istype(get_area(src), DScommunications.captivity_area)) + if(GLOB.communications_controller.xenomorph_egg_delivered && istype(get_area(src), GLOB.communications_controller.captivity_area)) mind.add_antag_datum(/datum/antagonist/xeno/captive) else mind.add_antag_datum(/datum/antagonist/xeno) diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index d152cf09e71..fa8b8332345 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -301,8 +301,8 @@ * * given_layer - the piping_layer we are checking */ /obj/machinery/atmospherics/proc/connection_check(obj/machinery/atmospherics/target, given_layer) - //check if the target & src connect in the same direction - if(!((initialize_directions & get_dir(src, target)) && (target.initialize_directions & get_dir(target, src)))) + //if target is not multiz then we have to check if the target & src connect in the same direction + if(!istype(target, /obj/machinery/atmospherics/pipe/multiz) && !((initialize_directions & get_dir(src, target)) && (target.initialize_directions & get_dir(target, src)))) return FALSE //both target & src can't be connected either way diff --git a/code/modules/bitrunning/orders/bepis.dm b/code/modules/bitrunning/orders/bepis.dm index 286e9817f3c..4b7253bdaf2 100644 --- a/code/modules/bitrunning/orders/bepis.dm +++ b/code/modules/bitrunning/orders/bepis.dm @@ -17,7 +17,3 @@ /datum/orderable_item/bepis/sprayoncan item_path = /obj/item/toy/sprayoncan cost_per_order = 750 - -/datum/orderable_item/bepis/pristine - item_path = /obj/item/disk/design_disk/bepis/remove_tech - cost_per_order = 1000 diff --git a/code/modules/bitrunning/server/loot.dm b/code/modules/bitrunning/server/loot.dm index cb4902abfe3..aa7b99d6e92 100644 --- a/code/modules/bitrunning/server/loot.dm +++ b/code/modules/bitrunning/server/loot.dm @@ -1,3 +1,9 @@ +#define GRADE_D "D" +#define GRADE_C "C" +#define GRADE_B "B" +#define GRADE_A "A" +#define GRADE_S "S" + /// Handles calculating rewards based on number of players, parts, threats, etc /obj/machinery/quantum_server/proc/calculate_rewards() var/rewards_base = 0.8 @@ -28,8 +34,11 @@ var/bonus = calculate_rewards() + var/time_difference = world.time - generated_domain.start_time + var/grade = grade_completion(time_difference) + var/obj/item/paper/certificate = new() - certificate.add_raw_text(get_completion_certificate()) + certificate.add_raw_text(get_completion_certificate(time_difference, grade)) certificate.name = "certificate of domain completion" certificate.update_appearance() @@ -37,6 +46,10 @@ reward_cache.manifest = certificate reward_cache.update_appearance() + if(can_generate_tech_disk(grade)) + new /obj/item/disk/design_disk/bepis/remove_tech(reward_cache) + generated_domain.disk_reward_spawned = TRUE + chosen_forge.start_to_spawn(reward_cache) return TRUE @@ -50,7 +63,7 @@ return TRUE /// Returns the markdown text containing domain completion information -/obj/machinery/quantum_server/proc/get_completion_certificate() +/obj/machinery/quantum_server/proc/get_completion_certificate(time_difference, grade) var/base_points = generated_domain.reward_points if(domain_randomized) base_points -= 1 @@ -59,11 +72,9 @@ var/domain_threats = length(spawned_threat_refs) - var/time_difference = world.time - generated_domain.start_time - var/completion_time = "### Completion Time: [DisplayTimeText(time_difference)]\n" - var/grade = "\n---\n\n# Rating: [grade_completion(time_difference)]" + var/completion_grade = "\n---\n\n# Rating: [grade]" var/text = "# Certificate of Domain Completion\n\n---\n\n" @@ -75,7 +86,7 @@ if(bonuses <= 1) text += completion_time - text += grade + text += completion_grade return text text += "### Bonuses\n" @@ -94,10 +105,24 @@ text += "- **Components:** + [servo_rating]\n" text += completion_time - text += grade + text += completion_grade return text +/// Checks if the players should get a bepis reward +/obj/machinery/quantum_server/proc/can_generate_tech_disk(grade) + if(generated_domain.disk_reward_spawned) + return FALSE + + if(!LAZYLEN(SSresearch.techweb_nodes_experimental)) + return FALSE + + var/static/list/passing_grades = list() + if(!passing_grades.len) + passing_grades = list(GRADE_A,GRADE_S) + + return generated_domain.difficulty >= BITRUNNER_DIFFICULTY_MEDIUM && (grade in passing_grades) + /// Grades the player's run based on several factors /obj/machinery/quantum_server/proc/grade_completion(completion_time) var/score = length(spawned_threat_refs) * 5 @@ -124,13 +149,18 @@ switch(score) if(1 to 4) - return "D" + return GRADE_D if(5 to 7) - return "C" + return GRADE_C if(8 to 10) - return "B" + return GRADE_B if(11 to 13) - return "A" + return GRADE_A else - return "S" + return GRADE_S +#undef GRADE_D +#undef GRADE_C +#undef GRADE_B +#undef GRADE_A +#undef GRADE_S diff --git a/code/modules/bitrunning/virtual_domain/virtual_domain.dm b/code/modules/bitrunning/virtual_domain/virtual_domain.dm index b316bb97cae..21898daad72 100644 --- a/code/modules/bitrunning/virtual_domain/virtual_domain.dm +++ b/code/modules/bitrunning/virtual_domain/virtual_domain.dm @@ -44,6 +44,8 @@ var/start_time /// This map is specifically for unit tests. Shouldn't display in game var/test_only = FALSE + /// Has this domain been beaten with high enough score to spawn a tech disk? + var/disk_reward_spawned = FALSE /// Sends a point to any loot signals on the map /datum/lazy_template/virtual_domain/proc/add_points(points_to_add) diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 97c0093c599..55d3bb1212a 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -166,6 +166,8 @@ desc = "An opulent hat that functions as a radio to God. Or as a lightning rod, depending on who you ask." icon_state = "bishopmitre" +#define CANDY_CD_TIME 2 MINUTES + //Detective /obj/item/clothing/head/fedora/det_hat name = "detective's fedora" @@ -174,11 +176,12 @@ icon_state = "detective" inhand_icon_state = "det_hat" interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING - /// Cooldown for retrieving precious candy corn on alt click - var/candy_cooldown = 0 dog_fashion = /datum/dog_fashion/head/detective - ///Path for the flask that spawns inside their hat roundstart + /// Path for the flask that spawns inside their hat roundstart var/flask_path = /obj/item/reagent_containers/cup/glass/flask/det + /// Cooldown for retrieving precious candy corn with rmb + COOLDOWN_DECLARE(candy_cooldown) + /datum/armor/fedora_det_hat melee = 25 @@ -189,28 +192,46 @@ acid = 50 wound = 5 + /obj/item/clothing/head/fedora/det_hat/Initialize(mapload) . = ..() create_storage(storage_type = /datum/storage/pockets/small/fedora/detective) + register_context() + new flask_path(src) + /obj/item/clothing/head/fedora/det_hat/examine(mob/user) . = ..() . += span_notice("Alt-click to take a candy corn.") + +/obj/item/clothing/head/fedora/det_hat/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + context[SCREENTIP_CONTEXT_ALT_LMB] = "Candy Time" + + return CONTEXTUAL_SCREENTIP_SET + + +/// Now to solve where all these keep coming from /obj/item/clothing/head/fedora/det_hat/click_alt(mob/user) - if(candy_cooldown >= world.time) + if(!COOLDOWN_FINISHED(src, candy_cooldown)) to_chat(user, span_warning("You just took a candy corn! You should wait a couple minutes, lest you burn through your stash.")) return CLICK_ACTION_BLOCKING - var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src) - user.put_in_hands(CC) + var/obj/item/food/candy_corn/sweets = new /obj/item/food/candy_corn(src) + user.put_in_hands(sweets) to_chat(user, span_notice("You slip a candy corn from your hat.")) - candy_cooldown = world.time+1200 + COOLDOWN_START(src, candy_cooldown, CANDY_CD_TIME) + return CLICK_ACTION_SUCCESS + +#undef CANDY_CD_TIME + /obj/item/clothing/head/fedora/det_hat/minor flask_path = /obj/item/reagent_containers/cup/glass/flask/det/minor diff --git a/code/modules/events/immovable_rod/immovable_rod.dm b/code/modules/events/immovable_rod/immovable_rod.dm index 658d2d07bd8..e9d2995218d 100644 --- a/code/modules/events/immovable_rod/immovable_rod.dm +++ b/code/modules/events/immovable_rod/immovable_rod.dm @@ -45,9 +45,9 @@ RegisterSignal(src, COMSIG_ATOM_ENTERING, PROC_REF(on_entering_atom)) if(special_target) - DSmove_manager.home_onto(src, special_target) + GLOB.move_manager.home_onto(src, special_target) else - DSmove_manager.move_towards(src, real_destination) + GLOB.move_manager.move_towards(src, real_destination) /obj/effect/immovablerod/Destroy(force) UnregisterSignal(src, COMSIG_ATOM_ENTERING) @@ -76,11 +76,6 @@ if(istype(ghost)) ghost.ManualFollow(src) -/obj/effect/immovablerod/proc/on_entered_over_movable(datum/source, atom/movable/atom_crossed_over) - SIGNAL_HANDLER - if((atom_crossed_over.density || isliving(atom_crossed_over)) && !QDELETED(atom_crossed_over)) - Bump(atom_crossed_over) - /obj/effect/immovablerod/proc/on_entering_atom(datum/source, atom/destination, atom/old_loc, list/atom/old_locs) SIGNAL_HANDLER if(destination.density && isturf(destination)) @@ -113,7 +108,7 @@ return visible_message(span_danger("[src] phases into reality.")) - DSmove_manager.home_onto(src, special_target) + GLOB.move_manager.home_onto(src, special_target) if(loc == target_turf) complete_trajectory() @@ -264,7 +259,7 @@ * Stops your rod's automated movement. Sit... Stay... Good rod! */ /obj/effect/immovablerod/proc/sit_stay_good_rod() - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) /** * Allows your rod to release restraint level zero and go for a walk. @@ -278,7 +273,7 @@ /obj/effect/immovablerod/proc/go_for_a_walk(walkies_location = null) if(walkies_location) special_target = walkies_location - DSmove_manager.home_onto(src, special_target) + GLOB.move_manager.home_onto(src, special_target) return complete_trajectory() @@ -294,7 +289,7 @@ */ /obj/effect/immovablerod/proc/walk_in_direction(direction) destination_turf = get_edge_target_turf(src, direction) - DSmove_manager.move_towards(src, destination_turf) + GLOB.move_manager.move_towards(src, destination_turf) /** * Rod will push the tram to a landmark if it hits the tram from the front/back diff --git a/code/modules/events/shuttle_insurance.dm b/code/modules/events/shuttle_insurance.dm index fed6ad9af9e..4442291a9ed 100644 --- a/code/modules/events/shuttle_insurance.dm +++ b/code/modules/events/shuttle_insurance.dm @@ -43,7 +43,7 @@ /datum/round_event/shuttle_insurance/start() insurance_message = new("Shuttle Insurance", "Hey, pal, this is the [ship_name]. Can't help but notice you're rocking a wild and crazy shuttle there with NO INSURANCE! Crazy. What if something happened to it, huh?! We've done a quick evaluation on your rates in this sector and we're offering [insurance_evaluation] to cover for your shuttle in case of any disaster.", list("Purchase Insurance.","Reject Offer.")) insurance_message.answer_callback = CALLBACK(src, PROC_REF(answered)) - DScommunications.send_message(insurance_message, unique = TRUE) + GLOB.communications_controller.send_message(insurance_message, unique = TRUE) /datum/round_event/shuttle_insurance/proc/answered() if(EMERGENCY_AT_LEAST_DOCKED) diff --git a/code/modules/jobs/job_types/station_trait/human_ai.dm b/code/modules/jobs/job_types/station_trait/human_ai.dm index 285479a6912..af80df69fe8 100644 --- a/code/modules/jobs/job_types/station_trait/human_ai.dm +++ b/code/modules/jobs/job_types/station_trait/human_ai.dm @@ -148,8 +148,8 @@ return ..() /obj/item/secure_camera_console_pod - name = "advanced camera control pod" - desc = "Calls down a secure camera console to use for all your AI stuff, may only be activated in the SAT." + name = "pre-packaged advanced camera control" + desc = "A pre-packaged camera console used for all your AI stuff, programmed to only active in the SAT." icon = 'icons/obj/devices/remote.dmi' icon_state = "botpad_controller" inhand_icon_state = "radio" @@ -163,9 +163,9 @@ if(!is_type_in_typecache(current_area, allowed_areas)) user.balloon_alert(user, "not in the sat!") return - podspawn(list( - "target" = get_turf(src), - "style" = STYLE_BLUESPACE, - "spawn" = /obj/machinery/computer/camera_advanced, - )) + user.balloon_alert(user, "unpacking...") + if(!do_after(user, 5 SECONDS, src)) + return + playsound(src, 'sound/items/drill_use.ogg', 40, TRUE) + new /obj/machinery/computer/camera_advanced/human_ai(get_turf(src)) qdel(src) diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm b/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm index 55fe9e77eac..7f1c8d781f4 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm @@ -45,5 +45,5 @@ else if(isliving(hit_atom)) var/mob/living/hit_mob = hit_atom - DSmove_manager.stop_looping(hit_mob) //stops them mid pathing even if they're stunimmune + GLOB.move_manager.stop_looping(hit_mob) //stops them mid pathing even if they're stunimmune hit_mob.apply_status_effect(/datum/status_effect/ice_block_talisman, 3 SECONDS) diff --git a/code/modules/meteors/meteor_types.dm b/code/modules/meteors/meteor_types.dm index d7a7dd14002..120352f14c5 100644 --- a/code/modules/meteors/meteor_types.dm +++ b/code/modules/meteors/meteor_types.dm @@ -76,7 +76,7 @@ /obj/effect/meteor/proc/chase_target(atom/chasing, delay, home) if(!isatom(chasing)) return - var/datum/move_loop/new_loop = DSmove_manager.move_towards(src, chasing, delay, home, lifetime) + var/datum/move_loop/new_loop = GLOB.move_manager.move_towards(src, chasing, delay, home, lifetime) if(!new_loop) return diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 2eaa1d95db9..61318f63b92 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -152,7 +152,7 @@ materials = AddComponent( \ /datum/component/material_container, \ - DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ allowed_items = accepted_type \ diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index 5096f00a770..97c3a90b78e 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -20,7 +20,7 @@ materials = AddComponent( \ /datum/component/material_container, \ - DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ container_signals = list( \ diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 7aa48093a0d..3537dd37bbe 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -168,24 +168,17 @@ /obj/item/organ/internal/brain/primate/on_mob_insert(mob/living/carbon/primate) . = ..() - RegisterSignal(primate, COMSIG_MOVABLE_CROSS, PROC_REF(on_crossed)) + RegisterSignal(primate, COMSIG_LIVING_MOB_BUMPED, PROC_REF(on_mob_bump)) /obj/item/organ/internal/brain/primate/on_mob_remove(mob/living/carbon/primate) . = ..() - UnregisterSignal(primate, COMSIG_MOVABLE_CROSS) + UnregisterSignal(primate, COMSIG_LIVING_MOB_BUMPED) -/obj/item/organ/internal/brain/primate/proc/on_crossed(datum/source, atom/movable/crossed) +/obj/item/organ/internal/brain/primate/proc/on_mob_bump(mob/source, mob/living/crossing_mob) SIGNAL_HANDLER - if(!tripping) + if(!tripping || !crossing_mob.combat_mode) return - if(IS_DEAD_OR_INCAP(owner) || !isliving(crossed)) - return - var/mob/living/in_the_way_mob = crossed - if(iscarbon(in_the_way_mob) && !in_the_way_mob.combat_mode) - return - if(in_the_way_mob.pass_flags & PASSMOB) - return - in_the_way_mob.knockOver(owner) + crossing_mob.knockOver(owner) /obj/item/organ/internal/brain/primate/get_attacking_limb(mob/living/carbon/human/target) if(!HAS_TRAIT(owner, TRAIT_ADVANCEDTOOLUSER)) diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index 2c390c540ce..8415881a83a 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -98,7 +98,7 @@ SIGNAL_HANDLER mobility_flags &= ~MOBILITY_MOVE if(living_flags & MOVES_ON_ITS_OWN) - DSmove_manager.stop_looping(src) //stop mid walk //This is also really dumb + GLOB.move_manager.stop_looping(src) //stop mid walk //This is also really dumb /// Called when [TRAIT_IMMOBILIZED] is removed from the mob. /mob/living/proc/on_immobilized_trait_loss(datum/source) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 05fdbad99e8..cd745931963 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -73,11 +73,19 @@ if(levels <= 1 && can_help_themselves) var/obj/item/organ/external/wings/gliders = get_organ_by_type(/obj/item/organ/external/wings) if(HAS_TRAIT(src, TRAIT_FREERUNNING) || gliders?.can_soften_fall()) // the power of parkour or wings allows falling short distances unscathed + var/graceful_landing = HAS_TRAIT(src, TRAIT_CATLIKE_GRACE) + + if(graceful_landing) + add_movespeed_modifier(/datum/movespeed_modifier/landed_on_feet) + addtimer(CALLBACK(src, TYPE_PROC_REF(/mob, remove_movespeed_modifier), /datum/movespeed_modifier/landed_on_feet), levels * 3 SECONDS) + else + Knockdown(levels * 4 SECONDS) + emote("spin") + visible_message( - span_notice("[src] makes a hard landing on [impacted_turf] but remains unharmed from the fall."), - span_notice("You brace for the fall. You make a hard landing on [impacted_turf], but remain unharmed."), + span_notice("[src] makes a hard landing on [impacted_turf] but remains unharmed from the fall[graceful_landing ? " and stays on [p_their()] feet" : " by tucking in rolling into the landing"]."), + span_notice("You brace for the fall. You make a hard landing on [impacted_turf], but remain unharmed[graceful_landing ? " while landing on your feet" : " by tucking in and rolling into the landing"]."), ) - Knockdown(levels * 4 SECONDS) return . | ZIMPACT_NO_MESSAGE var/incoming_damage = (levels * 5) ** 1.5 @@ -153,6 +161,7 @@ return TRUE SEND_SIGNAL(src, COMSIG_LIVING_MOB_BUMP, M) + SEND_SIGNAL(M, COMSIG_LIVING_MOB_BUMPED, src) //Even if we don't push/swap places, we "touched" them, so spread fire spreadFire(M) @@ -1361,9 +1370,9 @@ return FALSE if(invisibility || alpha <= 50)//cloaked return FALSE - if(!isturf(src.loc)) //The reason why we don't just use get_turf is because they could be in a closet, disposals, or a vehicle. + if(!isturf(loc)) //The reason why we don't just use get_turf is because they could be in a closet, disposals, or a vehicle. return FALSE - var/turf/T = src.loc + var/turf/T = loc if(is_centcom_level(T.z)) //dont detect mobs on centcom return FALSE if(is_away_level(T.z)) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 4fbd1b55234..95623e3c538 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -480,3 +480,11 @@ stack_trace("Silicon [src] ( [type] ) was somehow missing their integrated tablet. Please make a bug report.") create_modularInterface() modularInterface.imprint_id(name = newname) + +/mob/living/silicon/can_track(mob/living/user) + //if their camera is online, it's safe to assume they are in cameranets + //since it takes a while for camera vis to update, this lets us bypass that so AIs can always see their borgs, + //without making cameras constantly update every time a borg moves. + if(builtInCamera && builtInCamera.can_use()) + return TRUE + return ..() diff --git a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm index 6d85b9c1867..f09361e9bdf 100644 --- a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm +++ b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm @@ -71,7 +71,7 @@ switch(mode) if(BOT_IDLE) // idle update_appearance() - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) look_for_perp() // see if any criminals are in range if(!mode && bot_mode_flags & BOT_MODE_AUTOPATROL) // still idle, and set to patrol mode = BOT_START_PATROL // switch to patrol mode @@ -80,7 +80,7 @@ playsound(src,'sound/effects/beepskyspinsabre.ogg',100,TRUE,-1) // general beepsky doesn't give up so easily, jedi scum if(frustration >= 20) - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) back_to_idle() return if(target) // make sure target exists @@ -91,7 +91,7 @@ return else // not next to perp var/turf/olddist = get_dist(src, target) - DSmove_manager.move_to(src, target, 1, 4) + GLOB.move_manager.move_to(src, target, 1, 4) if((get_dist(src, target)) >= (olddist)) frustration++ else diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 8c933e8f83a..5f22d0ed1c8 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -164,7 +164,7 @@ target = null oldtarget_name = null set_anchored(FALSE) - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) last_found = world.time /mob/living/simple_animal/bot/secbot/proc/on_saboteur(datum/source, disrupt_duration) @@ -389,7 +389,7 @@ switch(mode) if(BOT_IDLE) // idle - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) look_for_perp() // see if any criminals are in range if((mode == BOT_IDLE) && bot_mode_flags & BOT_MODE_AUTOPATROL) // didn't start hunting during look_for_perp, and set to patrol mode = BOT_START_PATROL // switch to patrol mode @@ -397,7 +397,7 @@ if(BOT_HUNT) // hunting for perp // if can't reach perp for long enough, go idle if(frustration >= 8) - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) back_to_idle() return @@ -415,7 +415,7 @@ // not next to perp var/turf/olddist = get_dist(src, target) - DSmove_manager.move_to(src, target, 1, 4) + GLOB.move_manager.move_to(src, target, 1, 4) if((get_dist(src, target)) >= (olddist)) frustration++ else diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 86fc82d77e0..4bba53270e5 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -104,7 +104,7 @@ /mob/living/simple_animal/hostile/Life(seconds_per_tick = SSMOBS_DT, times_fired) . = ..() if(!.) //dead - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) /mob/living/simple_animal/hostile/handle_automated_action() if(AIStatus == AI_OFF || QDELETED(src)) @@ -339,11 +339,11 @@ if(!target.Adjacent(target_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown OpenFire(target) if(!Process_Spacemove(0)) //Drifting - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) return 1 if(retreat_distance != null) //If we have a retreat distance, check if we need to run from our target if(target_distance <= retreat_distance) //If target's closer than our retreat distance, run - DSmove_manager.move_away(src, target, retreat_distance, move_to_delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) + GLOB.move_manager.move_away(src, target, retreat_distance, move_to_delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) else Goto(target,move_to_delay,minimum_distance) //Otherwise, get to our minimum distance so we chase them else @@ -378,7 +378,7 @@ approaching_target = TRUE else approaching_target = FALSE - DSmove_manager.move_to(src, target, minimum_distance, delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) + GLOB.move_manager.move_to(src, target, minimum_distance, delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) return TRUE /mob/living/simple_animal/hostile/adjustHealth(amount, updating_health = TRUE, forced = FALSE) @@ -418,7 +418,7 @@ GiveTarget(null) approaching_target = FALSE in_melee = FALSE - DSmove_manager.stop_looping(src) + GLOB.move_manager.stop_looping(src) LoseAggro() SEND_SIGNAL(src, COMSIG_HOSTILE_MOB_LOST_TARGET) // SKYRAT EDIT ADDITION diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 81bc6c166d2..a9c109b81a3 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -381,7 +381,7 @@ /obj/machinery/anomalous_crystal/theme_warp/Initialize(mapload) . = ..() - terrain_theme = DSmaterials.dimensional_themes[pick(subtypesof(/datum/dimension_theme))] + terrain_theme = SSmaterials.dimensional_themes[pick(subtypesof(/datum/dimension_theme))] observer_desc = "This crystal changes the area around it to match the theme of \"[terrain_theme.name]\"." /obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm index b2555309f8a..95744d0a2d3 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm @@ -45,7 +45,7 @@ /mob/living/simple_animal/hostile/asteroid/curseblob/proc/move_loop(move_target, delay) if(our_loop) return - our_loop = DSmove_manager.force_move(src, move_target, delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + our_loop = GLOB.move_manager.force_move(src, move_target, delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) if(!our_loop) return RegisterSignal(move_target, COMSIG_MOB_STATCHANGE, PROC_REF(stat_change)) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index cda62ce836f..3a297b400eb 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -539,7 +539,7 @@ /mob/living/simple_animal/proc/Goto(target, delay, minimum_distance) if(prevent_goto_movement) return FALSE - DSmove_manager.move_to(src, target, minimum_distance, delay) + GLOB.move_manager.move_to(src, target, minimum_distance, delay) return TRUE //Makes this mob hunt the prey, be it living or an object. Will kill living creatures, and delete objects. diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 35ef05ec40f..2e2f5c85b53 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -315,7 +315,7 @@ if(rebound.last_pushoff == world.time) continue if(continuous_move && !pass_allowed) - var/datum/move_loop/move/rebound_engine = DSmove_manager.processing_on(rebound, SSspacedrift) + var/datum/move_loop/move/rebound_engine = GLOB.move_manager.processing_on(rebound, SSspacedrift) // If you're moving toward it and you're both going the same direction, stop if(moving_direction == get_dir(src, pushover) && rebound_engine && moving_direction == rebound_engine.direction) continue diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index adbcc2064f8..2aec3e361c4 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -834,7 +834,7 @@ . = ..() if(!length(accepted_mats)) - accepted_mats = DSmaterials.materials_by_category[MAT_CATEGORY_SILO] + accepted_mats = SSmaterials.materials_by_category[MAT_CATEGORY_SILO] container = AddComponent( \ /datum/component/material_container, \ diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 605e88f1e48..5dd5515c47c 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -441,8 +441,8 @@ // Handle stamping items. if(writing_stats["interaction_mode"] == MODE_STAMPING) if(!user.can_read(src) || user.is_blind()) - //The paper's stampable window area is assumed approx 400x500 - add_stamp(writing_stats["stamp_class"], rand(0, 400), rand(0, 500), rand(0, 360), writing_stats["stamp_icon_state"]) + //The paper's stampable window area is assumed approx 300x400 + add_stamp(writing_stats["stamp_class"], rand(0, 300), rand(0, 400), rand(0, 360), writing_stats["stamp_icon_state"]) user.visible_message(span_notice("[user] blindly stamps [src] with \the [attacking_item]!")) to_chat(user, span_notice("You stamp [src] with \the [attacking_item] the best you can!")) playsound(src, 'sound/items/handling/standard_stamp.ogg', 50, vary = TRUE) @@ -454,6 +454,25 @@ ui_interact(user) return ..() +/// Secondary right click interaction to quickly stamp things +/obj/item/paper/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + var/list/writing_stats = tool.get_writing_implement_details() + + if(!length(writing_stats)) + return NONE + if(writing_stats["interaction_mode"] != MODE_STAMPING) + return NONE + if(!user.can_read(src) || user.is_blind()) // Just leftclick instead + return NONE + + add_stamp(writing_stats["stamp_class"], rand(1, 300), rand(1, 400), stamp_icon_state = writing_stats["stamp_icon_state"]) + user.visible_message( + span_notice("[user] quickly stamps [src] with [tool] without looking."), + span_notice("You quickly stamp [src] with [tool] without looking."), + ) + playsound(src, 'sound/items/handling/standard_stamp.ogg', 50, vary = TRUE) + + return ITEM_INTERACT_BLOCKING // Stop the UI from opening. /** * Attempts to ui_interact the paper to the given user, with some sanity checking * to make sure the camera still exists via the weakref and that this paper is still diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index d47d7536094..74b7bfdbcdc 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -340,7 +340,7 @@ if(STAGE_ONE) steps = 1 if(STAGE_TWO) - steps = 3//Yes this is right + steps = 2 if(STAGE_THREE) steps = 3 if(STAGE_FOUR) diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index ec2139ad5d0..15135bee1a5 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -43,7 +43,7 @@ /obj/item/ammo_box/Initialize(mapload) . = ..() - custom_materials = DSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1) + custom_materials = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1) if(!start_empty) top_off(starting=TRUE) update_icon_state() diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index e7bb73d29f2..7013c9bdb96 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -174,6 +174,8 @@ CAT_TUBES = GLOB.reagent_containers[CAT_TUBES], CAT_PILLS = GLOB.reagent_containers[CAT_PILLS], CAT_PATCHES = GLOB.reagent_containers[CAT_PATCHES], + CAT_HYPOS = GLOB.reagent_containers[CAT_HYPOS], // SKYRAT EDIT + CAT_DARTS = GLOB.reagent_containers[CAT_DARTS], // SKYRAT EDIT ) return containers @@ -488,6 +490,10 @@ item_name_default = "[master_reagent.name] [item_name_default]" if(!(initial(selected_container.reagent_flags) & OPENCONTAINER)) // Closed containers get both reagent name and units in the name item_name_default = "[master_reagent.name] [item_name_default] ([volume_in_each]u)" + // SKYRAT EDIT ADDITION START - Autonamed hyposprays/smartdarts + if(ispath(selected_container, /obj/item/reagent_containers/cup/vial) || ispath(selected_container, /obj/item/reagent_containers/syringe/smartdart)) + item_name_default = "[master_reagent.name] [item_name_default]" + // SKYRAT EDIT ADDITION END var/item_name = tgui_input_text(usr, "Container name", "Name", diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index e35a71e5d9b..d2e44a4c4bb 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -100,7 +100,7 @@ reagent_puff.end_life() return - var/datum/move_loop/our_loop = DSmove_manager.move_towards_legacy(reagent_puff, target, wait_step, timeout = range * wait_step, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/our_loop = GLOB.move_manager.move_towards_legacy(reagent_puff, target, wait_step, timeout = range * wait_step, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) reagent_puff.RegisterSignal(our_loop, COMSIG_QDELETING, TYPE_PROC_REF(/obj/effect/decal/chempuff, loop_ended)) reagent_puff.RegisterSignal(our_loop, COMSIG_MOVELOOP_POSTPROCESS, TYPE_PROC_REF(/obj/effect/decal/chempuff, check_move)) diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm index 6d5b270cd71..6ef15929ecc 100644 --- a/code/modules/recycling/conveyor.dm +++ b/code/modules/recycling/conveyor.dm @@ -241,7 +241,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /obj/machinery/conveyor/proc/conveyable_enter(datum/source, atom/convayable) SIGNAL_HANDLER if(operating == CONVEYOR_OFF) - DSmove_manager.stop_looping(convayable, SSconveyors) + GLOB.move_manager.stop_looping(convayable, SSconveyors) return start_conveying(convayable) @@ -249,12 +249,12 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) SIGNAL_HANDLER var/has_conveyor = neighbors["[direction]"] if(convayable.z != z || !has_conveyor || !isturf(convayable.loc)) //If you've entered something on us, stop moving - DSmove_manager.stop_looping(convayable, SSconveyors) + GLOB.move_manager.stop_looping(convayable, SSconveyors) /obj/machinery/conveyor/proc/start_conveying(atom/movable/moving) if(QDELETED(moving)) return - var/datum/move_loop/move/moving_loop = DSmove_manager.processing_on(moving, SSconveyors) + var/datum/move_loop/move/moving_loop = GLOB.move_manager.processing_on(moving, SSconveyors) if(moving_loop) moving_loop.direction = movedir moving_loop.delay = speed * 1 SECONDS @@ -268,7 +268,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /obj/machinery/conveyor/proc/stop_conveying(atom/movable/thing) if(!ismovable(thing)) return - DSmove_manager.stop_looping(thing, SSconveyors) + GLOB.move_manager.stop_looping(thing, SSconveyors) // attack with item, place item on conveyor /obj/machinery/conveyor/attackby(obj/item/attacking_item, mob/living/user, params) @@ -350,8 +350,6 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /// The current state of the switch. var/position = CONVEYOR_OFF - /// Last direction setting. - var/last_pos = CONVEYOR_BACKWARDS /// If the switch only operates the conveyor belts in a single direction. var/oneway = FALSE /// If the level points the opposite direction when it's turned on. @@ -372,6 +370,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) AddComponent(/datum/component/usb_port, list( /obj/item/circuit_component/conveyor_switch, )) + register_context() /obj/machinery/conveyor_switch/Destroy() LAZYREMOVE(GLOB.conveyors_by_id[id], src) @@ -397,6 +396,27 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) icon_state = "[base_icon_state]-[invert_icon ? "rev" : "fwd"]" return ..() +/obj/machinery/conveyor_switch/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(!held_item) + context[SCREENTIP_CONTEXT_LMB] = "Toggle forwards" + if(!oneway) + context[SCREENTIP_CONTEXT_RMB] = "Toggle backwards" + return CONTEXTUAL_SCREENTIP_SET + if(held_item.tool_behaviour == TOOL_MULTITOOL) + context[SCREENTIP_CONTEXT_LMB] = "Set speed" + context[SCREENTIP_CONTEXT_RMB] = "View wires" + return CONTEXTUAL_SCREENTIP_SET + if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "Toggle oneway" + return CONTEXTUAL_SCREENTIP_SET + if(held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Detach" + return CONTEXTUAL_SCREENTIP_SET + if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "Invert" + return CONTEXTUAL_SCREENTIP_SET + /// Updates all conveyor belts that are linked to this switch, and tells them to start processing. /obj/machinery/conveyor_switch/proc/update_linked_conveyors() for(var/obj/machinery/conveyor/belt in GLOB.conveyors_by_id[id]) @@ -414,28 +434,29 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) CHECK_TICK /// Updates the switch's `position` and `last_pos` variable. Useful so that the switch can properly cycle between the forwards, backwards and neutral positions. -/obj/machinery/conveyor_switch/proc/update_position() +/obj/machinery/conveyor_switch/proc/update_position(direction) if(position == CONVEYOR_OFF) if(oneway) //is it a oneway switch position = oneway else - if(last_pos < CONVEYOR_OFF) + if(direction == CONVEYOR_FORWARD) position = CONVEYOR_FORWARD - last_pos = CONVEYOR_OFF else position = CONVEYOR_BACKWARDS - last_pos = CONVEYOR_OFF else - last_pos = position position = CONVEYOR_OFF /// Called when a user clicks on this switch with an open hand. -/obj/machinery/conveyor_switch/interact(mob/user) +/obj/machinery/conveyor_switch/attack_hand(mob/living/user, list/modifiers) add_fingerprint(user) - update_position() + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + update_position(CONVEYOR_BACKWARDS) + else + update_position(CONVEYOR_FORWARD) update_appearance() update_linked_conveyors() update_linked_switches() + return TRUE /obj/machinery/conveyor_switch/attackby(obj/item/attacking_item, mob/user, params) if(is_wire_tool(attacking_item)) @@ -588,14 +609,19 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /obj/item/circuit_component/conveyor_switch display_name = "Conveyor Switch" desc = "Allows to control connected conveyor belts." - circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL + /// Direction input ports. + var/datum/port/input/stop + var/datum/port/input/active + var/datum/port/input/reverse /// The current direction of the conveyor attached to the component. var/datum/port/output/direction /// The switch this conveyor switch component is attached to. var/obj/machinery/conveyor_switch/attached_switch /obj/item/circuit_component/conveyor_switch/populate_ports() + active = add_input_port("Activate", PORT_TYPE_SIGNAL, trigger = PROC_REF(activate)) + stop = add_input_port("Stop", PORT_TYPE_SIGNAL, trigger = PROC_REF(stop)) direction = add_output_port("Conveyor Direction", PORT_TYPE_NUMBER) /obj/item/circuit_component/conveyor_switch/get_ui_notices() @@ -606,27 +632,34 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) . = ..() if(istype(shell, /obj/machinery/conveyor_switch)) attached_switch = shell + if(!attached_switch.oneway) + reverse = add_input_port("Reverse", PORT_TYPE_SIGNAL, trigger = PROC_REF(reverse)) /obj/item/circuit_component/conveyor_switch/unregister_usb_parent(atom/movable/shell) attached_switch = null return ..() -/obj/item/circuit_component/conveyor_switch/input_received(datum/port/input/port) - if(!attached_switch) - return - - INVOKE_ASYNC(src, PROC_REF(update_conveyors), port) - -/obj/item/circuit_component/conveyor_switch/proc/update_conveyors(datum/port/input/port) - if(!attached_switch) - return - - attached_switch.update_position() +/obj/item/circuit_component/conveyor_switch/proc/on_switch_changed() attached_switch.update_appearance() attached_switch.update_linked_conveyors() attached_switch.update_linked_switches() direction.set_output(attached_switch.position) +/obj/item/circuit_component/conveyor_switch/proc/activate() + SIGNAL_HANDLER + attached_switch.position = CONVEYOR_FORWARD + INVOKE_ASYNC(src, PROC_REF(on_switch_changed)) + +/obj/item/circuit_component/conveyor_switch/proc/stop() + SIGNAL_HANDLER + attached_switch.position = CONVEYOR_OFF + INVOKE_ASYNC(src, PROC_REF(on_switch_changed)) + +/obj/item/circuit_component/conveyor_switch/proc/reverse() + SIGNAL_HANDLER + attached_switch.position = CONVEYOR_BACKWARDS + INVOKE_ASYNC(src, PROC_REF(on_switch_changed)) + #undef CONVEYOR_BACKWARDS #undef CONVEYOR_OFF #undef CONVEYOR_FORWARD diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index ecc33c240bf..b842a69413d 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -78,7 +78,7 @@ /// Starts the movement process, persists while the holder is moving through pipes /obj/structure/disposalholder/proc/start_moving() var/delay = world.tick_lag - var/datum/move_loop/our_loop = DSmove_manager.move_disposals(src, delay = delay, timeout = delay * count) + var/datum/move_loop/our_loop = GLOB.move_manager.move_disposals(src, delay = delay, timeout = delay * count) if(our_loop) RegisterSignal(our_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(our_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(try_expel)) diff --git a/code/modules/religion/rites.dm b/code/modules/religion/rites.dm index af02fa72117..d7d0fa81844 100644 --- a/code/modules/religion/rites.dm +++ b/code/modules/religion/rites.dm @@ -128,13 +128,36 @@ /datum/religion_rites/machine_blessing/invoke_effect(mob/living/user, atom/movable/religious_tool) ..() var/altar_turf = get_turf(religious_tool) - var/blessing = pick( - /obj/item/organ/internal/cyberimp/arm/surgery, - /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic, - /obj/item/organ/internal/cyberimp/eyes/hud/medical, - /obj/item/organ/internal/cyberimp/mouth/breathing_tube, - /obj/item/organ/internal/cyberimp/chest/thrusters, - /obj/item/organ/internal/eyes/robotic/glow, + var/blessing = pick_weight_recursive( + list( + // Arms + list( + /obj/item/organ/internal/cyberimp/arm/combat = 1, + /obj/item/organ/internal/cyberimp/arm/surgery = 1000000, + /obj/item/organ/internal/cyberimp/arm/toolset = 1500000, + ) = 15, + // Eyes + list( + /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic = 1, + /obj/item/organ/internal/cyberimp/eyes/hud/medical = 1, + /obj/item/organ/internal/eyes/robotic/glow = 1, + /obj/item/organ/internal/eyes/robotic/shield = 2, + ) = 15, + // Chest + list( + /obj/item/organ/internal/cyberimp/chest/reviver = 1, + /obj/item/organ/internal/cyberimp/chest/thrusters = 2, + ) = 9, + // Brain / Head + list( + /obj/item/organ/internal/cyberimp/brain/anti_drop = 100, + /obj/item/organ/internal/cyberimp/brain/anti_stun = 10, + ) = 10, + // Misc + list( + /obj/item/organ/internal/cyberimp/mouth/breathing_tube = 1, + ) = 5, + ) ) new blessing(altar_turf) return TRUE @@ -391,7 +414,7 @@ /datum/religion_rites/ceremonial_weapon/perform_rite(mob/living/user, atom/religious_tool) for(var/obj/item/stack/sheet/could_blade in get_turf(religious_tool)) - if(!(GET_MATERIAL_REF(could_blade.material_type) in DSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL])) + if(!(GET_MATERIAL_REF(could_blade.material_type) in SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL])) continue if(could_blade.amount < 5) continue diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index 7b85a878ec3..0e6a37ce3d0 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -93,8 +93,8 @@ Slimecrossing Items icon_state = "yellow slime extract" rating = 7 custom_materials = null - maxcharge = 50000 - chargerate = 2500 + maxcharge = 50 * STANDARD_CELL_CHARGE + chargerate = 2.5 * STANDARD_CELL_RATE charge_light_type = null connector_type = "slimecore" diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index f0f7b0accaf..e17488bc96a 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -71,7 +71,7 @@ /// If this uplink item is only available to certain roles. Roles are dependent on the frequency chip or stored ID. var/list/restricted_roles = list() /// The species able to purchase this uplink item. - var/restricted_species = list() + var/list/restricted_species = list() /// The minimum amount of progression needed for this item to be added to uplinks. var/progression_minimum = 0 /// Whether this purchase is visible in the purchase log. diff --git a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm index 61853ef1cdc..6a70d4db9f0 100644 --- a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm @@ -129,7 +129,7 @@ /obj/item/mecha_parts/mecha_equipment/gravcatapult/proc/do_scatter(atom/movable/scatter, atom/movable/target) var/dist = 5 - get_dist(scatter, target) var/delay = 2 - DSmove_manager.move_away(scatter, target, delay = delay, timeout = delay * dist, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + GLOB.move_manager.move_away(scatter, target, delay = delay, timeout = delay * dist, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) /obj/item/mecha_parts/mecha_equipment/gravcatapult/get_snowflake_data() return list( diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm index 92fcb995f76..d40b57276c0 100644 --- a/code/modules/vehicles/wheelchair.dm +++ b/code/modules/vehicles/wheelchair.dm @@ -126,7 +126,7 @@ . = ..() if(over_object != usr || !Adjacent(usr) || !foldabletype) return FALSE - if(!ishuman(usr) || !usr.can_perform_action(src)) + if(!ishuman(usr) || !usr.can_perform_action(src, ALLOW_RESTING)) return FALSE if(has_buckled_mobs()) return FALSE @@ -138,6 +138,12 @@ /obj/item/wheelchair/attack_self(mob/user) //Deploys wheelchair on in-hand use deploy_wheelchair(user, user.loc) +/obj/item/wheelchair/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isopenturf(interacting_with)) + deploy_wheelchair(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE + /obj/item/wheelchair/proc/deploy_wheelchair(mob/user, atom/location) var/obj/vehicle/ridden/wheelchair/wheelchair_unfolded = new unfolded_type(location) wheelchair_unfolded.add_fingerprint(user) diff --git a/code/modules/wiremod/shell/gun.dm b/code/modules/wiremod/shell/gun.dm index 9f196e6c1fc..283815fb334 100644 --- a/code/modules/wiremod/shell/gun.dm +++ b/code/modules/wiremod/shell/gun.dm @@ -30,7 +30,7 @@ range = 7 /obj/item/stock_parts/cell/emproof/wiremod_gun - maxcharge = 100 + maxcharge = 0.1 * STANDARD_CELL_CHARGE /obj/item/gun/energy/wiremod_gun/Initialize(mapload) . = ..() diff --git a/config/game_options.txt b/config/game_options.txt index 208d4657ced..09a9a10fc7c 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -147,6 +147,13 @@ EVENTS_MIN_TIME_MUL 5 ## Set to 0 to make dangerous events avaliable for all populations. EVENTS_MIN_PLAYERS_MUL 1 +## The lower bound, in deciseconds, for how soon another random event can be scheduled. +## Defaults to 1500 deciseconds or 2.5 minutes +EVENTS_FREQUENCY_LOWER 1500 + +## The upper bound, in deciseconds, for how soon another random event can be scheduled. +## Defaults to 4200 deciseconds or 7 minutes +EVENTS_FREQUENCY_UPPER 4200 ## AI ### diff --git a/html/changelogs/AutoChangeLog-pr-27585.yml b/html/changelogs/AutoChangeLog-pr-27585.yml new file mode 100644 index 00000000000..6105e70440d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-27585.yml @@ -0,0 +1,5 @@ +author: "SkyratBot" +delete-after: True +changes: + - balance: "Bitrunners can now earn Bepis disks, once per medium domain or above, if they scored at least an A." + - rscdel: "Bitrunners can not buy Bepis disks from their vendors." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-27586.yml b/html/changelogs/AutoChangeLog-pr-27586.yml new file mode 100644 index 00000000000..dd43731450a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-27586.yml @@ -0,0 +1,4 @@ +author: "SkyratBot" +delete-after: True +changes: + - bugfix: "Fixed lua scripts breaking when turfs with registered signals get deleted." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-27588.yml b/html/changelogs/AutoChangeLog-pr-27588.yml new file mode 100644 index 00000000000..f79ea04becd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-27588.yml @@ -0,0 +1,5 @@ +author: "Useroth" +delete-after: True +changes: + - bugfix: "Fixes transfer votes" + - refactor: "Removes modular piece of code related to electrocution that is no longer necessary." \ No newline at end of file diff --git a/html/changelogs/archive/2024-05.yml b/html/changelogs/archive/2024-05.yml index 159e5f7723a..7cb0990839f 100644 --- a/html/changelogs/archive/2024-05.yml +++ b/html/changelogs/archive/2024-05.yml @@ -54,3 +54,77 @@ - bugfix: Automatically link machines to closest research server for off-station z levels (fixes Tarkon/DS-2 machines linking to wrong R&D server) - qol: Wrench down research console on DS-2 +2024-05-02: + Fluffles: + - qol: you can pick up wheelchairs while on the ground + - qol: you can place wheelchairs a tile away from you, like roller beds + Majkl-J: + - bugfix: Company imports button is brought back + SkyratBot: + - bugfix: The syndicate infiltrator has no weak spots anymore + - rscadd: trainship hijack deathmatch map + - qol: The Human AI's advanced security console can be repackaged with a screwdriver + if you wish to move it. + - bugfix: You can now re-construct pod doors that had deconstruction started. + - qol: You can now make pod door assemblies using plasteel in-hand. + - bugfix: If you are a freerunner, you don't end up faceplanting despite having + catlike grace. + - admin: Debug uplinks now shows all categories and won't lock upon buying items + like his grace and the syndicate balloon. + - qol: conveyor switches now have direction-specific input signals + - bugfix: AIs can now track Silicon as long as their built-in camera is online. + - bugfix: Constantly fleeing in Battle Arcade will no longer give you a very large + amount of decimals due to halving your gold every time. + - bugfix: Monkey changelings that are disguised as someone can now take off their + flesh clothes. + - bugfix: Fixes hypercharged slime core cells and circuit guns having 1,000 times + less energy than intended. + - bugfix: Monkeys can no longer be knocked over by walking into a windoor on combat + mode while they're behind it. +2024-05-03: + Majkl-J: + - qol: Health analyzers now include basic information on treatment of husked bodies. + - bugfix: Synth computers no longer force open the messenger app + Melbert: + - admin: Custom Single and Custom Multi votes are now combined into one vote + - admin: Admins can now end votes instantly, rather than cancelling them + - admin: Admins can now reset the vote cooldown + - bugfix: Vote cooldown actually applies now + SkyratBot: + - qol: You can now quickly stamp papers with a right click + - image: added directional sprites for radiation shutters + - bugfix: the civilian bounty control terminal displays the payout of new bounty + options again + - qol: the civilian bounty control terminal displays the description of new bounty + options + - qol: conveyors now use left and right click controls + - qol: add screentips for conveyor switches + - rscdel: removes circuit conveyor circuit default trigger behavior in favor in + favor of the three state triggers + - bugfix: fix runtime when no events were drafted to be picked from + - config: make events frequency configurable + - rscadd: increased the size of the pool that Machine Blessing draws from + - balance: weighted some of the implants that Machine Blessing can give + SpaceLoveSs13: + - rscadd: Fragile now has customization for damage from 1.2x to 5x modifier. + - bugfix: Interlink Arrivals shuttles have tiny fans for air support! + nikothedude: + - bugfix: Jousting no longer bypasses pacifism +2024-05-04: + Melbert: + - bugfix: New machine god blessings now actually works probably + Ryll/Shaps: + - bugfix: Pacifists can no longer endlessly spam the backblast functionality of + loaded rocket launchers that they cannot actually fire + SkyratBot: + - bugfix: mobs in the same faction will no longer be at odds against one another + - bugfix: mobs can now perform behaviors alongside searching for targets + - bugfix: mobs will no longer be starting and stopping when chasing targets + - bugfix: Candy corn is once again available to detective fedoras + - rscadd: Adds an Icebox-specific station trait that brightens outdoors areas on + the surface level. + - bugfix: Stage 2 singularities should no longer escape containment + - bugfix: Fire ant colonies created by burning regular ants will now contain fire + ants as their reagent + mogeoko: + - bugfix: Ventcrawling mobs can change Z-level using multiz-decks again. diff --git a/icons/obj/doors/shutters_radiation.dmi b/icons/obj/doors/shutters_radiation.dmi index 657b613b0cc..2e70b24a4aa 100644 Binary files a/icons/obj/doors/shutters_radiation.dmi and b/icons/obj/doors/shutters_radiation.dmi differ diff --git a/lua/SS13_base.lua b/lua/SS13_base.lua index f49908f0942..ea04c8c6503 100644 --- a/lua/SS13_base.lua +++ b/lua/SS13_base.lua @@ -100,7 +100,8 @@ function SS13.register_signal(datum, signal, func) callback:call_proc("RegisterSignal", datum, signal, "Invoke") local path = { "__SS13_signal_handlers", datumWeakRef, signal, callbackWeakRef, "func" } callback.vars.arguments = { path } - if not __SS13_signal_handlers[datumWeakRef]._cleanup then + -- Turfs don't remove their signals on deletion. + if not __SS13_signal_handlers[datumWeakRef]._cleanup and not SS13.istype(datum, "/turf") then local cleanupCallback = SS13.new("/datum/callback", SS13.state, "call_function_return_first") local cleanupPath = { "__SS13_signal_handlers", datumWeakRef, "_cleanup"} cleanupCallback.vars.arguments = { cleanupPath } @@ -134,6 +135,11 @@ function SS13.unregister_signal(datum, signal, callback) local callbackWeakRef = dm.global_proc("WEAKREF", handler_callback) if not SS13.istype(datum, "/datum/weakref") then handler_callback:call_proc("UnregisterSignal", datum, signal) + else + local actualDatum = datum:call_proc("hard_resolve") + if SS13.is_valid(actualDatum) then + handler_callback:call_proc("UnregisterSignal", actualDatum, signal) + end end SS13.stop_tracking(handler_callback) end diff --git a/lua/handler_group.lua b/lua/handler_group.lua index fff63ad18e4..0246d33c744 100644 --- a/lua/handler_group.lua +++ b/lua/handler_group.lua @@ -14,7 +14,7 @@ function HandlerGroup:register_signal(datum, signal, func) if not callback then return end - table.insert(self.registered, { datum = datum, signal = signal, callback = callback }) + table.insert(self.registered, { datum = dm.global_proc("WEAKREF", datum), signal = signal, callback = callback }) end -- Clears all the signals that have been registered on this HandlerGroup diff --git a/modular_skyrat/master_files/code/datums/traits/negative.dm b/modular_skyrat/master_files/code/datums/traits/negative.dm index 621795c25aa..5387f215df5 100644 --- a/modular_skyrat/master_files/code/datums/traits/negative.dm +++ b/modular_skyrat/master_files/code/datums/traits/negative.dm @@ -15,17 +15,56 @@ medical_record_text = "Patient's body has adapted to low gravity. Sadly low-gravity environments are not conducive to strong bone development." icon = FA_ICON_TIRED +/datum/quirk_constant_data/fragile + associated_typepath = /datum/quirk/fragile + customization_options = list( + /datum/preference/numeric/fragile_customization/brute, + /datum/preference/numeric/fragile_customization/burn, + ) + +/datum/preference/numeric/fragile_customization + abstract_type = /datum/preference/numeric/fragile_customization + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_identifier = PREFERENCE_CHARACTER + + minimum = 1.25 + maximum = 5 // 5x damage, arbitrary + + step = 0.01 + +/datum/preference/numeric/fragile_customization/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return FALSE + +/datum/preference/numeric/fragile_customization/create_default_value() + return 1.25 + +/datum/preference/numeric/fragile_customization/brute + savefile_key = "fragile_brute" + +/datum/preference/numeric/fragile_customization/burn + savefile_key = "fragile_burn" + /datum/quirk/fragile/post_add() . = ..() + var/mob/living/carbon/human/user = quirk_holder - user.physiology.brute_mod *= 1.25 - user.physiology.burn_mod *= 1.2 + var/datum/preferences/prefs = user.client.prefs + var/brutemod = prefs.read_preference(/datum/preference/numeric/fragile_customization/brute) + var/burnmod = prefs.read_preference(/datum/preference/numeric/fragile_customization/burn) + + user.physiology.brute_mod *= brutemod + user.physiology.burn_mod *= burnmod /datum/quirk/fragile/remove() . = ..() + var/mob/living/carbon/human/user = quirk_holder - user.physiology.brute_mod /= 1.25 - user.physiology.burn_mod /= 1.2 + var/datum/preferences/prefs = user.client.prefs + var/brutemod = prefs.read_preference(/datum/preference/numeric/fragile_customization/brute) + var/burnmod = prefs.read_preference(/datum/preference/numeric/fragile_customization/burn) + // will cause issues if the user changes this value before removal + user.physiology.brute_mod /= brutemod + user.physiology.burn_mod /= burnmod /datum/quirk/monophobia name = "Monophobia" diff --git a/modular_skyrat/master_files/code/modules/power/powernet.dm b/modular_skyrat/master_files/code/modules/power/powernet.dm deleted file mode 100644 index 189a4aa0449..00000000000 --- a/modular_skyrat/master_files/code/modules/power/powernet.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/powernet/get_electrocute_damage() - if(avail >= 1000) - var/damage = clamp(20 + round(avail/25000), 20, 195) + rand(-5,5) - return damage * HUMAN_HEALTH_MODIFIER - else - return 0 diff --git a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm index e7e760a6f27..64e199150f2 100644 --- a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm +++ b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm @@ -68,7 +68,7 @@ /obj/machinery/ammo_workbench/Initialize(mapload) AddComponent( \ /datum/component/material_container, \ - DSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ + SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ 200000, \ MATCONTAINER_EXAMINE, \ allowed_items = /obj/item/stack, \ diff --git a/modular_skyrat/modules/autotransfer/code/transfer_vote.dm b/modular_skyrat/modules/autotransfer/code/transfer_vote.dm index 709c6369dc4..97703fe4805 100644 --- a/modular_skyrat/modules/autotransfer/code/transfer_vote.dm +++ b/modular_skyrat/modules/autotransfer/code/transfer_vote.dm @@ -7,34 +7,26 @@ CHOICE_TRANSFER, CHOICE_CONTINUE, ) + default_message = "Vote to initiate a crew transfer." -/datum/vote/transfer_vote/toggle_votable(mob/toggler) - if(!toggler) - CRASH("[type] wasn't passed a \"toggler\" mob to toggle_votable.") - if(!check_rights_for(toggler.client, R_ADMIN)) - return FALSE - - +/datum/vote/transfer_vote/toggle_votable() CONFIG_SET(flag/allow_vote_transfer, !CONFIG_GET(flag/allow_vote_transfer)) - return TRUE /datum/vote/transfer_vote/is_config_enabled() return CONFIG_GET(flag/autotransfer) && CONFIG_GET(flag/allow_vote_transfer) -/datum/vote/transfer_vote/can_be_initiated(mob/by_who, forced) +/datum/vote/transfer_vote/can_be_initiated(forced) . = ..() - if(!.) - return FALSE + if(. != VOTE_AVAILABLE) + return . if(forced) - return TRUE + return VOTE_AVAILABLE if(!CONFIG_GET(flag/autotransfer) || !CONFIG_GET(flag/allow_vote_transfer)) - if(by_who) - to_chat(by_who, span_warning("Transfer voting is disabled.")) - return FALSE + return "Transfer voting is disabled." - return TRUE + return VOTE_AVAILABLE /datum/vote/transfer_vote/finalize_vote(winning_option) if(winning_option == CHOICE_CONTINUE) diff --git a/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm b/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm index ef17198a781..4ea599ba001 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm @@ -18,6 +18,7 @@ if(!istype(loc, /obj/item/organ/internal/brain/synth)) return INITIALIZE_HINT_QDEL +/* Action for opening the synthbrain computer */ /datum/action/item_action/synth/open_internal_computer name = "Open persocom emulation" desc = "Accesses your built-in virtual machine." @@ -28,6 +29,9 @@ var/obj/item/organ/internal/brain/synth/targetmachine = target targetmachine.internal_computer.interact(owner) +/* +Various overrides necessary to get the persocom working, namely ui status, power, and ID handling +*/ /obj/item/modular_computer/pda/synth/ui_state(mob/user) return GLOB.default_state @@ -44,6 +48,11 @@ ) return ..() +// Needed to tell the power check that we're handling power ourselves +/obj/item/modular_computer/pda/synth/check_power_override(amount) + return TRUE + +// Handles the id slot reading our id /obj/item/modular_computer/pda/synth/proc/handle_id_slot(mob/living/carbon/human/synth) if(!istype(synth)) return @@ -64,7 +73,7 @@ /obj/item/modular_computer/pda/synth/get_ntnet_status() . = ..() - if(is_centcom_level(loc.z)) // Centcom is excluded because cafe + if(is_centcom_level(loc.z)) // Centcom is excluded because cafe would allow people to abuse these . = NTNET_NO_SIGNAL return . diff --git a/tgstation.dme b/tgstation.dme index 2ba68b7ed44..dceed8ad3f0 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -765,6 +765,7 @@ #include "code\controllers\subsystem\lua.dm" #include "code\controllers\subsystem\machines.dm" #include "code\controllers\subsystem\mapping.dm" +#include "code\controllers\subsystem\materials.dm" #include "code\controllers\subsystem\minor_mapping.dm" #include "code\controllers\subsystem\mobs.dm" #include "code\controllers\subsystem\modular_computers.dm" @@ -876,6 +877,7 @@ #include "code\datums\chat_payload.dm" #include "code\datums\chatmessage.dm" #include "code\datums\cogbar.dm" +#include "code\datums\communications.dm" #include "code\datums\dash_weapon.dm" #include "code\datums\datum.dm" #include "code\datums\datumvars.dm" @@ -896,6 +898,7 @@ #include "code\datums\map_config.dm" #include "code\datums\minigames_menu.dm" #include "code\datums\mood.dm" +#include "code\datums\move_manager.dm" #include "code\datums\movement_detector.dm" #include "code\datums\mutable_appearance.dm" #include "code\datums\numbered_display.dm" @@ -1959,12 +1962,6 @@ #include "code\datums\storage\subtypes\rped.dm" #include "code\datums\storage\subtypes\surgery_tray.dm" #include "code\datums\storage\subtypes\trash.dm" -#include "code\datums\systems\_system.dm" -#include "code\datums\systems\manager.dm" -#include "code\datums\systems\ds\battle_royale.dm" -#include "code\datums\systems\ds\communications.dm" -#include "code\datums\systems\ds\materials.dm" -#include "code\datums\systems\ds\move_handler.dm" #include "code\datums\votes\_vote_datum.dm" #include "code\datums\votes\custom_vote.dm" #include "code\datums\votes\map_vote.dm" @@ -6633,7 +6630,6 @@ #include "modular_skyrat\master_files\code\modules\paperwork\stamps.dm" #include "modular_skyrat\master_files\code\modules\power\cable.dm" #include "modular_skyrat\master_files\code\modules\power\circulator.dm" -#include "modular_skyrat\master_files\code\modules\power\powernet.dm" #include "modular_skyrat\master_files\code\modules\power\thermoelectric_generator.dm" #include "modular_skyrat\master_files\code\modules\power\lighting\light_mapping_helpers.dm" #include "modular_skyrat\master_files\code\modules\power\singularity\containment_field.dm" diff --git a/tgui/packages/tgui/interfaces/CivCargoHoldTerminal.jsx b/tgui/packages/tgui/interfaces/CivCargoHoldTerminal.jsx index 386f3c5721a..438030e3947 100644 --- a/tgui/packages/tgui/interfaces/CivCargoHoldTerminal.jsx +++ b/tgui/packages/tgui/interfaces/CivCargoHoldTerminal.jsx @@ -96,41 +96,66 @@ const BountyTextBox = (props) => { const BountyPickBox = (props) => { const { act, data } = useBackend(); - const { id_bounty_names, id_bounty_values } = data; + const { id_bounty_names, id_bounty_infos, id_bounty_values } = data; return (
- + - + - +
); }; + +const BountyPickButton = (props) => { + return ( + + ); +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/fragile_customization.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/fragile_customization.tsx new file mode 100644 index 00000000000..32af5d28d96 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/fragile_customization.tsx @@ -0,0 +1,12 @@ +// THIS IS A SKYRAT UI FILE +import { Feature, FeatureNumberInput } from '../../base'; + +export const fragile_brute: Feature = { + name: 'Brute Modifier', + component: FeatureNumberInput, +}; + +export const fragile_burn: Feature = { + name: 'Burn Modifier', + component: FeatureNumberInput, +}; diff --git a/tgui/packages/tgui/interfaces/Uplink/index.tsx b/tgui/packages/tgui/interfaces/Uplink/index.tsx index a8b2e7d477b..4949fc94ee7 100644 --- a/tgui/packages/tgui/interfaces/Uplink/index.tsx +++ b/tgui/packages/tgui/interfaces/Uplink/index.tsx @@ -137,13 +137,15 @@ export class Uplink extends Component<{}, UplinkState> { uplinkData.items = uplinkData.items.filter((value) => { if ( value.restricted_roles.length > 0 && - !value.restricted_roles.includes(uplinkRole) + !value.restricted_roles.includes(uplinkRole) && + !data.debug ) { return false; } if ( value.restricted_species.length > 0 && - !value.restricted_species.includes(uplinkSpecies) + !value.restricted_species.includes(uplinkSpecies) && + !data.debug ) { return false; } @@ -455,7 +457,7 @@ export class Uplink extends Component<{}, UplinkState> { } }} /> - {(shop_locked && ( + {(shop_locked && !data.debug && ( { - const { data } = useBackend(); - const { currentVote, user } = data; + const { act, data } = useBackend(); + const { currentVote, user, LastVoteTime, VoteCD } = data; /** * Adds the voting type to title if there is an ongoing vote. @@ -81,7 +84,19 @@ export const VotePanel = (props) => { -
+
act('resetCooldown')} + /> + ) + } + > {!!user.isLowerAdmin && currentVote && }
@@ -93,51 +108,86 @@ export const VotePanel = (props) => { ); }; +const VoteOptionDimmer = (props) => { + const { data } = useBackend(); + const { LastVoteTime, VoteCD } = data; + + return ( + + + + Vote Cooldown + + {Math.floor((VoteCD + LastVoteTime) / 10)}s + + + ); +}; + /** * The create vote options menu. Only upper admins can disable voting. * @returns A section visible to everyone with vote options. */ const VoteOptions = (props) => { const { act, data } = useBackend(); - const { possibleVotes, user } = data; + const { possibleVotes, user, LastVoteTime, VoteCD } = data; return ( - - {possibleVotes.map((option) => ( - - {!!user.isLowerAdmin && option.config !== VoteConfig.None && ( - - act('toggleVote', { - voteName: option.name, - }) - } - /> - )} -
); @@ -153,11 +203,11 @@ const VotersList = (props) => { return ( -
+
{data.voting.map((voter) => { return {voter}; })} @@ -280,13 +330,26 @@ const TimePanel = (props) => { {currentVote?.timeRemaining || 0}s {!!user.isLowerAdmin && ( - + + + + + + + + )}