diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4f689686028..97b77c3a3dc 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -88,7 +88,7 @@ Things you **CAN'T** do: * [Close PRs](https://imgur.com/w2RqpX8.png): Only maintainers are allowed to close PRs. Do not hit that button. * Close issues purely for breaking a template if the same information is contained without it. -For more information reference the [Issue Manager Guide](.github/guides/ISSUE_MANAGER.md). +For more information reference the [Issue Manager Guide](./guides/ISSUE_MANAGER.md). diff --git a/.github/guides/ISSUE_MANAGER.md b/.github/guides/ISSUE_MANAGER.md index c0ef14ae0cc..3ecab32a7f5 100644 --- a/.github/guides/ISSUE_MANAGER.md +++ b/.github/guides/ISSUE_MANAGER.md @@ -15,10 +15,10 @@ When examining new issues you should immediately notify a maintainer if you see - **Server Lagging** [[1]](https://github.com/tgstation/tgstation/issues/60193) [[2]](https://github.com/tgstation/tgstation/issues/51927) [[3]](https://github.com/tgstation/tgstation/issues/32762) - Something that is causing a _severe_ amount of lag during the game #### Runtime Issue Reports -If an issue reports a runtime, it must have the actual runtime call stack provided by round logging or in-game debug menu (https://github.com/tgstation/tgstation/issues/70329#issuecomment-1279853883). +If an issue reports a runtime, it must have the actual runtime call stack provided by round logging or in-game debug menu (https://github.com/tgstation/tgstation/issues/70329#issuecomment-1279853883).
Example runtime call stack - + ``` [2022-10-15 16:12:38.902] runtime error: Cannot execute null.add(). - proc name: visibility (/datum/cameranet/proc/visibility) @@ -28,8 +28,8 @@ If an issue reports a runtime, it must have the actual runtime call stack provid - usr.loc: the floor (150,25,4) (/turf/open/floor/circuit) - call stack: - Camera Net (/datum/cameranet): visibility(/list (/list), null, /list (/list), 1) - - AI (/mob/living/silicon/ai): camera visibility(Inactive AI Eye (/mob/camera/ai_eye)) - - Inactive AI Eye (/mob/camera/ai_eye): setLoc(the floor (150,25,4) (/turf/open/floor/circuit), 0) + - AI (/mob/living/silicon/ai): camera visibility(Inactive AI Eye (/mob/eye/ai_eye)) + - Inactive AI Eye (/mob/eye/ai_eye): setLoc(the floor (150,25,4) (/turf/open/floor/circuit), 0) - AI (/mob/living/silicon/ai): create eye() - AI (/mob/living/silicon/ai): Initialize(0, null, TagGamerGame2 (/mob/dead/new_player)) - Atoms (/datum/controller/subsystem/atoms): InitAtom(AI (/mob/living/silicon/ai), 0, /list (/list)) diff --git a/README.md b/README.md index ef946e8f0bc..6859688b6eb 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,15 @@ Find `BUILD.bat` here in the root folder of tgstation, and double click it to in **[How to compile in VSCode and other build options](tools/build/README.md).** -## Contributors -[Guides for Contributors](.github/CONTRIBUTING.md) +## Getting started -[/tg/station HACKMD account](https://hackmd.io/@tgstation) - Design documentation here +For contribution guidelines refer to the [Guides for Contributors](.github/CONTRIBUTING.md). + +For getting started (dev env, compilation) see the HackMD document [here](https://hackmd.io/@tgstation/HJ8OdjNBc#tgstation-Development-Guide). + +For overall design documentation see [HackMD](https://hackmd.io/@tgstation). + +For lore, [see Common Core](https://github.com/tgstation/common_core). ## LICENSE diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 175d9c72ce0..ef4ae3a2ae5 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -2854,6 +2854,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "bfe" = ( @@ -2875,6 +2876,7 @@ /obj/structure/disposalpipe/junction/flip{ dir = 8 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "bfU" = ( @@ -6754,6 +6756,7 @@ /area/space/nearstation) "cCM" = ( /obj/structure/cable, +/obj/structure/sink/kitchen/directional/east, /turf/open/floor/iron/kitchen/small, /area/station/service/kitchen) "cCP" = ( @@ -10747,15 +10750,12 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "dZa" = ( -/obj/structure/table/reinforced, /obj/machinery/camera/directional/west, /obj/effect/decal/cleanable/cobweb, -/obj/item/retractor, -/obj/item/hemostat, -/obj/item/cautery, /obj/machinery/camera/autoname/directional/north, /obj/structure/sign/poster/official/random/directional/north, /obj/machinery/status_display/ai/directional/west, +/obj/item/surgery_tray/full/deployed, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) "dZk" = ( @@ -14030,13 +14030,13 @@ /turf/open/floor/iron/small, /area/station/security/office) "fhp" = ( -/obj/structure/table, /obj/effect/spawner/random/food_or_drink/donkpockets{ pixel_y = 6 }, /obj/effect/turf_decal/siding{ dir = 8 }, +/obj/structure/table, /turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "fhT" = ( @@ -15014,6 +15014,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "fyZ" = ( @@ -15896,6 +15897,7 @@ dir = 1 }, /obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "fMg" = ( @@ -17909,10 +17911,6 @@ pixel_y = 8 }, /obj/item/clothing/mask/surgical, -/obj/item/surgical_drapes{ - pixel_x = -1; - pixel_y = 4 - }, /obj/machinery/status_display/evac/directional/west, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) @@ -20103,6 +20101,11 @@ name = "Pharmacy Shutters Control"; req_access = list("pharmacy") }, +/obj/item/reagent_containers/cup/bottle/multiver, +/obj/item/reagent_containers/cup/bottle/epinephrine, +/obj/item/reagent_containers/cup/bottle/formaldehyde, +/obj/item/reagent_containers/cup/bottle/acidic_buffer, +/obj/item/reagent_containers/cup/bottle/basic_buffer, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) "hdT" = ( @@ -21861,9 +21864,9 @@ /turf/open/floor/iron/smooth, /area/station/command/gateway) "hIm" = ( -/obj/machinery/libraryscanner, /obj/machinery/camera/autoname/directional/north, /obj/machinery/airalarm/directional/north, +/obj/machinery/bookbinder, /turf/open/floor/wood/parquet, /area/station/service/library) "hIE" = ( @@ -24221,6 +24224,7 @@ pixel_y = 18 }, /obj/structure/extinguisher_cabinet/directional/east, +/obj/item/circuitboard/mecha/ripley/main, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) "ivC" = ( @@ -25630,6 +25634,16 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"iPx" = ( +/obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ + dir = 1; + filter_type = list(/datum/gas/nitrogen) + }, +/obj/effect/turf_decal/bot{ + dir = 1 + }, +/turf/open/floor/engine, +/area/station/engineering/supermatter/room) "iPy" = ( /obj/structure/cable, /turf/open/floor/iron, @@ -26363,6 +26377,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "jab" = ( @@ -35546,7 +35561,7 @@ "mae" = ( /obj/structure/cable, /turf/closed/wall, -/area/station/service/bar) +/area/station/maintenance/central/greater) "maf" = ( /turf/closed/wall/rust, /area/station/hallway/primary/fore) @@ -40713,6 +40728,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "nSd" = ( @@ -43703,6 +43719,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "oYj" = ( @@ -44211,6 +44228,11 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"phk" = ( +/obj/structure/table/wood, +/obj/machinery/libraryscanner, +/turf/open/floor/carpet, +/area/station/service/library) "phm" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -46111,6 +46133,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron/small, /area/station/hallway/primary/port) "pOQ" = ( @@ -51218,10 +51241,10 @@ pixel_y = 2 }, /obj/item/holosign_creator/robot_seat/restaurant, -/obj/structure/table, /obj/effect/turf_decal/siding{ dir = 9 }, +/obj/structure/table, /turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "rya" = ( @@ -52580,7 +52603,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "rVI" = ( -/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped{ +/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped/inverse{ dir = 8 }, /turf/open/floor/iron, @@ -54598,13 +54621,7 @@ /turf/open/misc/sandy_dirt, /area/station/security/tram) "sGt" = ( -/obj/structure/table/reinforced, -/obj/item/scalpel{ - pixel_y = 12 - }, -/obj/item/blood_filter, -/obj/item/circular_saw, -/obj/item/bonesetter, +/obj/structure/closet/crate/freezer/surplus_limbs, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) "sGE" = ( @@ -61583,6 +61600,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "uQT" = ( @@ -62423,15 +62441,12 @@ /turf/open/floor/iron/smooth_large, /area/station/science/robotics/mechbay) "vfI" = ( -/obj/machinery/microwave{ - pixel_y = 5 - }, /obj/machinery/light_switch/directional/north, /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/table, /obj/effect/turf_decal/siding/end, +/obj/machinery/smartfridge/drying, /turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "vfK" = ( @@ -65146,9 +65161,15 @@ /turf/open/floor/iron/dark, /area/station/command/corporate_dock) "vTP" = ( -/obj/structure/sink/kitchen/directional/east, /obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/kitchen/small, +/obj/structure/table, +/obj/machinery/microwave{ + pixel_y = 5 + }, +/obj/effect/turf_decal/siding/end{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "vTV" = ( /turf/closed/wall/r_wall, @@ -67830,7 +67851,7 @@ /obj/effect/spawner/random/maintenance, /obj/structure/rack, /turf/open/floor/plating, -/area/station/service/bar) +/area/station/maintenance/central/greater) "wKO" = ( /obj/structure/disposalpipe/segment, /obj/machinery/camera/directional/east, @@ -69562,6 +69583,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "xiT" = ( @@ -90220,7 +90242,7 @@ jNV guh cBl fJe -aJb +iPx cay fMB maK @@ -94930,7 +94952,7 @@ sXD qSa feR aZh -jdx +phk pOQ wKr wKr @@ -98007,8 +98029,8 @@ xRV jVM xjQ jVM -tGq -tGq +jVM +jVM xmt xmt xmt @@ -100320,7 +100342,7 @@ jVM jVM jVM jVM -vkh +jVM lnD fzw bKO @@ -101348,7 +101370,7 @@ jgb hRc jVM kXC -vkh +jVM dxV jDT fOq @@ -101605,7 +101627,7 @@ vGe xno jVM kXC -vkh +jVM vkh kWF wtw @@ -102119,7 +102141,7 @@ xHD xHD jVM jBu -vkh +jVM vkh vkh vkh diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 5b4edfe4443..3cc15f7deff 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -1273,6 +1273,7 @@ /obj/effect/spawner/random/maintenance, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/security) "apC" = ( @@ -21053,7 +21054,6 @@ "fiL" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, /obj/structure/chair/comfy/black{ dir = 8 }, @@ -44023,6 +44023,7 @@ /obj/item/folder/red, /obj/item/lighter, /obj/machinery/power/apc/auto_name/directional/east, +/obj/structure/cable, /turf/open/floor/wood, /area/station/service/electronic_marketing_den) "kWE" = ( @@ -49572,6 +49573,7 @@ "msx" = ( /obj/item/kirbyplants/random, /obj/structure/sign/poster/contraband/random/directional/south, +/obj/structure/cable, /turf/open/floor/wood, /area/station/service/electronic_marketing_den) "msB" = ( @@ -55831,6 +55833,7 @@ pixel_y = 3 }, /obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, /turf/open/floor/plating, /area/station/security/detectives_office/private_investigators_office) "nXY" = ( @@ -57721,7 +57724,6 @@ /turf/open/floor/iron/white, /area/station/science/research) "oxV" = ( -/obj/structure/cable, /obj/effect/mapping_helpers/broken_floor, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -58618,7 +58620,6 @@ /turf/open/floor/iron, /area/station/security/prison) "oLz" = ( -/obj/structure/cable, /obj/structure/chair/office{ dir = 4 }, @@ -59132,7 +59133,6 @@ /turf/open/floor/iron, /area/station/hallway/secondary/construction) "oRD" = ( -/obj/structure/cable, /obj/item/circuitboard/computer/secure_data, /obj/structure/frame/computer{ anchored = 1; @@ -63253,7 +63253,6 @@ "pQT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, /obj/structure/chair/comfy/brown{ dir = 8 }, @@ -72633,6 +72632,7 @@ dir = 8 }, /obj/machinery/light/small/dim/directional/north, +/obj/machinery/power/apc/auto_name/directional/north, /turf/open/floor/iron/checker, /area/station/service/hydroponics/garden/abandoned) "sgh" = ( @@ -85739,7 +85739,6 @@ /obj/item/reagent_containers/cup/watering_can, /obj/item/plant_analyzer, /obj/structure/sign/poster/contraband/kudzu/directional/south, -/obj/machinery/power/apc/auto_name/directional/south, /obj/effect/turf_decal/bot, /obj/effect/turf_decal/siding/green{ dir = 8 @@ -92440,7 +92439,6 @@ }, /area/station/science/lobby) "xeF" = ( -/obj/structure/cable, /obj/item/kirbyplants/random, /obj/machinery/light/small/dim/directional/north, /turf/open/floor/wood, diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index 280fcdfc858..d1b9a7ec350 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -216,6 +216,10 @@ /obj/machinery/announcement_system, /turf/open/floor/iron, /area/station/engineering/gravity_generator) +"bs" = ( +/obj/effect/landmark/carpspawn, +/turf/open/space/basic, +/area/space) "bu" = ( /turf/closed/wall/r_wall, /area/station/command/bridge) @@ -443,10 +447,20 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/commons/storage/primary) +"dd" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/aft) "de" = ( /obj/machinery/gulag_teleporter, /turf/open/floor/iron, /area/station/security/brig) +"df" = ( +/obj/machinery/computer/piratepad_control/civilian{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "dh" = ( /turf/closed/wall, /area/station/hallway/secondary/entry) @@ -2278,6 +2292,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/commons/storage/primary) +"Pe" = ( +/obj/effect/landmark/event_spawn, +/turf/open/floor/plating, +/area/station/construction) "Pk" = ( /obj/machinery/airalarm/directional/north, /obj/effect/mapping_helpers/airalarm/unlocked, @@ -2361,6 +2379,9 @@ /area/station/cargo/bitrunning/den) "Rb" = ( /obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters{ + id = "light_control" + }, /turf/open/floor/plating, /area/station/maintenance/aft) "Re" = ( @@ -2373,6 +2394,12 @@ /obj/machinery/byteforge, /turf/open/floor/circuit/green, /area/station/cargo/bitrunning/den) +"Rq" = ( +/obj/machinery/piratepad/civilian{ + cooldown_reduction = 99999 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "Ru" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, @@ -2483,6 +2510,13 @@ }, /turf/open/space, /area/space/nearstation) +"TY" = ( +/obj/machinery/button/door/directional/south{ + id = "light_control"; + name = "Light Control" + }, +/turf/open/floor/plating, +/area/station/maintenance/aft) "Ue" = ( /turf/closed/wall/r_wall, /area/station/cargo/bitrunning/den) @@ -6512,7 +6546,7 @@ dn dn dn dn -dn +Pe dn dn dn @@ -6704,7 +6738,7 @@ dn dn dL cN -Tt +dd bL fg aa @@ -6985,7 +7019,7 @@ Rb fg aa aa -aa +bs aa aa aa @@ -7256,7 +7290,7 @@ dl dp dE cS -Tt +TY bL aa aa @@ -8531,8 +8565,8 @@ XA vB es by -eu -eu +df +Rq qx eP fY diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index a0c0bc0964b..acc639880b1 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -28229,13 +28229,6 @@ /obj/effect/mapping_helpers/airlock/access/any/security/maintenance, /turf/open/floor/iron/smooth, /area/station/maintenance/department/security) -"jer" = ( -/obj/item/clothing/under/color/jumpskirt/white, -/obj/effect/turf_decal/trimline/neutral/filled/corner{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "jev" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -43869,8 +43862,8 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/junction{ - dir = 2 +/obj/structure/disposalpipe/junction/yjunction{ + dir = 8 }, /turf/open/floor/iron, /area/station/hallway/secondary/service) @@ -105391,7 +105384,7 @@ xpb xpb kVP xpb -jer +sKN xJG vsn bHn diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 24461464c3e..b5a7ad1ddfa 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -49,11 +49,13 @@ #define BB_BANE_BATMAN "BB_bane_batman" //yep that's it -///Hunting BB keys +//Hunting BB keys +///key that holds our current hunting target #define BB_CURRENT_HUNTING_TARGET "BB_current_hunting_target" +///key that holds our less priority hunting target #define BB_LOW_PRIORITY_HUNTING_TARGET "BB_low_priority_hunting_target" -#define BB_HUNTING_COOLDOWN "BB_HUNTING_COOLDOWN" - +///key that holds the cooldown for our hunting subtree +#define BB_HUNTING_COOLDOWN(type) "BB_HUNTING_COOLDOWN_[type]" ///Basic Mob Keys ///Targeting subtrees diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index cbc0ffdaa65..228f32e97f2 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -89,6 +89,14 @@ #define PATH_LOCK "Lock Path" #define PATH_MOON "Moon Path" +//Heretic knowledge tree defines +#define HKT_NEXT "next" +#define HKT_BAN "ban" +#define HKT_DEPTH "depth" +#define HKT_ROUTE "route" +#define HKT_UI_BGR "ui_bgr" + + /// Defines are used in /proc/has_living_heart() to report if the heretic has no heart period, no living heart, or has a living heart. #define HERETIC_NO_HEART_ORGAN -1 #define HERETIC_NO_LIVING_HEART 0 diff --git a/code/__DEFINES/dcs/signals/signals_blob.dm b/code/__DEFINES/dcs/signals/signals_blob.dm index afd4737bdd9..dac33906a3f 100644 --- a/code/__DEFINES/dcs/signals/signals_blob.dm +++ b/code/__DEFINES/dcs/signals/signals_blob.dm @@ -1,4 +1,4 @@ -/// Signal sent when a blob overmind picked a new strain (/mob/camera/blob/overmind, /datum/blobstrain/new_strain) +/// Signal sent when a blob overmind picked a new strain (/mob/eye/blob/overmind, /datum/blobstrain/new_strain) #define COMSIG_BLOB_SELECTED_STRAIN "blob_selected_strain" /// Signal sent by a blob spore when it creates a zombie (/mob/living/basic/blob_minion/spore/spore, //mob/living/basic/blob_minion/zombie/zombie) #define COMSIG_BLOB_ZOMBIFIED "blob_zombified" diff --git a/code/__DEFINES/dcs/signals/signals_datum.dm b/code/__DEFINES/dcs/signals/signals_datum.dm index 5565c143d66..696d359ac57 100644 --- a/code/__DEFINES/dcs/signals/signals_datum.dm +++ b/code/__DEFINES/dcs/signals/signals_datum.dm @@ -14,6 +14,8 @@ #define COMSIG_PREQDELETED "parent_preqdeleted" /// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called #define COMSIG_QDELETING "parent_qdeleting" +/// Called whenever an admin manually deletes an object, via the "Delete" verb, before qdel() is called: (client/deleting_admin) +#define COMSIG_ADMIN_DELETING "parent_admin_deleting" /// generic topic handler (usr, href_list) #define COMSIG_TOPIC "handle_topic" /// handler for vv_do_topic (usr, href_list) diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index 494d0541326..b3147466592 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -45,6 +45,8 @@ #define COMSIG_FISHING_CHALLENGE_ROLL_REWARD "fishing_roll_reward" /// Adjusting the difficulty of a rishing challenge, often based on the reward path #define COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY "fishing_get_difficulty" +/// From /datum/fishing_challenge/start_minigame_phase, called after the fish movement datum is spawned: (datum/fish_movement/mover) +#define COMSIG_FISHING_CHALLENGE_MOVER_INITIALIZED "fishing_mover_initialized" /// Fishing challenge completed /// Sent to the fisherman when the reward is dispensed: (reward) #define COMSIG_FISH_SOURCE_REWARD_DISPENSED "fish_source_reward_dispensed" diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 367ec946361..78b4cec5ca0 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -14,7 +14,7 @@ #define COMSIG_REAGENT_EXPOSE_ATOM "reagent_expose_atom" ///from base of [/datum/reagent/proc/expose_atom]: (/obj, reac_volume) #define COMSIG_REAGENT_EXPOSE_OBJ "reagent_expose_obj" -///from base of [/datum/reagent/proc/expose_atom]: (/mob/living, reac_volume, methods, show_message, touch_protection, /mob/camera/blob) // ovemind arg is only used by blob reagents. +///from base of [/datum/reagent/proc/expose_atom]: (/mob/living, reac_volume, methods, show_message, touch_protection, /mob/eye/blob) // ovemind arg is only used by blob reagents. #define COMSIG_REAGENT_EXPOSE_MOB "reagent_expose_mob" ///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume) #define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 954aec32350..b6aa66a5b1e 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -210,13 +210,13 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define isnewplayer(A) (istype(A, /mob/dead/new_player)) -#define isovermind(A) (istype(A, /mob/camera/blob)) +#define isovermind(A) (istype(A, /mob/eye/blob)) -#define issentientdisease(A) (istype(A, /mob/camera/disease)) +#define issentientdisease(A) (istype(A, /mob/eye/disease)) -#define iscameramob(A) (istype(A, /mob/camera)) +#define iseyemob(A) (istype(A, /mob/eye)) -#define isaicamera(A) (istype(A, /mob/camera/ai_eye)) +#define isaicamera(A) (istype(A, /mob/eye/ai_eye)) //Objects #define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index a7a95817b44..aa13298e339 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -1,14 +1,5 @@ -// Remove these once we have Byond implementation. -// ------------------------------------ -#define IS_NAN(a) (a != a) - -#define IS_INF__UNSAFE(a) (a == a && a-a != a-a) -#define IS_INF(a) (isnum(a) && IS_INF__UNSAFE(a)) - -#define IS_FINITE__UNSAFE(a) (a-a == a-a) +#define IS_FINITE__UNSAFE(a) (!isinf(a) && !isnan(a)) #define IS_FINITE(a) (isnum(a) && IS_FINITE__UNSAFE(a)) -// ------------------------------------ -// Aight dont remove the rest // Credits to Nickr5 for the useful procs I've taken from his library resource. // This file is quadruple wrapped for your pleasure diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index d5608c69687..b46b4bef31b 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -663,7 +663,8 @@ #define GRADIENT_APPLIES_TO_FACIAL_HAIR (1<<1) // Hair masks -#define HAIR_MASK_HIDE_ABOVE_45_DEG_MEDIUM "hide_above_45deg" +#define HAIR_MASK_HIDE_ABOVE_45_DEG_MEDIUM "hide_above_45deg_medium" +#define HAIR_MASK_HIDE_ABOVE_45_DEG_LOW "hide_above_45deg_low" // Height defines // - They are numbers so you can compare height values (x height < y height) diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 8cb40a1d6cc..a5d8f48cdb6 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -266,6 +266,7 @@ GLOBAL_LIST_INIT(announcer_keys, list( #define SFX_INDUSTRIAL_SCAN "industrial_scan" #define SFX_MALE_SIGH "male_sigh" #define SFX_FEMALE_SIGH "female_sigh" +#define SFX_WRITING_PEN "writing_pen" // Standard is 44.1khz #define MIN_EMOTE_PITCH 40000 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 121cf5a072d..756d78c1723 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -7,6 +7,11 @@ /// if it only allows one, and new instances just instead refresh the timer #define STATUS_EFFECT_REFRESH 3 +/// Use in status effect "duration" to make it last forever +#define STATUS_EFFECT_PERMANENT -1 +/// Use in status effect "tick_interval" to prevent it from calling tick() +#define STATUS_EFFECT_NO_TICK -1 + ///Processing flags - used to define the speed at which the status will work ///This is fast - 0.2s between ticks (I believe!) #define STATUS_EFFECT_FAST_PROCESS 0 diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm index 51283ef98a8..5edba8746f8 100644 --- a/code/__DEFINES/time.dm +++ b/code/__DEFINES/time.dm @@ -57,8 +57,6 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using #define SATURDAY "Sat" #define SUNDAY "Sun" -#define INFINITE -1 // -1 is commonly used to indicate an infinite time duration - #define MILLISECONDS *0.01 #define DECISECONDS *1 //the base unit all of these defines are scaled by, because byond uses that as a unit of measurement for some fucking reason diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 04e5aaf13b3..0045cfd111f 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -305,5 +305,8 @@ /// Trait added by style component #define STYLE_TRAIT "style" +/// Trait added by a xenobio console +#define XENOBIO_CONSOLE_TRAIT "xenobio_console_trait" + /// Trait from an engraving #define ENGRAVED_TRAIT "engraved" diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index bd8ce7d5f0e..e94d58dd693 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -316,14 +316,45 @@ rough example of the "cone" made by the 3 dirs checked loc = loc.loc return null -///Returns the last atom type in the specified loc -/proc/get_highest_loc(atom/loc, type) - var/atom/last_found = null - while(loc) - if(istype(loc, type)) - last_found = loc - loc = loc.loc - return last_found +/** + * Line of sight check! + * Spawns a dummy object and then iterates through each turf to see if it's blocked by something not handled by pass_args. + * Contains a mid_los_check, meant to be overriden by subtypes. + * args: + * * user = Origin to start at. + * * target = End point. + * * pass_args = pass_flags given to dummy object to allow it to ignore certain types of blockades. + */ +/proc/los_check(atom/movable/user, mob/target, pass_args = PASSTABLE|PASSGLASS|PASSGRILLE, datum/callback/mid_check) + var/turf/user_turf = user.loc + if(!istype(user_turf)) + return FALSE + var/obj/dummy = new(user_turf) + dummy.pass_flags |= pass_args //Grille/Glass so it can be used through common windows + var/turf/previous_step = user_turf + var/first_step = TRUE + for(var/turf/next_step as anything in (get_line(user_turf, target) - user_turf)) + if(first_step) + for(var/obj/blocker in user_turf) + if(!blocker.density || !(blocker.flags_1 & ON_BORDER_1)) + continue + if(blocker.CanPass(dummy, get_dir(user_turf, next_step))) + continue + return FALSE // Could not leave the first turf. + first_step = FALSE + if(next_step.density) + qdel(dummy) + return FALSE + for(var/atom/movable/movable as anything in next_step) + if(!movable.CanPass(dummy, get_dir(next_step, previous_step))) + qdel(dummy) + return FALSE + if(mid_check?.Invoke(user, target, pass_args, next_step, dummy) == FALSE) // specify false as it may return null if there's no check + qdel(dummy) + return FALSE + previous_step = next_step + qdel(dummy) + return TRUE ///Returns true if the src countain the atom target /atom/proc/contains(atom/target) diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm index 0e489f3f572..f78e8476b28 100644 --- a/code/__HELPERS/level_traits.dm +++ b/code/__HELPERS/level_traits.dm @@ -11,7 +11,7 @@ GLOBAL_VAR(station_level_z_scratch) // Called a lot, somewhat slow, so has its own cache #define is_station_level(z_level) \ ( \ - (z_level) && \ + (z_level) && ( \ ( \ /* The right hand side of this guarantees that we'll have the space to fill later on, while also not failing the condition */ \ (GLOB.station_levels_cache.len < (GLOB.station_level_z_scratch = (z_level)) && (GLOB.station_levels_cache.len = GLOB.station_level_z_scratch)) \ @@ -19,6 +19,7 @@ GLOBAL_VAR(station_level_z_scratch) ) \ ? (GLOB.station_levels_cache[GLOB.station_level_z_scratch] = !!SSmapping.level_trait(GLOB.station_level_z_scratch, ZTRAIT_STATION)) \ : GLOB.station_levels_cache[GLOB.station_level_z_scratch] \ + ) \ ) #define is_mining_level(z) SSmapping.level_trait(z, ZTRAIT_MINING) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index e4d84913fdc..f29ba81366c 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -539,7 +539,7 @@ GLOBAL_LIST_INIT(skin_tone_names, list( . += borg //Returns a list of AI's -/proc/active_ais(check_mind=FALSE, z = null, skip_syndicate, only_syndicate) +/proc/active_ais(check_mind = FALSE, z = null, skip_syndicate = FALSE, only_syndicate = FALSE) . = list() for(var/mob/living/silicon/ai/ai as anything in GLOB.ai_list) if(ai.stat == DEAD) @@ -551,10 +551,9 @@ GLOBAL_LIST_INIT(skin_tone_names, list( continue if(only_syndicate && !syndie_ai) continue - if(check_mind) - if(!ai.mind) - continue - if(z && !(z == ai.z) && (!is_station_level(z) || !is_station_level(ai.z))) //if a Z level was specified, AND the AI is not on the same level, AND either is off the station... + if(check_mind && !ai.mind) + continue + if(!isnull(z) && z != ai.z && (!is_station_level(z) || !is_station_level(ai.z))) //if a Z level was specified, AND the AI is not on the same level, AND either is off the station... continue . += ai @@ -612,7 +611,7 @@ GLOBAL_LIST_INIT(skin_tone_names, list( var/list/sortmob = sort_names(GLOB.mob_list) for(var/mob/living/silicon/ai/mob_to_sort in sortmob) moblist += mob_to_sort - for(var/mob/camera/mob_to_sort in sortmob) + for(var/mob/eye/mob_to_sort in sortmob) moblist += mob_to_sort for(var/mob/living/silicon/pai/mob_to_sort in sortmob) moblist += mob_to_sort diff --git a/code/__HELPERS/paths/path.dm b/code/__HELPERS/paths/path.dm index 9530a545235..950cd190684 100644 --- a/code/__HELPERS/paths/path.dm +++ b/code/__HELPERS/paths/path.dm @@ -346,7 +346,7 @@ src.can_ventcrawl = HAS_TRAIT(living_construct, TRAIT_VENTCRAWLER_ALWAYS) || HAS_TRAIT(living_construct, TRAIT_VENTCRAWLER_NUDE) src.mob_size = living_construct.mob_size src.incorporeal_move = living_construct.incorporeal_move - if(iscameramob(construct_from)) + if(iseyemob(construct_from)) src.camera_type = construct_from.type src.is_bot = isbot(construct_from) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index d278a1a359c..cd375f2b332 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -12,7 +12,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list()) var/json_file = file("[GLOB.log_directory]/round_end_data.json") // All but npcs sublists and ghost category contain only mobs with minds var/list/file_data = list("escapees" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "abandoned" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "ghosts" = list(), "additional data" = list()) - var/num_survivors = 0 //Count of non-brain non-camera mobs with mind that are alive + var/num_survivors = 0 //Count of non-brain non-eye mobs with mind that are alive var/num_escapees = 0 //Above and on centcom z var/num_shuttle_escapees = 0 //Above and on escape shuttle var/list/area/shuttle_areas @@ -32,7 +32,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list()) if(M.mind) count_only = FALSE mob_data["ckey"] = M.mind.key - if(M.stat != DEAD && !isbrain(M) && !iscameramob(M)) + if(M.stat != DEAD && !isbrain(M) && !iseyemob(M)) num_survivors++ if(EMERGENCY_ESCAPED_OR_ENDGAMED && (M.onCentCom() || M.onSyndieBase())) num_escapees++ diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 011af8345cb..1058b1d0b40 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -100,6 +100,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_EXPANDED_FOV" = TRAIT_EXPANDED_FOV, "TRAIT_EXPERT_FISHER" = TRAIT_EXPERT_FISHER, "TRAIT_EXTROVERT" = TRAIT_EXTROVERT, + "TRAIT_EVIL" = TRAIT_EVIL, "TRAIT_FAKEDEATH" = TRAIT_FAKEDEATH, "TRAIT_FASTMED" = TRAIT_FASTMED, "TRAIT_FAST_CUFFING" = TRAIT_FAST_CUFFING, diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index e9643bfff76..1b3f950edd6 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -858,6 +858,8 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /atom/movable/screen/alert/notify_action/Click() . = ..() + if(!.) + return var/atom/target = target_ref?.resolve() if(isnull(target) || !isobserver(owner) || target == owner) diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index be860caa1f0..8f8193a5045 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -17,7 +17,7 @@ /atom/movable/screen/blob/jump_to_node/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.jump_to_node() /atom/movable/screen/blob/jump_to_core @@ -27,7 +27,7 @@ /atom/movable/screen/blob/jump_to_core/MouseEntered(location,control,params) if(hud?.mymob && isovermind(hud.mymob)) - var/mob/camera/blob/B = hud.mymob + var/mob/eye/blob/B = hud.mymob if(!B.placed) name = "Place Blob Core" desc = "Attempt to place your blob core at this location." @@ -39,7 +39,7 @@ /atom/movable/screen/blob/jump_to_core/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr if(!blob.placed) blob.place_blob_core(BLOB_NORMAL_PLACEMENT) blob.transport_core() @@ -58,7 +58,7 @@ /atom/movable/screen/blob/blobbernaut/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_blobbernaut() /atom/movable/screen/blob/resource_blob @@ -75,7 +75,7 @@ /atom/movable/screen/blob/resource_blob/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_special(BLOB_STRUCTURE_RESOURCE_COST, /obj/structure/blob/special/resource, BLOB_RESOURCE_MIN_DISTANCE, TRUE) /atom/movable/screen/blob/node_blob @@ -92,7 +92,7 @@ /atom/movable/screen/blob/node_blob/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_special(BLOB_STRUCTURE_NODE_COST, /obj/structure/blob/special/node, BLOB_NODE_MIN_DISTANCE, FALSE) /atom/movable/screen/blob/factory_blob @@ -109,7 +109,7 @@ /atom/movable/screen/blob/factory_blob/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_special(BLOB_STRUCTURE_FACTORY_COST, /obj/structure/blob/special/factory, BLOB_FACTORY_MIN_DISTANCE, TRUE) /atom/movable/screen/blob/readapt_strain @@ -120,7 +120,7 @@ /atom/movable/screen/blob/readapt_strain/MouseEntered(location,control,params) if(hud?.mymob && isovermind(hud.mymob)) - var/mob/camera/blob/B = hud.mymob + var/mob/eye/blob/B = hud.mymob if(B.free_strain_rerolls) name = "[initial(name)] (FREE)" desc = "Randomly rerolls your strain for free." @@ -131,7 +131,7 @@ /atom/movable/screen/blob/readapt_strain/Click() if(isovermind(usr)) - var/mob/camera/blob/B = usr + var/mob/eye/blob/B = usr B.strain_reroll() /atom/movable/screen/blob/relocate_core @@ -147,7 +147,7 @@ /atom/movable/screen/blob/relocate_core/Click() if(isovermind(usr)) - var/mob/camera/blob/B = usr + var/mob/eye/blob/B = usr B.relocate_core() /datum/hud/blob_overmind/New(mob/owner) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 1711e0cb989..122af45163b 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -176,8 +176,16 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( /datum/hud/proc/client_refresh(datum/source) SIGNAL_HANDLER - RegisterSignal(mymob.canon_client, COMSIG_CLIENT_SET_EYE, PROC_REF(on_eye_change)) - on_eye_change(null, null, mymob.canon_client.eye) + var/client/client = mymob.canon_client + if(client.rebuild_plane_masters) + var/new_relay_loc = (client.byond_version > 515) ? "1,1" : "CENTER" + for(var/group_key as anything in master_groups) + var/datum/plane_master_group/group = master_groups[group_key] + group.relay_loc = new_relay_loc + group.rebuild_plane_masters() + client.rebuild_plane_masters = FALSE + RegisterSignal(client, COMSIG_CLIENT_SET_EYE, PROC_REF(on_eye_change)) + on_eye_change(null, null, client.eye) /datum/hud/proc/clear_client(datum/source) SIGNAL_HANDLER diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm index 900ad59bde2..a9d8dba6e13 100644 --- a/code/_onclick/overmind.dm +++ b/code/_onclick/overmind.dm @@ -1,7 +1,7 @@ // Blob Overmind Controls -/mob/camera/blob/ClickOn(atom/A, params) //Expand blob +/mob/eye/blob/ClickOn(atom/A, params) //Expand blob var/list/modifiers = params2list(params) if(LAZYACCESS(modifiers, MIDDLE_CLICK)) MiddleClickOn(A, params) @@ -19,18 +19,18 @@ if(T) expand_blob(T) -/mob/camera/blob/MiddleClickOn(atom/A) //Rally spores +/mob/eye/blob/MiddleClickOn(atom/A) //Rally spores . = ..() var/turf/T = get_turf(A) if(T) rally_spores(T) -/mob/camera/blob/CtrlClickOn(atom/A) //Create a shield +/mob/eye/blob/CtrlClickOn(atom/A) //Create a shield var/turf/T = get_turf(A) if(T) create_shield(T) -/mob/camera/blob/proc/blob_click_alt(atom/A) //Remove a blob +/mob/eye/blob/proc/blob_click_alt(atom/A) //Remove a blob var/turf/T = get_turf(A) if(T) remove_blob(T) diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index bbc21becc0f..f19d2a99e36 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -551,10 +551,10 @@ SUBSYSTEM_DEF(air) // Taking advantage of current cycle being set to negative before this run to do A->B B->A prevention for(var/turf/open/potential_diff as anything in difference_check) // I can't use 0 here, so we're gonna do this instead. If it ever breaks I'll eat my shoe - potential_diff.current_cycle = -INFINITE + potential_diff.current_cycle = -INFINITY for(var/turf/open/enemy_tile as anything in potential_diff.atmos_adjacent_turfs) // If it's already been processed, then it's already talked to us - if(enemy_tile.current_cycle == -INFINITE) + if(enemy_tile.current_cycle == -INFINITY) continue // .air instead of .return_air() because we can guarantee that the proc won't do anything if(potential_diff.air.compare(enemy_tile.air, MOLES)) diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 56832eb2c14..636895be130 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -94,7 +94,7 @@ SUBSYSTEM_DEF(blackbox) for(var/player_key in GLOB.player_details) var/datum/player_details/PD = GLOB.player_details[player_key] - record_feedback("tally", "client_byond_version", 1, PD.byond_version) + record_feedback("tally", "client_byond_version", 1, PD.full_byond_version()) /datum/controller/subsystem/blackbox/Shutdown() sealed = FALSE diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index 79b3e2d040c..0d0a7a6ab2e 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -31,7 +31,7 @@ SUBSYSTEM_DEF(economy) var/list/bank_accounts_by_id = list() /// A list of bank accounts indexed by their assigned job typepath. var/list/bank_accounts_by_job = list() - ///List of the departmental budget cards in existance. + ///List of the departmental budget cards in existence. var/list/dep_cards = list() /// A var that collects the total amount of credits owned in player accounts on station, reset and recounted on fire() var/station_total = 0 diff --git a/code/controllers/subsystem/points_of_interest.dm b/code/controllers/subsystem/points_of_interest.dm index 4280d747b61..7bec303d66a 100644 --- a/code/controllers/subsystem/points_of_interest.dm +++ b/code/controllers/subsystem/points_of_interest.dm @@ -225,7 +225,7 @@ SUBSYSTEM_DEF(points_of_interest) /datum/point_of_interest/mob_poi/proc/get_type_sort_priority() if(isAI(target)) return 0 - if(iscameramob(target)) + if(iseyemob(target)) return 1 if(ispAI(target)) return 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 3c3cc5ce1ee..e06d080df29 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -658,7 +658,7 @@ SUBSYSTEM_DEF(ticker) if(STATION_NUKED) // There was a blob on board, guess it was nuked to stop it if(length(GLOB.overminds)) - for(var/mob/camera/blob/overmind as anything in GLOB.overminds) + for(var/mob/eye/blob/overmind as anything in GLOB.overminds) if(overmind.max_count < overmind.announcement_size) continue diff --git a/code/datums/actions/items/beserk.dm b/code/datums/actions/items/beserk.dm index 43e29dbd150..01183fd8e3f 100644 --- a/code/datums/actions/items/beserk.dm +++ b/code/datums/actions/items/beserk.dm @@ -7,14 +7,27 @@ overlay_icon_state = "bg_demon_border" /datum/action/item_action/berserk_mode/Trigger(trigger_flags) - if(istype(target, /obj/item/clothing/head/hooded/berserker)) - var/obj/item/clothing/head/hooded/berserker/berserk = target - if(berserk.berserk_active) + . = ..() + if(!.) + return FALSE + var/obj/item/clothing/head/hooded/berserker/berserk = target + berserk.berserk_mode(owner) + return TRUE + +/datum/action/item_action/berserk_mode/IsAvailable(feedback = FALSE) + . = ..() + if(!.) + return FALSE + if(!istype(target, /obj/item/clothing/head/hooded/berserker)) + return FALSE + + var/obj/item/clothing/head/hooded/berserker/berserk = target + if(berserk.berserk_active) + if(feedback) to_chat(owner, span_warning("You are already berserk!")) - return - if(berserk.berserk_charge < 100) + return FALSE + if(berserk.berserk_charge < 100) + if(feedback) to_chat(owner, span_warning("You don't have a full charge.")) - return - berserk.berserk_mode(owner) - return - return ..() + return FALSE + return TRUE diff --git a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm index 5d9841a5247..649a45d4cc7 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm @@ -11,23 +11,24 @@ /// Disables AI after a certain amount of time spent with no target, you will have to enable the AI again somewhere else /datum/ai_behavior/sleep_after_targetless_time - /// Turn off AI if we spend this many seconds without a target, don't use the macro because seconds_per_tick is already in seconds - var/time_to_wait = 10 + /// Turn off AI if we spend this many seconds without a target + var/time_to_wait = 10 SECONDS /datum/ai_behavior/sleep_after_targetless_time/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - var/atom/target = controller.blackboard[target_key] - if(QDELETED(target)) - return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED - return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED + return (controller.blackboard_key_exists(target_key)) ? ( AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED) : ( AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED) -/datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, seconds_per_tick) +/datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() if (!succeeded) - controller.set_blackboard_key(BB_TARGETLESS_TIME, 0) + controller.clear_blackboard_key(BB_TARGETLESS_TIME) return - controller.add_blackboard_key(BB_TARGETLESS_TIME, seconds_per_tick) - if (controller.blackboard[BB_TARGETLESS_TIME] > time_to_wait) + + if (isnull(controller.blackboard[BB_TARGETLESS_TIME])) + controller.set_blackboard_key(BB_TARGETLESS_TIME, world.time + time_to_wait) + + if (controller.blackboard[BB_TARGETLESS_TIME] < world.time) enter_sleep(controller) + controller.clear_blackboard_key(BB_TARGETLESS_TIME) /// Disables AI, override to do additional things or something else /datum/ai_behavior/sleep_after_targetless_time/proc/enter_sleep(datum/ai_controller/controller) diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index 0ab14ff0d32..db684921281 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -26,16 +26,11 @@ /datum/ai_planning_subtree/find_and_hunt_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) if(!SPT_PROB(hunt_chance, seconds_per_tick)) return - if(controller.blackboard[BB_HUNTING_COOLDOWN] >= world.time) - return - var/mob/living/living_pawn = controller.pawn - // We can't hunt if we're indisposed - if(HAS_TRAIT(controller.pawn, TRAIT_HANDS_BLOCKED) || living_pawn.stat != CONSCIOUS) + + if(controller.blackboard[BB_HUNTING_COOLDOWN(type)] >= world.time) return - var/atom/hunted = controller.blackboard[target_key] - // We're not hunting anything, look around for something - if(isnull(hunted)) + if(!controller.blackboard_key_exists(target_key)) controller.queue_behavior(finding_behavior, target_key, hunt_targets, hunt_range) return @@ -44,7 +39,7 @@ // we may accidentally be executing another tree's hunt - not ideal, // try to set a unique target key if you have multiple - controller.queue_behavior(hunting_behavior, target_key, BB_HUNTING_COOLDOWN) + controller.queue_behavior(hunting_behavior, target_key, BB_HUNTING_COOLDOWN(type)) if(finish_planning) return SUBTREE_RETURN_FINISH_PLANNING //If we're hunting we're too busy for anything else @@ -115,7 +110,7 @@ /datum/ai_behavior/hunt_target/finish_action(datum/ai_controller/controller, succeeded, hunting_target_key, hunting_cooldown_key) . = ..() - if(succeeded) + if(succeeded && hunting_cooldown_key) controller.set_blackboard_key(hunting_cooldown_key, world.time + hunt_cooldown) else if(hunting_target_key) controller.clear_blackboard_key(hunting_target_key) diff --git a/code/datums/ai/idle_behaviors/idle_haunted.dm b/code/datums/ai/idle_behaviors/idle_haunted.dm index 5784b5104f6..756adae9313 100644 --- a/code/datums/ai/idle_behaviors/idle_haunted.dm +++ b/code/datums/ai/idle_behaviors/idle_haunted.dm @@ -10,4 +10,6 @@ return if(SPT_PROB(teleport_chance, seconds_per_tick)) playsound(item_pawn.loc, 'sound/items/haunted/ghostitemattack.ogg', 100, TRUE) + #ifndef UNIT_TESTS // hauntium teleports can cause mapping nearstation tests to fail if it teleports outside an area do_teleport(item_pawn, get_turf(item_pawn), 4, channel = TELEPORT_CHANNEL_MAGIC) + #endif diff --git a/code/datums/ai/movement/ai_movement_complete_stop.dm b/code/datums/ai/movement/ai_movement_complete_stop.dm index 2b39e162719..e9609a30dda 100644 --- a/code/datums/ai/movement/ai_movement_complete_stop.dm +++ b/code/datums/ai/movement/ai_movement_complete_stop.dm @@ -1,6 +1,6 @@ /// Come to a complete stop for a set amount of time. /datum/ai_movement/complete_stop - max_pathing_attempts = INFINITE // path all you want, you can not escape your fate + max_pathing_attempts = INFINITY // path all you want, you can not escape your fate /datum/ai_movement/complete_stop/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target, min_distance) . = ..() diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index ad60f6cd9a6..6945648a734 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -9,7 +9,7 @@ scan_desc = "partial schizophrenia" gain_text = span_notice("You feel in good company, for some reason.") lose_text = span_warning("You feel lonely again.") - var/mob/camera/imaginary_friend/friend + var/mob/eye/imaginary_friend/friend var/friend_initialized = FALSE /datum/brain_trauma/special/imaginary_friend/on_gain() @@ -76,7 +76,7 @@ friend.log_message("became [key_name(owner)]'s split personality.", LOG_GAME) message_admins("[ADMIN_LOOKUPFLW(friend)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.") -/mob/camera/imaginary_friend +/mob/eye/imaginary_friend name = "imaginary friend" real_name = "imaginary friend" move_on_shuttle = TRUE @@ -96,7 +96,7 @@ /// Whether our host and other imaginary friends can hear us only when nearby or practically anywhere. var/extended_message_range = TRUE -/mob/camera/imaginary_friend/Login() +/mob/eye/imaginary_friend/Login() . = ..() if(!. || !client) return FALSE @@ -104,7 +104,7 @@ greet() Show() -/mob/camera/imaginary_friend/proc/greet() +/mob/eye/imaginary_friend/proc/greet() to_chat(src, span_notice("You are the imaginary friend of [owner]!")) to_chat(src, span_notice("You are absolutely loyal to your friend, no matter what.")) to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what [owner] cannot.")) @@ -114,7 +114,7 @@ * * imaginary_friend_owner - The living mob that owns the imaginary friend. * * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on these prefs. */ -/mob/camera/imaginary_friend/Initialize(mapload) +/mob/eye/imaginary_friend/Initialize(mapload) . = ..() var/static/list/grantable_actions = list( /datum/action/innate/imaginary_join, @@ -123,7 +123,7 @@ grant_actions_by_list(grantable_actions) /// Links this imaginary friend to the provided mob -/mob/camera/imaginary_friend/proc/attach_to_owner(mob/living/imaginary_friend_owner) +/mob/eye/imaginary_friend/proc/attach_to_owner(mob/living/imaginary_friend_owner) owner = imaginary_friend_owner if(!owner.imaginary_group) owner.imaginary_group = list(owner) @@ -131,14 +131,14 @@ greet() /// Copies appearance from passed player prefs, or randomises them if none are provided -/mob/camera/imaginary_friend/proc/setup_appearance(datum/preferences/appearance_from_prefs = null) +/mob/eye/imaginary_friend/proc/setup_appearance(datum/preferences/appearance_from_prefs = null) if(appearance_from_prefs) INVOKE_ASYNC(src, PROC_REF(setup_friend_from_prefs), appearance_from_prefs) else INVOKE_ASYNC(src, PROC_REF(setup_friend)) /// Randomise friend name and appearance -/mob/camera/imaginary_friend/proc/setup_friend() +/mob/eye/imaginary_friend/proc/setup_friend() gender = pick(MALE, FEMALE) real_name = generate_random_name_species_based(gender, FALSE, /datum/species/human) name = real_name @@ -151,7 +151,7 @@ * Arguments: * * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on the currently selected character in them. Otherwise, it's random. */ -/mob/camera/imaginary_friend/proc/setup_friend_from_prefs(datum/preferences/appearance_from_prefs) +/mob/eye/imaginary_friend/proc/setup_friend_from_prefs(datum/preferences/appearance_from_prefs) if(!istype(appearance_from_prefs)) stack_trace("Attempted to create imaginary friend appearance from null prefs. Using random appearance.") setup_friend() @@ -181,14 +181,14 @@ Show() /// Returns all member clients of the imaginary_group -/mob/camera/imaginary_friend/proc/group_clients() +/mob/eye/imaginary_friend/proc/group_clients() var/group_clients = list() for(var/mob/person as anything in owner.imaginary_group) if(person.client) group_clients += person.client return group_clients -/mob/camera/imaginary_friend/proc/Show() +/mob/eye/imaginary_friend/proc/Show() if(!client || !owner) //nobody home return @@ -209,7 +209,7 @@ src.client.images |= current_image -/mob/camera/imaginary_friend/Destroy() +/mob/eye/imaginary_friend/Destroy() if(owner?.client) owner.client.images.Remove(human_image) if(client) @@ -217,12 +217,12 @@ owner.imaginary_group -= src return ..() -/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) +/mob/eye/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker))) create_chat_message(speaker, message_language, raw_message, spans) to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods)) -/mob/camera/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null) +/mob/eye/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null) message = get_message_mods(message, message_mods) message = capitalize(message) @@ -296,16 +296,16 @@ var/link = FOLLOW_LINK(dead_player, owner) to_chat(dead_player, "[link] [dead_rendered]") -/mob/camera/imaginary_friend/proc/clear_saypopup(image/say_popup) +/mob/eye/imaginary_friend/proc/clear_saypopup(image/say_popup) LAZYREMOVE(update_on_z, say_popup) -/mob/camera/imaginary_friend/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced, filterproof) +/mob/eye/imaginary_friend/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced, filterproof) if(!message) return say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced, filterproof) /datum/emote/imaginary_friend - mob_type_allowed_typecache = /mob/camera/imaginary_friend + mob_type_allowed_typecache = /mob/eye/imaginary_friend // We have to create our own since we can only show emotes to ourselves and our owner /datum/emote/imaginary_friend/run_emote(mob/user, params, type_override, intentional = FALSE) @@ -322,7 +322,7 @@ if(!msg) return TRUE - var/mob/camera/imaginary_friend/friend = user + var/mob/eye/imaginary_friend/friend = user var/dchatmsg = "[span_bold("[friend] (Imaginary friend of [friend.owner])")] [msg]" message = "[span_name("[user]")] [msg]" @@ -346,7 +346,7 @@ message = "points." message_param = "points at %t." -/datum/emote/imaginary_friend/point/run_emote(mob/camera/imaginary_friend/friend, params, type_override, intentional) +/datum/emote/imaginary_friend/point/run_emote(mob/eye/imaginary_friend/friend, params, type_override, intentional) message_param = initial(message_param) // reset return ..() @@ -380,7 +380,7 @@ return message // Another snowflake proc, when will they end... should have refactored it differently -/mob/camera/imaginary_friend/point_at(atom/pointed_atom) +/mob/eye/imaginary_friend/point_at(atom/pointed_atom) if(!isturf(loc)) return @@ -398,36 +398,36 @@ INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(flick_overlay_global), visual, group_clients(), 2.5 SECONDS) animate(visual, pixel_x = (tile.x - our_tile.x) * ICON_SIZE_X + pointed_atom.pixel_x, pixel_y = (tile.y - our_tile.y) * ICON_SIZE_Y + pointed_atom.pixel_y, time = 1.7, easing = EASE_OUT) -/mob/camera/imaginary_friend/create_thinking_indicator() +/mob/eye/imaginary_friend/create_thinking_indicator() if(active_thinking_indicator || active_typing_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER)) return FALSE active_thinking_indicator = image('icons/mob/effects/talk.dmi', src, "[bubble_icon]3", TYPING_LAYER) add_image_to_clients(active_thinking_indicator, group_clients()) -/mob/camera/imaginary_friend/remove_thinking_indicator() +/mob/eye/imaginary_friend/remove_thinking_indicator() if(!active_thinking_indicator) return FALSE remove_image_from_clients(active_thinking_indicator, group_clients()) active_thinking_indicator = null -/mob/camera/imaginary_friend/create_typing_indicator() +/mob/eye/imaginary_friend/create_typing_indicator() if(active_typing_indicator || active_thinking_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER)) return FALSE active_typing_indicator = image('icons/mob/effects/talk.dmi', src, "[bubble_icon]0", TYPING_LAYER) add_image_to_clients(active_typing_indicator, group_clients()) -/mob/camera/imaginary_friend/remove_typing_indicator() +/mob/eye/imaginary_friend/remove_typing_indicator() if(!active_typing_indicator) return FALSE remove_image_from_clients(active_typing_indicator, group_clients()) active_typing_indicator = null -/mob/camera/imaginary_friend/remove_all_indicators() +/mob/eye/imaginary_friend/remove_all_indicators() REMOVE_TRAIT(src, TRAIT_THINKING_IN_CHARACTER, CURRENTLY_TYPING_TRAIT) remove_thinking_indicator() remove_typing_indicator() -/mob/camera/imaginary_friend/Move(NewLoc, Dir = 0) +/mob/eye/imaginary_friend/Move(NewLoc, Dir = 0) if(world.time < move_delay) return FALSE setDir(Dir) @@ -438,11 +438,11 @@ abstract_move(NewLoc) move_delay = world.time + 1 -/mob/camera/imaginary_friend/setDir(newdir) +/mob/eye/imaginary_friend/setDir(newdir) . = ..() Show() // The image does not actually update until Show() gets called -/mob/camera/imaginary_friend/proc/recall() +/mob/eye/imaginary_friend/proc/recall() if(!owner || loc == owner) return FALSE abstract_move(owner) @@ -456,7 +456,7 @@ button_icon_state = "join" /datum/action/innate/imaginary_join/Activate() - var/mob/camera/imaginary_friend/I = owner + var/mob/eye/imaginary_friend/I = owner I.recall() /datum/action/innate/imaginary_hide @@ -468,7 +468,7 @@ button_icon_state = "hide" /datum/action/innate/imaginary_hide/proc/update_status() - var/mob/camera/imaginary_friend/I = owner + var/mob/eye/imaginary_friend/I = owner if(I.hidden) name = "Show" desc = "Become visible to your owner." @@ -480,13 +480,13 @@ build_all_button_icons() /datum/action/innate/imaginary_hide/Activate() - var/mob/camera/imaginary_friend/fake_friend = owner + var/mob/eye/imaginary_friend/fake_friend = owner fake_friend.hidden = !fake_friend.hidden fake_friend.Show() build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) /datum/action/innate/imaginary_hide/update_button_name(atom/movable/screen/movable/action_button/button, force) - var/mob/camera/imaginary_friend/fake_friend = owner + var/mob/eye/imaginary_friend/fake_friend = owner if(fake_friend.hidden) name = "Show" desc = "Become visible to your owner." @@ -496,7 +496,7 @@ return ..() /datum/action/innate/imaginary_hide/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force = FALSE) - var/mob/camera/imaginary_friend/fake_friend = owner + var/mob/eye/imaginary_friend/fake_friend = owner if(fake_friend.hidden) button_icon_state = "unhide" else @@ -515,7 +515,7 @@ random_gain = FALSE /datum/brain_trauma/special/imaginary_friend/trapped_owner/make_friend() - friend = new /mob/camera/imaginary_friend/trapped(get_turf(owner), src) + friend = new /mob/eye/imaginary_friend/trapped(get_turf(owner), src) /datum/brain_trauma/special/imaginary_friend/trapped_owner/reroll_friend() //no rerolling- it's just the last owner's hell if(friend.client) //reconnected @@ -527,17 +527,17 @@ /datum/brain_trauma/special/imaginary_friend/trapped_owner/get_ghost() //no randoms return -/mob/camera/imaginary_friend/trapped +/mob/eye/imaginary_friend/trapped name = "figment of imagination?" real_name = "figment of imagination?" desc = "The previous host of this body." -/mob/camera/imaginary_friend/trapped/greet() +/mob/eye/imaginary_friend/trapped/greet() to_chat(src, span_notice(span_bold("You have managed to hold on as a figment of the new host's imagination!"))) to_chat(src, span_notice("All hope is lost for you, but at least you may interact with your host. You do not have to be loyal to them.")) to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what the host cannot.")) -/mob/camera/imaginary_friend/trapped/setup_friend() +/mob/eye/imaginary_friend/trapped/setup_friend() real_name = "[owner.real_name]?" name = real_name human_image = icon('icons/mob/simple/lavaland/lavaland_monsters.dmi', icon_state = "curseblob") diff --git a/code/datums/components/blob_minion.dm b/code/datums/components/blob_minion.dm index fb92e1139cc..78bff449317 100644 --- a/code/datums/components/blob_minion.dm +++ b/code/datums/components/blob_minion.dm @@ -4,23 +4,23 @@ /datum/component/blob_minion dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS /// Overmind who is our boss - var/mob/camera/blob/overmind + var/mob/eye/blob/overmind /// Callback to run if overmind strain changes var/datum/callback/on_strain_changed -/datum/component/blob_minion/Initialize(mob/camera/blob/overmind, datum/callback/on_strain_changed) +/datum/component/blob_minion/Initialize(mob/eye/blob/overmind, datum/callback/on_strain_changed) . = ..() if (!isliving(parent)) return COMPONENT_INCOMPATIBLE src.on_strain_changed = on_strain_changed register_overlord(overmind) -/datum/component/blob_minion/InheritComponent(datum/component/new_comp, i_am_original, mob/camera/blob/overmind, datum/callback/on_strain_changed) +/datum/component/blob_minion/InheritComponent(datum/component/new_comp, i_am_original, mob/eye/blob/overmind, datum/callback/on_strain_changed) if (!isnull(on_strain_changed)) src.on_strain_changed = on_strain_changed register_overlord(overmind) -/datum/component/blob_minion/proc/register_overlord(mob/camera/blob/overmind) +/datum/component/blob_minion/proc/register_overlord(mob/eye/blob/overmind) if (isnull(overmind)) return src.overmind = overmind @@ -36,7 +36,7 @@ overmind_properties_changed() /// Our overmind has changed colour and properties -/datum/component/blob_minion/proc/overmind_properties_changed(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/datum/component/blob_minion/proc/overmind_properties_changed(mob/eye/blob/overmind, datum/blobstrain/new_strain) SIGNAL_HANDLER var/mob/living/living_parent = parent living_parent.update_appearance(UPDATE_ICON) @@ -139,6 +139,7 @@ /// We only speak telepathically to blobs /datum/component/blob_minion/proc/on_try_speech(mob/living/minion, message, ignore_spam, forced) SIGNAL_HANDLER + minion.log_talk(message, LOG_SAY, tag = "blob hivemind telepathy") var/spanned_message = minion.say_quote(message) var/rendered = span_blob("\[Blob Telepathy\] [minion.real_name] [spanned_message]") relay_to_list_and_observers(rendered, GLOB.blob_telepathy_mobs, minion) diff --git a/code/datums/components/bullet_intercepting.dm b/code/datums/components/bullet_intercepting.dm index 32e757c1823..f327cae9543 100644 --- a/code/datums/components/bullet_intercepting.dm +++ b/code/datums/components/bullet_intercepting.dm @@ -56,7 +56,7 @@ wearer = null /// Called when wearer is shot, check if we're going to block the hit -/datum/component/bullet_intercepting/proc/on_wearer_shot(mob/living/victim, list/signal_args, obj/projectile/bullet) +/datum/component/bullet_intercepting/proc/on_wearer_shot(mob/living/victim, obj/projectile/bullet) SIGNAL_HANDLER if (victim != wearer || victim.stat == DEAD || bullet.armor_flag != block_type) return NONE diff --git a/code/datums/components/hat_stabilizer.dm b/code/datums/components/hat_stabilizer.dm index 7a4033c3b2b..40cae0633f4 100644 --- a/code/datums/components/hat_stabilizer.dm +++ b/code/datums/components/hat_stabilizer.dm @@ -14,27 +14,32 @@ if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE + var/atom/movable/source = parent + source.flags_1 |= HAS_CONTEXTUAL_SCREENTIPS_1 + src.use_worn_icon = use_worn_icon src.pixel_y_offset = pixel_y_offset - RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) - RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_qdel)) - RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(on_secondary_attack_hand)) - RegisterSignals(parent, list(COMSIG_MODULE_GENERATE_WORN_OVERLAY, COMSIG_ITEM_GET_WORN_OVERLAYS), PROC_REF(get_worn_overlays)) + RegisterSignal(source, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(source, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) + RegisterSignal(source, COMSIG_QDELETING, PROC_REF(on_qdel)) + RegisterSignal(source, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(on_secondary_attack_hand)) + RegisterSignals(source, list(COMSIG_MODULE_GENERATE_WORN_OVERLAY, COMSIG_ITEM_GET_WORN_OVERLAYS), PROC_REF(get_worn_overlays)) + RegisterSignal(source, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item)) if (add_overlay) - RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) + RegisterSignal(source, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) /datum/component/hat_stabilizer/UnregisterFromParent() if (attached_hat) remove_hat() UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND_SECONDARY, COMSIG_MODULE_GENERATE_WORN_OVERLAY, - COMSIG_ITEM_GET_WORN_OVERLAYS, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_QDELETING)) + COMSIG_ITEM_GET_WORN_OVERLAYS, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_QDELETING, + COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM)) /datum/component/hat_stabilizer/proc/on_examine(datum/source, mob/user, list/base_examine) SIGNAL_HANDLER if(attached_hat) - base_examine += span_notice("There's \a [attached_hat] placed on [parent]. Right-click to remove it.") + base_examine += span_notice("There's \a [attached_hat] placed on [parent].") else base_examine += span_notice("There's nothing placed on [parent]. Yet.") @@ -44,11 +49,13 @@ return if(attached_hat) var/mutable_appearance/worn_overlay = attached_hat.build_worn_icon(default_layer = ABOVE_BODY_FRONT_HEAD_LAYER-0.1, default_icon_file = 'icons/mob/clothing/head/default.dmi') - worn_overlay.pixel_y = pixel_y_offset + worn_overlay.pixel_y = pixel_y_offset + attached_hat.worn_y_offset overlays += worn_overlay /datum/component/hat_stabilizer/proc/on_update_overlays(atom/movable/source, list/overlays) SIGNAL_HANDLER + if (isnull(attached_hat)) + return var/mutable_appearance/worn_overlay = use_worn_icon ? attached_hat.build_worn_icon(default_layer = ABOVE_OBJ_LAYER, default_icon_file = 'icons/mob/clothing/head/default.dmi') : mutable_appearance(attached_hat, layer = ABOVE_OBJ_LAYER) worn_overlay.pixel_y = pixel_y_offset overlays += worn_overlay @@ -86,7 +93,7 @@ RegisterSignal(hat, COMSIG_MOVABLE_MOVED, PROC_REF(remove_hat)) if (!isnull(user)) - movable_parent.balloon_alert(user, "hat attached, right-click to remove") + movable_parent.balloon_alert(user, "hat attached") if (!istype(parent, /obj/item/clothing)) movable_parent.update_appearance() @@ -146,3 +153,16 @@ if (ismob(apparel.loc)) var/mob/wearer = apparel.loc wearer.update_clothing(wearer.get_slot_by_item(apparel)) + +/datum/component/hat_stabilizer/proc/on_requesting_context_from_item(atom/source, list/context, obj/item/held_item, mob/user) + SIGNAL_HANDLER + + if(attached_hat && !held_item) + context[SCREENTIP_CONTEXT_RMB] = "Remove hat" + return CONTEXTUAL_SCREENTIP_SET + + if(istype(held_item, /obj/item/clothing/head)) + context[SCREENTIP_CONTEXT_LMB] = "Attach hat" + return CONTEXTUAL_SCREENTIP_SET + + return NONE diff --git a/code/datums/components/jetpack.dm b/code/datums/components/jetpack.dm index ccbe2b3fd4d..fd49aa2b67b 100644 --- a/code/datums/components/jetpack.dm +++ b/code/datums/components/jetpack.dm @@ -164,6 +164,12 @@ /datum/component/jetpack/proc/on_pushoff(mob/source, movement_dir, continuous_move, atom/backup) SIGNAL_HANDLER + if (get_dir(source, backup) == movement_dir || source.loc == backup.loc) + return + + if (!source.client.intended_direction || (source.client.intended_direction & get_dir(source, backup))) + return + if (!should_trigger(source) || !check_on_move.Invoke(FALSE)) return diff --git a/code/datums/components/lock_on_cursor.dm b/code/datums/components/lock_on_cursor.dm index 84e315dc6ce..1d8adedcb3c 100644 --- a/code/datums/components/lock_on_cursor.dm +++ b/code/datums/components/lock_on_cursor.dm @@ -36,7 +36,7 @@ lock_amount = 1, list/target_typecache = list(), list/immune = list(), - icon = 'icons/mob/silicon/cameramob.dmi', + icon = 'icons/mob/eyemob.dmi', icon_state = "marker", datum/callback/on_lock, datum/callback/can_target_callback, diff --git a/code/datums/components/material/material_container.dm b/code/datums/components/material/material_container.dm index e4f7941f03a..d57f5a95d1e 100644 --- a/code/datums/components/material/material_container.dm +++ b/code/datums/components/material/material_container.dm @@ -274,7 +274,7 @@ * * user - the mob inserting this item * * context - the atom performing the operation, this is the last argument sent in COMSIG_MATCONTAINER_ITEM_CONSUMED and is used mostly for silo logging */ -/datum/component/material_container/proc/user_insert(obj/item/held_item, mob/living/user, atom/context = parent, forced_type = FALSE) +/datum/component/material_container/proc/user_insert(obj/item/held_item, mob/living/user, atom/context = parent) set waitfor = FALSE . = 0 @@ -312,7 +312,7 @@ if(SEND_SIGNAL(src, COMSIG_MATCONTAINER_PRE_USER_INSERT, target_item, user) & MATCONTAINER_BLOCK_INSERT) continue //item is either indestructible, not allowed for redemption or not in the allowed types - if((target_item.resistance_flags & INDESTRUCTIBLE) || (target_item.item_flags & NO_MAT_REDEMPTION) || (allowed_item_typecache && !is_type_in_typecache(target_item, allowed_item_typecache) && !forced_type)) + if((target_item.resistance_flags & INDESTRUCTIBLE) || (target_item.item_flags & NO_MAT_REDEMPTION) || (allowed_item_typecache && !is_type_in_typecache(target_item, allowed_item_typecache))) if(!(mat_container_flags & MATCONTAINER_SILENT)) var/list/status_data = chat_msgs["[MATERIAL_INSERT_ITEM_FAILURE]"] || list() var/list/item_data = status_data[target_item.name] || list() diff --git a/code/datums/components/material/remote_materials.dm b/code/datums/components/material/remote_materials.dm index 8ae52069c1b..65ba94e8b02 100644 --- a/code/datums/components/material/remote_materials.dm +++ b/code/datums/components/material/remote_materials.dm @@ -23,8 +23,6 @@ handles linking back and forth. var/mat_container_flags = NONE ///List of signals to hook onto the local container var/list/mat_container_signals - ///Typecache for items that the silo will accept through this remote no matter what - var/list/whitelist_typecache /datum/component/remote_materials/Initialize( mapload, @@ -32,7 +30,6 @@ handles linking back and forth. force_connect = FALSE, mat_container_flags = NONE, list/mat_container_signals = null, - list/whitelist_typecache = null ) if (!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -40,7 +37,6 @@ handles linking back and forth. src.allow_standalone = allow_standalone src.mat_container_flags = mat_container_flags src.mat_container_signals = mat_container_signals - src.whitelist_typecache = whitelist_typecache RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(OnMultitool)) @@ -48,11 +44,9 @@ handles linking back and forth. var/connect_to_silo = FALSE if(force_connect || (mapload && is_station_level(T.z))) connect_to_silo = TRUE - if(!(mat_container_flags & MATCONTAINER_NO_INSERT)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, TYPE_PROC_REF(/datum/component/remote_materials, SiloAttackBy)) if(mapload) // wait for silo to initialize during mapload - addtimer(CALLBACK(src, PROC_REF(_PrepareStorage), connect_to_silo)) + SSticker.OnRoundstart(CALLBACK(src, PROC_REF(_PrepareStorage), connect_to_silo)) else //directly register in round _PrepareStorage(connect_to_silo) @@ -70,17 +64,19 @@ handles linking back and forth. silo = GLOB.ore_silo_default if (silo) silo.ore_connected_machines += src - mat_container = silo.GetComponent(/datum/component/material_container) + mat_container = silo.materials + if(!(mat_container_flags & MATCONTAINER_NO_INSERT)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_insert)) + if (!mat_container && allow_standalone) _MakeLocal() /datum/component/remote_materials/Destroy() - if (silo) - silo.ore_connected_machines -= src - silo.holds -= src - silo = null - UnregisterSignal(parent, COMSIG_ATOM_ATTACKBY) + if(silo) + allow_standalone = FALSE + disconnect_from(silo) mat_container = null + return ..() /datum/component/remote_materials/proc/_MakeLocal() @@ -97,16 +93,12 @@ handles linking back and forth. allowed_items = /obj/item/stack \ ) - if (whitelist_typecache) - mat_container.allowed_item_typecache |= whitelist_typecache - -/datum/component/remote_materials/proc/toggle_holding(force_hold = FALSE) +/// Adds/Removes this connection from the silo +/datum/component/remote_materials/proc/toggle_holding() if(isnull(silo)) return - if(force_hold) - silo.holds[src] = TRUE - else if(!silo.holds[src]) + if(!silo.holds[src]) silo.holds[src] = TRUE else silo.holds -= src @@ -129,28 +121,17 @@ handles linking back and forth. * old_silo- The silo we are trying to disconnect from */ /datum/component/remote_materials/proc/disconnect_from(obj/machinery/ore_silo/old_silo) - if (!old_silo || silo != old_silo) + if (QDELETED(old_silo) || silo != old_silo) return + + UnregisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION) silo.ore_connected_machines -= src silo = null mat_container = null - UnregisterSignal(parent, COMSIG_ATOM_ATTACKBY) + if (allow_standalone) _MakeLocal() -///Insert mats into silo -/datum/component/remote_materials/proc/SiloAttackBy(datum/source, obj/item/target, mob/living/user) - SIGNAL_HANDLER - - //Allows you to attack the machine with iron sheets for e.g. - if(!(mat_container_flags & MATCONTAINER_ANY_INTENT) && user.combat_mode) - return - - if(silo) - mat_container.user_insert(target, user, parent, (whitelist_typecache && is_type_in_typecache(target, whitelist_typecache))) - - return COMPONENT_NO_AFTERATTACK - /datum/component/remote_materials/proc/OnMultitool(datum/source, mob/user, obj/item/multitool/M) SIGNAL_HANDLER @@ -182,10 +163,24 @@ handles linking back and forth. silo.ore_connected_machines += src mat_container = new_container if(!(mat_container_flags & MATCONTAINER_NO_INSERT)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, TYPE_PROC_REF(/datum/component/remote_materials, SiloAttackBy)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_insert)) to_chat(user, span_notice("You connect [parent] to [silo] from the multitool's buffer.")) return ITEM_INTERACT_SUCCESS +///Insert mats into silo +/datum/component/remote_materials/proc/on_item_insert(datum/source, mob/living/user, obj/item/target) + SIGNAL_HANDLER + + //Allows you to attack the machine with iron sheets for e.g. + if(!(mat_container_flags & MATCONTAINER_ANY_INTENT) && user.combat_mode) + return + + if(silo) + mat_container.user_insert(target, user, parent) + + return ITEM_INTERACT_SUCCESS + + /** * Checks if the param silo is in the same level as this components parent i.e. connected machine, rcd, etc * diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm index bb72654f978..080ee58a0f8 100644 --- a/code/datums/components/omen.dm +++ b/code/datums/components/omen.dm @@ -106,7 +106,7 @@ var/has_watchers = FALSE for(var/mob/viewer in viewers(our_guy, world.view)) - if(viewer.client) + if(viewer.client && !viewer.client.is_afk()) has_watchers = TRUE break if(!has_watchers) @@ -115,7 +115,9 @@ if(!prob(8 * effective_luck)) return - var/our_guy_pos = get_turf(living_guy) + var/turf/open/our_guy_pos = living_guy.loc + if(!isopenturf(our_guy_pos)) + return for(var/obj/machinery/door/airlock/darth_airlock in our_guy_pos) if(darth_airlock.locked || !darth_airlock.hasPower()) continue diff --git a/code/datums/components/parry.dm b/code/datums/components/parry.dm index 98bc9e3a84d..2486796d378 100644 --- a/code/datums/components/parry.dm +++ b/code/datums/components/parry.dm @@ -86,10 +86,9 @@ return parriers[user] = world.time + grace_period -/datum/component/parriable_projectile/proc/before_hit(obj/projectile/source, list/bullet_args) +/datum/component/parriable_projectile/proc/before_hit(obj/projectile/source, mob/living/user) SIGNAL_HANDLER - var/mob/user = bullet_args[2] if (!istype(user) || !parriers[user] || parried) return parriers -= user diff --git a/code/datums/components/profound_fisher.dm b/code/datums/components/profound_fisher.dm index 9638af4a8f2..cc7e87aeb40 100644 --- a/code/datums/components/profound_fisher.dm +++ b/code/datums/components/profound_fisher.dm @@ -2,15 +2,18 @@ /datum/component/profound_fisher ///the fishing rod this mob will use var/obj/item/fishing_rod/mob_fisher/our_rod + ///Wether we should delete the fishing rod along with the component or replace it if it's somehow removed from the parent + var/delete_rod_when_deleted = TRUE -/datum/component/profound_fisher/Initialize(our_rod) +/datum/component/profound_fisher/Initialize(our_rod, delete_rod_when_deleted = TRUE) var/isgloves = istype(parent, /obj/item/clothing/gloves) if(!isliving(parent) && !isgloves) return COMPONENT_INCOMPATIBLE src.our_rod = our_rod || new(parent) src.our_rod.internal = TRUE + src.delete_rod_when_deleted = delete_rod_when_deleted ADD_TRAIT(src.our_rod, TRAIT_NOT_BARFABLE, REF(src)) - RegisterSignal(src.our_rod, COMSIG_QDELETING, PROC_REF(on_rod_qdel)) + RegisterSignal(src.our_rod, COMSIG_MOVABLE_MOVED, PROC_REF(on_rod_moved)) if(!isgloves) RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack)) @@ -37,14 +40,26 @@ examine_list += span_info("When [EXAMINE_HINT("held")] or [EXAMINE_HINT("equipped")], [EXAMINE_HINT("right-click")] with a empty hand to open the integrated fishing rod interface.") examine_list += span_tinynoticeital("To fish, you need to turn combat mode off.") -/datum/component/profound_fisher/proc/on_rod_qdel(datum/source) +///Handles replacing the fishing rod if somehow removed from the parent movable if delete_rod_when_deleted is TRUE, otherwise delete the component. +/datum/component/profound_fisher/proc/on_rod_moved(datum/source) SIGNAL_HANDLER - qdel(src) + if(QDELETED(src) || our_rod.loc == parent) + return + if(delete_rod_when_deleted) + UnregisterSignal(our_rod, COMSIG_MOVABLE_MOVED) + if(!QDELETED(our_rod)) + qdel(our_rod) + our_rod = new our_rod.type(parent) + else + qdel(src) /datum/component/profound_fisher/Destroy() - our_rod.internal = FALSE - UnregisterSignal(our_rod, COMSIG_QDELETING) - REMOVE_TRAIT(our_rod, TRAIT_NOT_BARFABLE, REF(src)) + UnregisterSignal(our_rod, COMSIG_MOVABLE_MOVED) + if(!delete_rod_when_deleted) + our_rod.internal = FALSE + REMOVE_TRAIT(our_rod, TRAIT_NOT_BARFABLE, REF(src)) + else if(!QDELETED(our_rod)) + QDEL_NULL(our_rod) our_rod = null return ..() diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 7bbeaf747da..fe723e4e804 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -583,7 +583,7 @@ RegisterSignal(parent, COMSIG_PROJECTILE_PREHIT, PROC_REF(on_bullet_hit)) RegisterSignal(parent, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(on_attacked)) -/datum/component/riding/creature/raptor/proc/on_bullet_hit(atom/target, list/bullet_args, obj/projectile/hit_projectile) +/datum/component/riding/creature/raptor/proc/on_bullet_hit(atom/target, obj/projectile/hit_projectile) SIGNAL_HANDLER if(hit_projectile.armor_flag == ENERGY) diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm index bb3054aea6a..9c74920a862 100644 --- a/code/datums/components/shell.dm +++ b/code/datums/components/shell.dm @@ -376,7 +376,7 @@ return COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT /** - * Determines if a user is authorized to see the existance of this shell. Returns false if they are not + * Determines if a user is authorized to see the existence of this shell. Returns false if they are not * * Arguments: * * user - The user to check if they are authorized diff --git a/code/datums/components/wormborn.dm b/code/datums/components/wormborn.dm index 1841dbf38cc..05f833fc28f 100644 --- a/code/datums/components/wormborn.dm +++ b/code/datums/components/wormborn.dm @@ -50,7 +50,7 @@ /mob/living/basic/wizard_worm/has_gravity(turf/gravity_turf) return TRUE -/mob/living/basic/wizard_worm/can_be_pulled() +/mob/living/basic/wizard_worm/can_be_pulled(user, force) return FALSE /mob/living/basic/wizard_worm/Initialize(mapload, spawn_bodyparts = TRUE) diff --git a/code/datums/elements/cuffsnapping.dm b/code/datums/elements/cuffsnapping.dm index df445f4acc9..1abdc4a7a6b 100644 --- a/code/datums/elements/cuffsnapping.dm +++ b/code/datums/elements/cuffsnapping.dm @@ -42,13 +42,20 @@ src.snap_time_strong = snap_time_strong RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(target, COMSIG_ITEM_ATTACK , PROC_REF(try_cuffsnap_target)) + RegisterSignal(target, COMSIG_ITEM_ATTACK_SECONDARY, PROC_REF(try_cuffsnap_target)) + RegisterSignal(target, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, PROC_REF(add_item_context)) /datum/element/cuffsnapping/Detach(datum/target) - UnregisterSignal(target, list(COMSIG_ITEM_ATTACK, COMSIG_ATOM_EXAMINE)) - + UnregisterSignal(target, list(COMSIG_ITEM_ATTACK_SECONDARY, COMSIG_ATOM_EXAMINE, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET)) return ..() +/datum/element/cuffsnapping/proc/add_item_context(obj/item/source, list/context, mob/living/carbon/target, mob/living/user) + SIGNAL_HANDLER + if(!iscarbon(target) || !target.handcuffed) + return NONE + context[SCREENTIP_CONTEXT_RMB] = "Cut Restraints" + return CONTEXTUAL_SCREENTIP_SET + ///signal called on parent being examined /datum/element/cuffsnapping/proc/on_examine(datum/target, mob/user, list/examine_list) SIGNAL_HANDLER @@ -56,7 +63,7 @@ var/examine_string if(isnull(snap_time_weak)) return - examine_string = "It looks like it could cut zipties or cable restraints off someone in [snap_time_weak] seconds" + examine_string = "It looks like it could be used to cut zipties or cable restraints off someone in [snap_time_weak] seconds" if(!isnull(snap_time_strong)) examine_string += ", and handcuffs in [snap_time_strong] seconds." @@ -65,7 +72,7 @@ examine_list += span_notice(examine_string) -/datum/element/cuffsnapping/proc/try_cuffsnap_target(obj/item/cutter, mob/living/carbon/target, mob/cutter_user, params) +/datum/element/cuffsnapping/proc/try_cuffsnap_target(obj/item/cutter, mob/living/carbon/target, mob/living/cutter_user, params) SIGNAL_HANDLER if(!istype(target)) //we aren't the kind of mob that can even have cuffs, so we skip. diff --git a/code/datums/elements/organ_set_bonus.dm b/code/datums/elements/organ_set_bonus.dm index 082933e409e..118c64fbeaf 100644 --- a/code/datums/elements/organ_set_bonus.dm +++ b/code/datums/elements/organ_set_bonus.dm @@ -42,8 +42,8 @@ /datum/status_effect/organ_set_bonus id = "organ_set_bonus" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK alert_type = null ///how many organs the carbon with this has in the set var/organs = 0 diff --git a/code/datums/elements/ranged_armour.dm b/code/datums/elements/ranged_armour.dm index 6d1322c687b..de5ba61d223 100644 --- a/code/datums/elements/ranged_armour.dm +++ b/code/datums/elements/ranged_armour.dm @@ -40,7 +40,7 @@ return ..() /// Modify or ignore bullet damage based on projectile properties -/datum/element/ranged_armour/proc/pre_bullet_impact(atom/parent, list/signal_args, obj/projectile/bullet) +/datum/element/ranged_armour/proc/pre_bullet_impact(atom/parent, obj/projectile/bullet) SIGNAL_HANDLER if (bullet.damage >= minimum_projectile_force || (bullet.damage_type in vulnerable_projectile_types)) return diff --git a/code/datums/elements/relay_attackers.dm b/code/datums/elements/relay_attackers.dm index fd87cb3bc2c..5b7202608ec 100644 --- a/code/datums/elements/relay_attackers.dm +++ b/code/datums/elements/relay_attackers.dm @@ -60,7 +60,7 @@ relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK) /// Even if another component blocked this hit, someone still shot at us -/datum/element/relay_attackers/proc/on_bullet_act(atom/target, list/bullet_args, obj/projectile/hit_projectile) +/datum/element/relay_attackers/proc/on_bullet_act(atom/target, obj/projectile/hit_projectile) SIGNAL_HANDLER if(!hit_projectile.is_hostile_projectile()) return diff --git a/code/datums/elements/tenacious.dm b/code/datums/elements/tenacious.dm index 4d906812c13..35dd5774cf4 100644 --- a/code/datums/elements/tenacious.dm +++ b/code/datums/elements/tenacious.dm @@ -18,6 +18,9 @@ /datum/element/tenacious/Detach(datum/target) UnregisterSignal(target, COMSIG_MOB_STATCHANGE) REMOVE_TRAIT(target, TRAIT_TENACIOUS, ELEMENT_TRAIT(type)) + var/mob/living/carbon/human/valid_target = target + if(valid_target.remove_movespeed_modifier(/datum/movespeed_modifier/tenacious)) + valid_target.balloon_alert(valid_target, "your tenacity wears off") return ..() ///signal called by the stat of the target changing @@ -27,6 +30,5 @@ if(new_stat == SOFT_CRIT) target.balloon_alert(target, "your tenacity kicks in") target.add_movespeed_modifier(/datum/movespeed_modifier/tenacious) - else + else if(target.remove_movespeed_modifier(/datum/movespeed_modifier/tenacious)) target.balloon_alert(target, "your tenacity wears off") - target.remove_movespeed_modifier(/datum/movespeed_modifier/tenacious) diff --git a/code/datums/elements/watery_tile.dm b/code/datums/elements/watery_tile.dm index 6e32c7bb155..36e893fe0fc 100644 --- a/code/datums/elements/watery_tile.dm +++ b/code/datums/elements/watery_tile.dm @@ -51,7 +51,7 @@ /datum/status_effect/watery_tile_wetness id = "watery_tile_wetness" alert_type = null - duration = -1 + duration = STATUS_EFFECT_PERMANENT status_type = STATUS_EFFECT_UNIQUE /datum/status_effect/washing_regen/tick(seconds_between_ticks) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index b979c9cda0f..b51f7097a9f 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -23,7 +23,7 @@ // argument handling // if the precision is not specified, default to 0, but apply BoH penalties - if (isnull(precision)) + if(isnull(precision)) precision = 0 switch(channel) @@ -40,7 +40,7 @@ to_chat(MM, span_warning("The bluespace interface on your bag of holding interferes with the teleport!")) // if effects are not specified and not explicitly disabled, sparks - if ((!effectin || !effectout) && !no_effects) + if((!effectin || !effectout) && !no_effects) var/datum/effect_system/spark_spread/sparks = new sparks.set_up(5, 1, teleatom) if (!effectin) @@ -78,10 +78,16 @@ return TRUE tele_play_specials(teleatom, curturf, effectin, asoundin) + var/success = teleatom.forceMove(destturf) - if(success) - log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") - tele_play_specials(teleatom, destturf, effectout, asoundout) + if(!success) + return FALSE + + . = TRUE + /* Past this point, the teleport is successful and you can assume that they're already there */ + + log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") + tele_play_specials(teleatom, destturf, effectout, asoundout) if(ismob(teleatom)) var/mob/M = teleatom @@ -90,7 +96,22 @@ SEND_SIGNAL(teleatom, COMSIG_MOVABLE_POST_TELEPORT, destination, channel) - return TRUE + //We need to be sure that the buckled mobs can teleport too + if(teleatom.has_buckled_mobs()) + for(var/mob/living/rider in teleatom.buckled_mobs) + //just in case it fails, but the mob gets unbuckled anyways even if it passes + teleatom.unbuckle_mob(rider, TRUE, FALSE) + + var/rider_success = do_teleport(rider, destturf, precision, channel=channel, no_effects=TRUE) + if(!rider_success) + continue + + if(get_turf(rider) != destturf) //precision made them teleport somewhere else + to_chat(rider, span_warning("As you reorient your senses, you realize you aren't riding [teleatom] anymore!")) + continue + + // [mob/living].forceMove() forces mobs to unbuckle, so we need to buckle them again + teleatom.buckle_mob(rider, force=TRUE) /proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound) if(!location) diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index fead0417db9..84889ad6bd9 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -1,4 +1,4 @@ -/mob/camera/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE) // If we're moving outside the space of our projector, then just... don't var/obj/machinery/holopad/H = origin if(!H?.move_hologram(eye_user, destination)) @@ -24,7 +24,7 @@ var/list/dialed_holopads ///user's eye, once connected - var/mob/camera/ai_eye/remote/holo/eye + var/mob/eye/ai_eye/remote/holo/eye ///user's hologram, once connected var/obj/effect/overlay/holo_pad_hologram/hologram ///hangup action diff --git a/code/datums/mind/initialization.dm b/code/datums/mind/initialization.dm index e3b3e8225dc..a09cb040dbe 100644 --- a/code/datums/mind/initialization.dm +++ b/code/datums/mind/initialization.dm @@ -11,8 +11,10 @@ mind.set_current(src) // There's nowhere else to set this up, mind code makes me depressed mind.antag_hud = add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/antagonist_hud, "combo_hud", mind) + RegisterSignal(src, COMSIG_ADMIN_DELETING, PROC_REF(ghost_before_admin_delete), override = TRUE) SEND_SIGNAL(src, COMSIG_MOB_MIND_INITIALIZED, mind) + /mob/living/carbon/mind_initialize() ..() last_mind = mind @@ -35,3 +37,8 @@ . = ..() mind.set_assigned_role(SSjob.get_job_type(/datum/job/personal_ai)) mind.special_role = "" + +/// Signal proc for [COMSIG_ADMIN_DELETING], to ghostize a mob beforehand if an admin is manually deleting it. +/mob/proc/ghost_before_admin_delete(datum/source) + SIGNAL_HANDLER + ghostize(can_reenter_corpse = FALSE) diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index 2a43cc3c44f..eaf2ccce832 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -502,7 +502,7 @@ ///The max intensity of a nebula VAR_PROTECTED/maximum_nebula_intensity = 2 HOURS ///How long it takes to go to the next nebula level/intensity - VAR_PROTECTED/intensity_increment_time = INFINITE + VAR_PROTECTED/intensity_increment_time = 30 MINUTES ///Objects that we use to calculate the current shielding level var/list/shielding = list() diff --git a/code/datums/status_effects/_status_effect.dm b/code/datums/status_effects/_status_effect.dm index 637f2c3a076..df525fa8c81 100644 --- a/code/datums/status_effects/_status_effect.dm +++ b/code/datums/status_effects/_status_effect.dm @@ -6,7 +6,7 @@ /// When set initially / in on_creation, this is how long the status effect lasts in deciseconds. /// While processing, this becomes the world.time when the status effect will expire. /// -1 = infinite duration. - var/duration = -1 + var/duration = STATUS_EFFECT_PERMANENT /// When set initially / in on_creation, this is how long between [proc/tick] calls in deciseconds. /// Note that this cannot be faster than the processing subsystem you choose to fire the effect on. (See: [var/processing_speed]) /// While processing, this becomes the world.time when the next tick will occur. @@ -50,9 +50,13 @@ LAZYADD(owner.status_effects, src) RegisterSignal(owner, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(remove_effect_on_heal)) - if(duration != -1) + if(duration == INFINITY) + // we will optionally allow INFINITY, because i imagine it'll be convenient in some places, + // but we'll still set it to -1 / STATUS_EFFECT_PERMANENT for proper unified handling + duration = STATUS_EFFECT_PERMANENT + if(duration != STATUS_EFFECT_PERMANENT) duration = world.time + duration - if(tick_interval != -1) + if(tick_interval != STATUS_EFFECT_NO_TICK) tick_interval = world.time + tick_interval if(alert_type) @@ -107,7 +111,7 @@ qdel(src) return - if(tick_interval != -1 && tick_interval < world.time) + if(tick_interval != STATUS_EFFECT_NO_TICK && tick_interval < world.time) var/tick_length = initial(tick_interval) tick(tick_length / (1 SECONDS)) tick_interval = world.time + tick_length @@ -115,7 +119,7 @@ // tick deleted us, no need to continue return - if(duration != -1) + if(duration != STATUS_EFFECT_PERMANENT) if(duration < world.time) qdel(src) return @@ -170,7 +174,7 @@ /// has its duration refreshed in apply_status_effect - is passed New() args /datum/status_effect/proc/refresh(effect, ...) var/original_duration = initial(duration) - if(original_duration == -1) + if(original_duration == STATUS_EFFECT_PERMANENT) return duration = world.time + original_duration @@ -194,7 +198,7 @@ /// Remove [seconds] of duration from the status effect, qdeling / ending if we eclipse the current world time. /datum/status_effect/proc/remove_duration(seconds) - if(duration == -1) // Infinite duration + if(duration == STATUS_EFFECT_PERMANENT) // Infinite duration return FALSE duration -= seconds @@ -213,6 +217,18 @@ SHOULD_CALL_PARENT(FALSE) return +/datum/status_effect/vv_edit_var(var_name, var_value) + . = ..() + if(!.) + return + if(var_name == NAMEOF(src, duration)) + if(var_value == INFINITY) + duration = STATUS_EFFECT_PERMANENT + update_shown_duration() + + if(var_name == NAMEOF(src, show_duration)) + update_shown_duration() + /// Alert base type for status effect alerts /atom/movable/screen/alert/status_effect name = "Curse of Mundanity" diff --git a/code/datums/status_effects/agent_pinpointer.dm b/code/datums/status_effects/agent_pinpointer.dm index c22242be400..68b01a3eb1f 100644 --- a/code/datums/status_effects/agent_pinpointer.dm +++ b/code/datums/status_effects/agent_pinpointer.dm @@ -10,7 +10,7 @@ /datum/status_effect/agent_pinpointer id = "agent_pinpointer" - duration = -1 + duration = STATUS_EFFECT_PERMANENT tick_interval = PINPOINTER_PING_TIME alert_type = /atom/movable/screen/alert/status_effect/agent_pinpointer ///The minimum range to start pointing towards your target. diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index b1d36d47dd7..f758486c0f5 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -2,7 +2,7 @@ /datum/status_effect/his_grace id = "his_grace" - duration = -1 + duration = STATUS_EFFECT_PERMANENT tick_interval = 0.4 SECONDS alert_type = /atom/movable/screen/alert/status_effect/his_grace var/bloodlust = 0 @@ -75,7 +75,7 @@ /datum/status_effect/blooddrunk id = "blooddrunk" duration = 10 - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK alert_type = /atom/movable/screen/alert/status_effect/blooddrunk /atom/movable/screen/alert/status_effect/blooddrunk @@ -250,7 +250,7 @@ /datum/status_effect/hippocratic_oath id = "Hippocratic Oath" status_type = STATUS_EFFECT_UNIQUE - duration = -1 + duration = STATUS_EFFECT_PERMANENT tick_interval = 2.5 SECONDS alert_type = null @@ -517,7 +517,7 @@ /datum/status_effect/nest_sustenance id = "nest_sustenance" - duration = -1 + duration = STATUS_EFFECT_PERMANENT tick_interval = 0.4 SECONDS alert_type = /atom/movable/screen/alert/status_effect/nest_sustenance @@ -549,8 +549,8 @@ */ /datum/status_effect/blessing_of_insanity id = "blessing_of_insanity" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK alert_type = /atom/movable/screen/alert/status_effect/blessing_of_insanity /atom/movable/screen/alert/status_effect/blessing_of_insanity diff --git a/code/datums/status_effects/buffs/bioware/_bioware.dm b/code/datums/status_effects/buffs/bioware/_bioware.dm index c2f7259f270..24443f4f1ee 100644 --- a/code/datums/status_effects/buffs/bioware/_bioware.dm +++ b/code/datums/status_effects/buffs/bioware/_bioware.dm @@ -6,8 +6,8 @@ /datum/status_effect/bioware id = "bioware" alert_type = null - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK /datum/status_effect/bioware/on_apply() if(!ishuman(owner)) diff --git a/code/datums/status_effects/buffs/stun_absorption.dm b/code/datums/status_effects/buffs/stun_absorption.dm index 9532d79c4f5..393a6031e83 100644 --- a/code/datums/status_effects/buffs/stun_absorption.dm +++ b/code/datums/status_effects/buffs/stun_absorption.dm @@ -9,7 +9,7 @@ */ /datum/status_effect/stun_absorption id = "absorb_stun" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK alert_type = null status_type = STATUS_EFFECT_MULTIPLE diff --git a/code/datums/status_effects/debuffs/blindness.dm b/code/datums/status_effects/debuffs/blindness.dm index fb87d2fde85..06a5a46b942 100644 --- a/code/datums/status_effects/debuffs/blindness.dm +++ b/code/datums/status_effects/debuffs/blindness.dm @@ -5,7 +5,7 @@ /// Nearsighted /datum/status_effect/grouped/nearsighted id = "nearsighted" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK alert_type = null // This is not "remove on fullheal" as in practice, // fullheal should instead remove all the sources and in turn cure this @@ -59,7 +59,7 @@ /// Blindness /datum/status_effect/grouped/blindness id = "blindness" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK alert_type = /atom/movable/screen/alert/status_effect/blind // This is not "remove on fullheal" as in practice, // fullheal should instead remove all the sources and in turn cure this diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index f634e449b6e..35c349890b1 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -8,7 +8,7 @@ //Largely negative status effects go here, even if they have small beneficial effects //STUN EFFECTS /datum/status_effect/incapacitating - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_REPLACE alert_type = null remove_on_fullheal = TRUE @@ -139,7 +139,7 @@ if(!.) return if(HAS_TRAIT(owner, TRAIT_SLEEPIMMUNE)) - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK else ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_SLEEPIMMUNE), PROC_REF(on_owner_insomniac)) @@ -156,7 +156,7 @@ /datum/status_effect/incapacitating/sleeping/proc/on_owner_insomniac(mob/living/source) SIGNAL_HANDLER REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK ///If the mob has the TRAIT_SLEEPIMMUNE but somehow looses it we make him sleep and restart the tick() /datum/status_effect/incapacitating/sleeping/proc/on_owner_sleepy(mob/living/source) @@ -256,7 +256,7 @@ //STASIS /datum/status_effect/grouped/stasis id = "stasis" - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = /atom/movable/screen/alert/status_effect/stasis var/last_dead_time @@ -312,7 +312,7 @@ /datum/status_effect/his_wrath //does minor damage over time unless holding His Grace id = "his_wrath" - duration = -1 + duration = STATUS_EFFECT_PERMANENT tick_interval = 0.4 SECONDS alert_type = /atom/movable/screen/alert/status_effect/his_wrath @@ -335,7 +335,7 @@ /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes id = "cult_ghost" - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null /datum/status_effect/cultghost/on_apply() @@ -404,7 +404,7 @@ id = "neck_slice" status_type = STATUS_EFFECT_UNIQUE alert_type = null - duration = -1 + duration = STATUS_EFFECT_PERMANENT /datum/status_effect/neck_slice/on_apply() if(!ishuman(owner)) @@ -529,7 +529,7 @@ /datum/status_effect/gonbola_pacify id = "gonbolaPacify" status_type = STATUS_EFFECT_MULTIPLE - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK alert_type = null /datum/status_effect/gonbola_pacify/on_apply() diff --git a/code/datums/status_effects/debuffs/dna_transformation.dm b/code/datums/status_effects/debuffs/dna_transformation.dm index 243d20b1917..afb8be445c8 100644 --- a/code/datums/status_effects/debuffs/dna_transformation.dm +++ b/code/datums/status_effects/debuffs/dna_transformation.dm @@ -2,7 +2,7 @@ /// then turns them back to how they were before transformation. /datum/status_effect/temporary_transformation id = "temp_dna_transformation" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK duration = 1 MINUTES // set in on creation, this just needs to be any value to process alert_type = null /// A reference to a COPY of the DNA that the mob will be transformed into. @@ -16,7 +16,7 @@ QDEL_NULL(old_dna) /datum/status_effect/temporary_transformation/on_creation(mob/living/new_owner, new_duration = 1 MINUTES, datum/dna/dna_to_copy) - src.duration = (new_duration == INFINITY) ? -1 : new_duration + src.duration = new_duration src.new_dna = new() src.old_dna = new() dna_to_copy.copy_dna(new_dna) @@ -83,11 +83,11 @@ // Pause if we're dead, appear dead, or in stasis if(source.stat == DEAD || HAS_TRAIT(source, TRAIT_DEATHCOMA) || HAS_TRAIT(source, TRAIT_STASIS)) - if(duration == -1) + if(duration == STATUS_EFFECT_PERMANENT) return // Already paused time_before_pause = duration - world.time - duration = -1 + duration = STATUS_EFFECT_PERMANENT // Resume if we're none of the above and also were paused else if(time_before_pause != -1) diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index a575d2619fe..83510a2ded2 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -1,5 +1,5 @@ /datum/status_effect/fire_handler - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null status_type = STATUS_EFFECT_REFRESH //Custom code on_remove_on_mob_delete = TRUE diff --git a/code/datums/status_effects/debuffs/genetic_damage.dm b/code/datums/status_effects/debuffs/genetic_damage.dm index 21b6f1db218..21435f476c0 100644 --- a/code/datums/status_effects/debuffs/genetic_damage.dm +++ b/code/datums/status_effects/debuffs/genetic_damage.dm @@ -5,7 +5,7 @@ id = "genetic_damage" alert_type = null status_type = STATUS_EFFECT_REFRESH // New effects will add to total_damage - duration = -1 + duration = STATUS_EFFECT_PERMANENT tick_interval = 2 SECONDS on_remove_on_mob_delete = TRUE // Need to unregister from owner, be_replaced() would cause runtimes remove_on_fullheal = TRUE diff --git a/code/datums/status_effects/debuffs/hallucination.dm b/code/datums/status_effects/debuffs/hallucination.dm index 22c74f72cbd..3f24ab02e60 100644 --- a/code/datums/status_effects/debuffs/hallucination.dm +++ b/code/datums/status_effects/debuffs/hallucination.dm @@ -82,7 +82,7 @@ /datum/status_effect/hallucination/sanity id = "low sanity" status_type = STATUS_EFFECT_REFRESH - duration = -1 // This lasts "forever", only goes away with sanity gain + duration = STATUS_EFFECT_PERMANENT // This lasts "forever", only goes away with sanity gain /datum/status_effect/hallucination/sanity/on_health_scan(datum/source, list/render_list, advanced, mob/user, mode, tochat) return diff --git a/code/datums/status_effects/debuffs/hooked.dm b/code/datums/status_effects/debuffs/hooked.dm index 3eb7caf1c37..d7fcb2b1821 100644 --- a/code/datums/status_effects/debuffs/hooked.dm +++ b/code/datums/status_effects/debuffs/hooked.dm @@ -1,8 +1,8 @@ ///Status effect applied when casting a fishing rod at someone, provided the attached fishing hook allows it. /datum/status_effect/grouped/hooked id = "hooked" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_MULTIPLE alert_type = /atom/movable/screen/alert/status_effect/hooked diff --git a/code/datums/status_effects/debuffs/speech_debuffs.dm b/code/datums/status_effects/debuffs/speech_debuffs.dm index 991c3af6577..fc1afa30479 100644 --- a/code/datums/status_effects/debuffs/speech_debuffs.dm +++ b/code/datums/status_effects/debuffs/speech_debuffs.dm @@ -2,7 +2,7 @@ id = null alert_type = null remove_on_fullheal = TRUE - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK /// If TRUE, TTS will say the original message rather than what we changed it to var/make_tts_message_original = FALSE /// If set, this will be appended to the TTS filter of the message diff --git a/code/datums/status_effects/debuffs/stamcrit.dm b/code/datums/status_effects/debuffs/stamcrit.dm index a85c40f7b6d..901ebf62ad3 100644 --- a/code/datums/status_effects/debuffs/stamcrit.dm +++ b/code/datums/status_effects/debuffs/stamcrit.dm @@ -1,8 +1,8 @@ /datum/status_effect/incapacitating/stamcrit status_type = STATUS_EFFECT_UNIQUE // Lasts until we go back to 0 stamina, which is handled by the mob - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK /// Cooldown between displaying warning messages that we hit diminishing returns COOLDOWN_DECLARE(warn_cd) /// A counter that tracks every time we've taken enough damage to trigger diminishing returns diff --git a/code/datums/status_effects/debuffs/tower_of_babel.dm b/code/datums/status_effects/debuffs/tower_of_babel.dm index a56ea1ac6d9..bd2d38e7546 100644 --- a/code/datums/status_effects/debuffs/tower_of_babel.dm +++ b/code/datums/status_effects/debuffs/tower_of_babel.dm @@ -32,7 +32,7 @@ // Used by wizard magic and tower of babel event /datum/status_effect/tower_of_babel/magical id = "tower_of_babel_magic" // do we need a new id? - duration = -1 + duration = STATUS_EFFECT_PERMANENT trait_source = TRAUMA_TRAIT /datum/status_effect/tower_of_babel/magical/on_apply() diff --git a/code/datums/status_effects/drug_effects.dm b/code/datums/status_effects/drug_effects.dm index bb86e2b014b..849d3cb4d1e 100644 --- a/code/datums/status_effects/drug_effects.dm +++ b/code/datums/status_effects/drug_effects.dm @@ -1,6 +1,6 @@ /datum/status_effect/woozy id = "woozy" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/woozy @@ -14,7 +14,7 @@ /datum/status_effect/high_blood_pressure id = "high_blood_pressure" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/high_blood_pressure @@ -40,7 +40,7 @@ /datum/status_effect/seizure id = "seizure" - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/seizure diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm index f06a289da78..1dc39e81bf2 100644 --- a/code/datums/status_effects/gas.dm +++ b/code/datums/status_effects/gas.dm @@ -55,7 +55,7 @@ /datum/status_effect/freon/lasting id = "lasting_frozen" - duration = -1 + duration = STATUS_EFFECT_PERMANENT /datum/status_effect/hypernob_protection id = "hypernob_protection" diff --git a/code/datums/status_effects/limited_effect.dm b/code/datums/status_effects/limited_effect.dm index 0f56e72da52..b577248d35e 100644 --- a/code/datums/status_effects/limited_effect.dm +++ b/code/datums/status_effects/limited_effect.dm @@ -1,7 +1,7 @@ /// These effects reapply their on_apply() effect when refreshed while stacks < max_stacks. /datum/status_effect/limited_buff id = "limited_buff" - duration = -1 + duration = STATUS_EFFECT_PERMANENT status_type = STATUS_EFFECT_REFRESH ///How many stacks we currently have var/stacks = 1 diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index a6607cd7797..f8814c56f14 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -2,8 +2,8 @@ /datum/status_effect/crusher_damage id = "crusher_damage" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = null /// How much damage? @@ -71,7 +71,7 @@ /datum/status_effect/in_love id = "in_love" - duration = -1 + duration = STATUS_EFFECT_PERMANENT status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/in_love var/hearts @@ -146,8 +146,8 @@ // heldup is for the person being aimed at /datum/status_effect/grouped/heldup id = "heldup" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_MULTIPLE alert_type = /atom/movable/screen/alert/status_effect/heldup @@ -167,8 +167,8 @@ // holdup is for the person aiming /datum/status_effect/holdup id = "holdup" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/holdup @@ -187,8 +187,8 @@ // this status effect is used to negotiate the high-fiving capabilities of all concerned parties /datum/status_effect/offering id = "offering" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = null /// The people who were offered this item at the start @@ -349,8 +349,8 @@ //this effect gives the user an alert they can use to surrender quickly /datum/status_effect/grouped/surrender id = "surrender" - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/surrender @@ -394,7 +394,7 @@ /datum/status_effect/caltropped id = "caltropped" duration = 1 SECONDS - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK status_type = STATUS_EFFECT_REFRESH alert_type = null @@ -596,8 +596,8 @@ /datum/status_effect/gutted id = "gutted" alert_type = null - duration = -1 - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT + tick_interval = STATUS_EFFECT_NO_TICK /datum/status_effect/gutted/on_apply() RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(stop_gutting)) @@ -622,7 +622,7 @@ /datum/status_effect/shower_regen id = "shower_regen" - duration = -1 + duration = STATUS_EFFECT_PERMANENT status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/shower_regen /// How many heals from washing. diff --git a/code/datums/status_effects/stacking_effect.dm b/code/datums/status_effects/stacking_effect.dm index b0d00a92ba0..3ed7846f6ff 100644 --- a/code/datums/status_effects/stacking_effect.dm +++ b/code/datums/status_effects/stacking_effect.dm @@ -2,7 +2,7 @@ /// Status effects that can stack. /datum/status_effect/stacking id = "stacking_base" - duration = -1 // Only removed under specific conditions. + duration = STATUS_EFFECT_PERMANENT // Only removed under specific conditions. tick_interval = 1 SECONDS // Deciseconds between decays, once decay starts alert_type = null /// How many stacks are currently accumulated. diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index 30361dc9cf1..8d36aaf287f 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -28,7 +28,7 @@ /datum/status_effect/limp id = "limp" status_type = STATUS_EFFECT_REPLACE - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK alert_type = /atom/movable/screen/alert/status_effect/limp var/msg_stage = 0//so you dont get the most intense messages immediately /// The left leg of the limping person diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index eff2ff42fee..7fa51289713 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -47,6 +47,8 @@ var/rustle_vary = TRUE /// Path for the item's rustle sound. var/rustle_sound = SFX_RUSTLE + /// Path for the item's rustle sound when removing items. + var/remove_rustle_sound = null /// The sound to play when we open/access the storage var/open_sound var/open_sound_vary = TRUE @@ -563,7 +565,10 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) thing.forceMove(remove_to_loc) if(do_rustle && !silent) - playsound(parent, SFX_RUSTLE, 50, TRUE, -5) + if(remove_rustle_sound) + playsound(parent, remove_rustle_sound, 50, TRUE, -5) + else + playsound(parent, rustle_sound, 50, TRUE, -5) else thing.moveToNullspace() @@ -688,10 +693,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/on_preattack(datum/source, obj/item/thing, mob/user, params) SIGNAL_HANDLER - if(!istype(thing) || !allow_quick_gather || thing.atom_storage) + if(!istype(thing) || thing == parent.loc || !allow_quick_gather || thing.atom_storage) return if(collection_mode == COLLECT_ONE) + if(thing.loc == user) + user.dropItemToGround(thing, silent = TRUE) //this is nessassary to update any inventory slot it is attached to attempt_insert(thing, user) return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm index beb58fb1ce3..ec38d728981 100644 --- a/code/datums/wires/mulebot.dm +++ b/code/datums/wires/mulebot.dm @@ -29,18 +29,24 @@ if(WIRE_MOTOR1, WIRE_MOTOR2) if(is_cut(WIRE_MOTOR1) && is_cut(WIRE_MOTOR2)) ADD_TRAIT(mule, TRAIT_IMMOBILIZED, MOTOR_LACK_TRAIT) + holder.audible_message(span_hear("The motors of [src] go silent."), null, 1) else REMOVE_TRAIT(mule, TRAIT_IMMOBILIZED, MOTOR_LACK_TRAIT) + holder.audible_message(span_hear("The motors of [src] whir to life!"), null, 1) if(is_cut(WIRE_MOTOR1)) mule.set_varspeed(FAST_MOTOR_SPEED) + holder.audible_message(span_hear("The motors of [src] speed up!"), null, 1) else if(is_cut(WIRE_MOTOR2)) mule.set_varspeed(AVERAGE_MOTOR_SPEED) + holder.audible_message(span_hear("The motors of [src] whir."), null, 1) else mule.set_varspeed(SLOW_MOTOR_SPEED) + holder.audible_message(span_hear("The motors of [src] move gently."), null, 1) if(WIRE_AVOIDANCE) if (!isnull(source)) log_combat(source, mule, "[is_cut(WIRE_AVOIDANCE) ? "cut" : "mended"] the MULE safety wire of") + holder.audible_message(span_hear("Something inside [src] clicks ominously!"), null, 1) /datum/wires/mulebot/on_pulse(wire) var/mob/living/simple_animal/bot/mulebot/mule = holder diff --git a/code/game/atom/alternate_appearance.dm b/code/game/atom/alternate_appearance.dm index 8c50760ea45..3089f8d40b6 100644 --- a/code/game/atom/alternate_appearance.dm +++ b/code/game/atom/alternate_appearance.dm @@ -199,18 +199,24 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances) return TRUE return FALSE +/// Only shows the image to one person /datum/atom_hud/alternate_appearance/basic/one_person + /// The guy who gets to see the image var/mob/seer /datum/atom_hud/alternate_appearance/basic/one_person/mobShouldSee(mob/M) - if(M == seer) - return TRUE - return FALSE + return M == seer /datum/atom_hud/alternate_appearance/basic/one_person/New(key, image/I, options = NONE, mob/living/seer) src.seer = seer return ..() +/// Shows the image to everyone but one person +/datum/atom_hud/alternate_appearance/basic/one_person/reversed + +/datum/atom_hud/alternate_appearance/basic/one_person/reversed/mobShouldSee(mob/M) + return M != seer + /datum/atom_hud/alternate_appearance/basic/food_demands /datum/atom_hud/alternate_appearance/basic/heretic diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm index fee219f7b4b..2151e3927b9 100644 --- a/code/game/atom/atom_examine.dm +++ b/code/game/atom/atom_examine.dm @@ -1,7 +1,7 @@ /atom /// If non-null, overrides a/an/some in all cases var/article - /// Text that appears preceding the name in examine() + /// Text that appears preceding the name in [/atom/proc/examine_title] var/examine_thats = "That's" /mob/living/carbon/human @@ -11,12 +11,12 @@ examine_thats = "This is" /** - * Called when a mob examines (shift click or verb) this atom + * Called when a mob examines this atom: [/mob/verb/examinate] * * Default behaviour is to get the name and icon of the object and its reagents where * the [TRANSPARENT] flag is set on the reagents holder * - * Produces a signal [COMSIG_ATOM_EXAMINE] + * Produces a signal [COMSIG_ATOM_EXAMINE], for modifying the list returned from this proc */ /atom/proc/examine(mob/user) . = list() @@ -29,8 +29,8 @@ var/tag_string = list() for (var/atom_tag in tags_list) tag_string += (isnull(tags_list[atom_tag]) ? atom_tag : span_tooltip(tags_list[atom_tag], atom_tag)) - // Weird bit but ensures that if the final element has its own "and" we don't add another one - tag_string = english_list(tag_string, and_text = (findtext(tag_string[length(tag_string)], " and ")) ? ", " : " and ") + // some regex to ensure that we don't add another "and" if the final element's main text (not tooltip) has one + tag_string = english_list(tag_string, and_text = (findtext(tag_string[length(tag_string)], regex(@">.*?and .*?<"))) ? " " : " and ") var/post_descriptor = examine_post_descriptor(user) . += "[p_They()] [p_are()] a [tag_string] [examine_descriptor(user)][length(post_descriptor) ? " [jointext(post_descriptor, " ")]" : ""]." @@ -58,14 +58,25 @@ SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .) -/* +/** * A list of "tags" displayed after atom's description in examine. - * This should return an assoc list of tags -> tooltips for them. If item if null, then no tooltip is assigned. + * This should return an assoc list of tags -> tooltips for them. If item is null, then no tooltip is assigned. + * + * * TGUI tooltips (not the main text) in chat cannot use HTML stuff at all, so + * trying something like `ffff` will not work for tooltips. + * * For example: - * list("small" = "This is a small size class item.", "fireproof" = "This item is impervious to fire.") + * ```byond + * . = list() + * .["small"] = "It is a small item." + * .["fireproof"] = "It is made of fire-retardant materials." + * .["and conductive"] = "It's made of conductive materials and whatnot. Blah blah blah." // having "and " in the end tag's main text/key works too! + * ``` * will result in - * This is a small, fireproof item. - * where "item" is pulled from examine_descriptor() proc + * + * It is a *small*, *fireproof* *and conductive* item. + * + * where "item" is pulled from [/atom/proc/examine_descriptor] */ /atom/proc/examine_tags(mob/user) . = list() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 18dbc356d5b..e908dfa9cd9 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -523,7 +523,7 @@ /atom/movable/proc/start_pulling(atom/movable/pulled_atom, state, force = move_force, supress_message = FALSE) if(QDELETED(pulled_atom)) return FALSE - if(!(pulled_atom.can_be_pulled(src, state, force))) + if(!(pulled_atom.can_be_pulled(src, force))) return FALSE // If we're pulling something then drop what we're currently pulling and pull this instead. @@ -627,7 +627,7 @@ buckled_mob.set_glide_size(target) /** - * meant for movement with zero side effects. only use for objects that are supposed to move "invisibly" (like camera mobs or ghosts) + * meant for movement with zero side effects. only use for objects that are supposed to move "invisibly" (like eye mobs or ghosts) * if you want something to move onto a tile with a beartrap or recycler or tripmine or mouse without that object knowing about it at all, use this * most of the time you want forceMove() */ @@ -1655,7 +1655,7 @@ /atom/movable/proc/get_cell(atom/movable/interface, mob/user) return -/atom/movable/proc/can_be_pulled(user, grab_state, force) +/atom/movable/proc/can_be_pulled(user, force) if(src == user || !isturf(loc)) return FALSE if(SEND_SIGNAL(src, COMSIG_ATOM_CAN_BE_PULLED, user) & COMSIG_ATOM_CANT_PULL) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 2643680bce9..9d1a8fbfd30 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -73,7 +73,7 @@ . = ..() if(!new_viewer || hud_users_all_z_levels.len != 1) return - for(var/mob/camera/ai_eye/eye as anything in GLOB.aiEyes) + for(var/mob/eye/ai_eye/eye as anything in GLOB.aiEyes) eye.update_ai_detect_hud() /datum/atom_hud/data/malf_apc diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 62fd2f82609..24ad407763b 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -335,6 +335,13 @@ remove_all_languages(source = LANGUAGE_EMP) grant_random_uncommon_language(source = LANGUAGE_EMP) +/obj/machinery/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + //takes priority in case material container or other atoms that hook onto item interaction signals won't give it a chance + if(istype(tool, /obj/item/storage/part_replacer)) + return tool.interact_with_atom(src, user, modifiers) + + return ..() + /** * Opens the machine. * diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 6640f5582fa..80a06fa6b9f 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -8,7 +8,7 @@ var/list/z_lock = list() // Lock use to these z levels var/lock_override = NONE - var/mob/camera/ai_eye/remote/eyeobj + var/mob/eye/ai_eye/remote/eyeobj var/mob/living/current_user = null var/list/networks = list(CAMERANET_NETWORK_SS13) /// Typepath of the action button we use as "off" @@ -188,7 +188,7 @@ /obj/machinery/computer/camera_advanced/attack_ai(mob/user) return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise. -/mob/camera/ai_eye/remote +/mob/eye/ai_eye/remote name = "Inactive Camera Eye" ai_detector_visible = FALSE var/sprint = 10 @@ -200,24 +200,24 @@ var/visible_icon = 0 var/image/user_image = null -/mob/camera/ai_eye/remote/update_remote_sight(mob/living/user) +/mob/eye/ai_eye/remote/update_remote_sight(mob/living/user) user.set_invis_see(SEE_INVISIBLE_LIVING) //can't see ghosts through cameras user.set_sight(SEE_TURFS) return TRUE -/mob/camera/ai_eye/remote/Destroy() +/mob/eye/ai_eye/remote/Destroy() if(origin && eye_user) origin.remove_eye_control(eye_user,src) origin = null . = ..() eye_user = null -/mob/camera/ai_eye/remote/GetViewerClient() +/mob/eye/ai_eye/remote/GetViewerClient() if(eye_user) return eye_user.client return null -/mob/camera/ai_eye/remote/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/setLoc(turf/destination, force_update = FALSE) if(eye_user) destination = get_turf(destination) if (destination) @@ -237,7 +237,7 @@ SET_PLANE(user_image, ABOVE_GAME_PLANE, destination) eye_user.client.images += user_image -/mob/camera/ai_eye/remote/relaymove(mob/living/user, direction) +/mob/eye/ai_eye/remote/relaymove(mob/living/user, direction) var/initial = initial(sprint) var/max_sprint = 50 @@ -263,7 +263,7 @@ /datum/action/innate/camera_off/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/console = remote_eye.origin console.remove_eye_control(owner) @@ -275,7 +275,7 @@ /datum/action/innate/camera_jump/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin var/list/L = list() @@ -320,7 +320,7 @@ /datum/action/innate/camera_multiz_up/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control if(remote_eye.zMove(UP)) to_chat(owner, span_notice("You move upwards.")) else @@ -334,7 +334,7 @@ /datum/action/innate/camera_multiz_down/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control if(remote_eye.zMove(DOWN)) to_chat(owner, span_notice("You move downwards.")) else diff --git a/code/game/machinery/computer/orders/order_computer/order_computer.dm b/code/game/machinery/computer/orders/order_computer/order_computer.dm index 9098d5aeb09..8ad5d5dde28 100644 --- a/code/game/machinery/computer/orders/order_computer/order_computer.dm +++ b/code/game/machinery/computer/orders/order_computer/order_computer.dm @@ -120,7 +120,8 @@ GLOBAL_LIST_EMPTY(order_console_products) "cat" = item.category_index, "ref" = REF(item), "cost" = round(item.cost_per_order * cargo_cost_multiplier), - "product_icon" = icon2base64(getFlatIcon(image(icon = initial(item.item_path.icon), icon_state = initial(item.item_path.icon_state)), no_anim=TRUE)) + "icon" = item.item_path::icon, + "icon_state" = item.item_path::icon_state, )) return data diff --git a/code/game/machinery/dna_infuser/dna_infusion.dm b/code/game/machinery/dna_infuser/dna_infusion.dm index 37019afd51f..9b85ae856e2 100644 --- a/code/game/machinery/dna_infuser/dna_infusion.dm +++ b/code/game/machinery/dna_infuser/dna_infusion.dm @@ -40,8 +40,8 @@ /// Requires the target mob to have an existing organic organ to "mutate". // TODO: In the future, this should have more logic: // - Replace non-mutant organs before mutant ones. -/mob/living/carbon/human/proc/infuse_organ(datum/infuser_entry/entry) - var/obj/item/organ/new_organ = pick_infusion_organ(entry) +/mob/living/carbon/human/proc/infuse_organ(datum/infuser_entry/entry, atom/movable/infused_from) + var/obj/item/organ/new_organ = pick_infusion_organ(entry, infused_from) if(!new_organ) return FALSE // Valid organ successfully picked. diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 094ffa32ae1..07e9b61f457 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1831,7 +1831,7 @@ if(istype(mover) && (mover.pass_flags & PASSGLASS)) return !opacity -/obj/structure/fluff/airlock_filler/can_be_pulled(user, grab_state, force) +/obj/structure/fluff/airlock_filler/can_be_pulled(user, force) return FALSE /obj/structure/fluff/airlock_filler/singularity_act() diff --git a/code/game/machinery/flatpacker.dm b/code/game/machinery/flatpacker.dm index 6c90e45e4f6..4a0e78f5207 100644 --- a/code/game/machinery/flatpacker.dm +++ b/code/game/machinery/flatpacker.dm @@ -165,9 +165,8 @@ qdel(null_comp) return costs -/obj/machinery/flatpacker/item_interaction(mob/living/user, obj/item/attacking_item, params) - . = NONE - if(user.combat_mode || attacking_item.flags_1 & HOLOGRAM_1 || attacking_item.item_flags & ABSTRACT) +/obj/machinery/flatpacker/base_item_interaction(mob/living/user, obj/item/attacking_item, list/modifiers) + if(attacking_item.flags_1 & HOLOGRAM_1 || attacking_item.item_flags & ABSTRACT) return ITEM_INTERACT_SKIP_TO_ATTACK if(istype(attacking_item, /obj/item/circuitboard/machine)) @@ -193,6 +192,8 @@ update_appearance(UPDATE_OVERLAYS) return ITEM_INTERACT_SUCCESS + return ..() + /obj/machinery/flatpacker/screwdriver_act(mob/living/user, obj/item/tool) . = ITEM_INTERACT_BLOCKING if(default_deconstruction_screwdriver(user, "[base_icon_state]_o", base_icon_state, tool)) diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index c2fb218d50a..6db5f9d4f15 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -221,7 +221,7 @@ for(var/atom/movable/ROI in source) if(ROI == src) continue - if(!istype(ROI) || isdead(ROI) || iscameramob(ROI) || istype(ROI, /obj/effect/dummy/phased_mob)) + if(!istype(ROI) || isdead(ROI) || iseyemob(ROI) || istype(ROI, /obj/effect/dummy/phased_mob)) continue//don't teleport these var/on_chair = "" if(ROI.anchored)// if it's anchored, don't teleport diff --git a/code/game/machinery/newscaster/newscaster_machine.dm b/code/game/machinery/newscaster/newscaster_machine.dm index 47ab476cbca..39fe7ce6cb7 100644 --- a/code/game/machinery/newscaster/newscaster_machine.dm +++ b/code/game/machinery/newscaster/newscaster_machine.dm @@ -230,7 +230,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) data["channelLocked"] = current_channel.locked data["channelCensored"] = current_channel.censored - //We send all the information about all messages in existance. + //We send all the information about all messages in existence. data["messages"] = message_list data["wanted"] = wanted_info @@ -699,15 +699,17 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) * Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine. */ /obj/machinery/newscaster/proc/create_story(channel_name) - for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) - if(channel_name == potential_channel.channel_ID) - current_channel = potential_channel - break var/temp_message = tgui_input_text(usr, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE) if(length(temp_message) <= 1) return TRUE if(temp_message) feed_channel_message = temp_message + + for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) + if(channel_name == potential_channel.channel_ID) + current_channel = potential_channel + break + GLOB.news_network.submit_article("[parsemarkdown(feed_channel_message, usr)]", newscaster_username, current_channel.channel_name, send_photo_data(), adminMessage = FALSE, allow_comments = TRUE) SSblackbox.record_feedback("amount", "newscaster_stories", 1) feed_channel_message = "" diff --git a/code/game/machinery/newscaster/newspaper.dm b/code/game/machinery/newscaster/newspaper.dm index 6bc1e6c77ff..648b64d58e8 100644 --- a/code/game/machinery/newscaster/newspaper.dm +++ b/code/game/machinery/newscaster/newspaper.dm @@ -89,6 +89,7 @@ return add_fingerprint(user) user.balloon_alert(user, "scribbling...") + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) if(!do_after(user, 2 SECONDS, src)) return user.balloon_alert(user, "scribbled!") diff --git a/code/game/machinery/scanner_gate.dm b/code/game/machinery/scanner_gate.dm index 677681511cf..7da9ded217d 100644 --- a/code/game/machinery/scanner_gate.dm +++ b/code/game/machinery/scanner_gate.dm @@ -205,6 +205,7 @@ var/beep = FALSE var/color = null var/detected_thing = null + var/bypassed = FALSE playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE) switch(scangate_mode) if(SCANGATE_NONE) @@ -254,7 +255,7 @@ if((!HAS_TRAIT(scanned_human, TRAIT_MINDSHIELD)) && (isnull(idcard) || !(ACCESS_WEAPONS in idcard.access))) // mindshield or ID card with weapons access, like bartender beep = TRUE break - say("[detected_thing] detection bypassed.") + bypassed = TRUE break else for(var/obj/item/content in thing.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) @@ -303,6 +304,8 @@ assembly?.activate() else SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_NO_TRIGGER, thing) + if(bypassed) + say("[detected_thing] detection bypassed.") if(!ignore_signals) color = wires.get_color_of_wire(WIRE_DENY) var/obj/item/assembly/assembly = wires.get_attached(color) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index f06ac5d9209..4104367a73e 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -215,23 +215,25 @@ if(target == src) return FALSE - // Check if the target to buckle isn't INSIDE OF A WALL - if(!isopenturf(loc) || !isopenturf(target.loc)) - return FALSE - - // Check if the target to buckle isn't A SOLID OBJECT (not including vehicles) var/turf/ground = get_turf(src) - if(ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src)) - return FALSE + // If we're not already on the same turf as our target... + if(get_turf(target) != ground) + // Check if the target to buckle isn't INSIDE OF A WALL + if(!isopenturf(loc) || !isopenturf(target.loc)) + return FALSE + + // Check if the target to buckle isn't INSIDE A SOLID OBJECT (not including vehicles) + if(ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src)) + return FALSE + + // If we're checking the loc, make sure the target is on the thing we're bucking them to. + if(check_loc && !target.Adjacent(src)) + return FALSE // Check if this atom can have things buckled to it. if(!can_buckle && !force) return FALSE - // If we're checking the loc, make sure the target is on the thing we're bucking them to. - if(check_loc && !target.Adjacent(src)) - return FALSE - // Make sure the target isn't already buckled to something. if(target.buckled) return FALSE diff --git a/code/game/objects/effects/anomalies/anomalies_bluespace.dm b/code/game/objects/effects/anomalies/anomalies_bluespace.dm index 6c9d2bfd666..cadc0992a63 100644 --- a/code/game/objects/effects/anomalies/anomalies_bluespace.dm +++ b/code/game/objects/effects/anomalies/anomalies_bluespace.dm @@ -65,7 +65,7 @@ for (var/atom/movable/A in urange(12, FROM )) // iterate thru list of mobs in the area if(istype(A, /obj/item/beacon)) continue // don't teleport beacons because that's just insanely stupid - if(iscameramob(A)) + if(iseyemob(A)) continue // Don't mess with AI eye, blob eye, xenobio or advanced cameras if(A.anchored) continue diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 18f63350426..21a51ba9bcb 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -130,29 +130,35 @@ linked = null return ..() -/obj/effect/portal/attack_ghost(mob/dead/observer/O) - if(!teleport(O, TRUE)) +/obj/effect/portal/attack_ghost(mob/dead/observer/ghost) + if(!teleport(ghost, force = TRUE)) return ..() + return BULLET_ACT_FORCE_PIERCE -/obj/effect/portal/proc/teleport(atom/movable/M, force = FALSE) - if(!force && (!istype(M) || iseffect(M) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M)))) //Things that shouldn't teleport. +/obj/effect/portal/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) + if (!teleport(hitting_projectile, force = TRUE)) + return ..() + return BULLET_ACT_FORCE_PIERCE + +/obj/effect/portal/proc/teleport(atom/movable/moving, force = FALSE) + if(!force && (!istype(moving) || iseffect(moving) || (ismecha(moving) && !mech_sized) || (!isobj(moving) && !ismob(moving)))) //Things that shouldn't teleport. return var/turf/real_target = get_link_target_turf() if(!istype(real_target)) return FALSE - if(!force && (!ismecha(M) && !isprojectile(M) && M.anchored && !allow_anchored)) + if(!force && (!ismecha(moving) && !isprojectile(moving) && moving.anchored && !allow_anchored)) return var/no_effect = FALSE if(last_effect == world.time || sparkless) no_effect = TRUE else last_effect = world.time - var/turf/start_turf = get_turf(M) - if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport)) - if(isprojectile(M)) - var/obj/projectile/P = M + var/turf/start_turf = get_turf(moving) + if(do_teleport(moving, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport)) + if(isprojectile(moving)) + var/obj/projectile/P = moving P.ignore_source_check = TRUE - new /obj/effect/temp_visual/portal_animation(start_turf, src, M) + new /obj/effect/temp_visual/portal_animation(start_turf, src, moving) playsound(start_turf, SFX_PORTAL_ENTER, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) playsound(real_target, SFX_PORTAL_ENTER, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) return TRUE @@ -189,7 +195,7 @@ linked = P break -/obj/effect/portal/permanent/teleport(atom/movable/M, force = FALSE) +/obj/effect/portal/permanent/teleport(atom/movable/moving, force = FALSE) set_linked() // update portal links . = ..() @@ -213,9 +219,9 @@ name = "one-use portal" desc = "This is probably the worst decision you'll ever make in your life." -/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/M, force = FALSE) +/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/moving, force = FALSE) . = ..() - if (. && !isdead(M)) + if (. && !isdead(moving)) expire() /** diff --git a/code/game/objects/effects/temporary_visuals/effect_trail.dm b/code/game/objects/effects/temporary_visuals/effect_trail.dm index 9b28dcf909d..5eed9462dfd 100644 --- a/code/game/objects/effects/temporary_visuals/effect_trail.dm +++ b/code/game/objects/effects/temporary_visuals/effect_trail.dm @@ -2,7 +2,7 @@ /obj/effect/temp_visual/effect_trail name = "effect trail" desc = "An invisible effect, how did you examine this?" - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' icon_state = "marker" duration = 15 SECONDS invisibility = INVISIBILITY_ABSTRACT diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 0e74007cc5c..fcf1f6dd37d 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -300,14 +300,6 @@ /obj/effect/temp_visual/gib_animation/animal icon = 'icons/mob/simple/animal.dmi' -/obj/effect/temp_visual/dust_animation - icon = 'icons/mob/simple/mob.dmi' - duration = 15 - -/obj/effect/temp_visual/dust_animation/Initialize(mapload, dust_icon) - icon_state = dust_icon // Before ..() so the correct icon is flick()'d - . = ..() - /obj/effect/temp_visual/mummy_animation icon = 'icons/mob/simple/mob.dmi' icon_state = "mummy_revive" diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 62faf032e78..9d37bbb97f0 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -473,7 +473,7 @@ .[weight_class_to_text(w_class)] = weight_class_to_tooltip(w_class) if(item_flags & CRUEL_IMPLEMENT) - .[span_red("morbid")] = "It seems quite practical for particularly morbid procedures and experiments." + .[span_red("morbid")] = "It seems quite practical for particularly morbid procedures and experiments." if (siemens_coefficient == 0) .["insulated"] = "It is made from a robust electrical insulator and will block any electricity passing through it!" @@ -1051,36 +1051,93 @@ ///Called BEFORE the object is ground up - use this to change grind results based on conditions. Return "-1" to prevent the grinding from occurring /obj/item/proc/on_grind() + PROTECTED_PROC(TRUE) + return SEND_SIGNAL(src, COMSIG_ITEM_ON_GRIND) ///Grind item, adding grind_results to item's reagents and transfering to target_holder if specified -/obj/item/proc/grind(datum/reagents/target_holder, mob/user) +/obj/item/proc/grind(datum/reagents/target_holder, mob/user, atom/movable/grinder = loc) + SHOULD_NOT_OVERRIDE(TRUE) + . = FALSE - if(on_grind() == -1) + if(on_grind() == -1 || target_holder.holder_full()) return + . = grind_atom(target_holder, user) + + //reccursive grinding to get all them juices + var/result + for(var/obj/item/ingredient as anything in get_all_contents_type(/obj/item)) + if(ingredient == src) + continue + + result = ingredient.grind(target_holder, user) + if(!.) + . = result + + if(. && istype(grinder)) + return grinder.blended(src, grinded = TRUE) + +///Subtypes override his proc for custom grinding +/obj/item/proc/grind_atom(datum/reagents/target_holder, mob/user) + PROTECTED_PROC(TRUE) + + . = FALSE if(length(grind_results)) target_holder.add_reagent_list(grind_results) . = TRUE - if(reagents?.total_volume) - reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user) + if(reagents?.trans_to(target_holder, reagents.total_volume, transferred_by = user)) . = TRUE ///Called BEFORE the object is ground up - use this to change grind results based on conditions. Return "-1" to prevent the grinding from occurring /obj/item/proc/on_juice() + PROTECTED_PROC(TRUE) + if(!juice_typepath) return -1 + return SEND_SIGNAL(src, COMSIG_ITEM_ON_JUICE) ///Juice item, converting nutriments into juice_typepath and transfering to target_holder if specified -/obj/item/proc/juice(datum/reagents/target_holder, mob/user) +/obj/item/proc/juice(datum/reagents/target_holder, mob/user, atom/movable/juicer = loc) + SHOULD_NOT_OVERRIDE(TRUE) + + . = FALSE if(on_juice() == -1 || !reagents?.total_volume) - return FALSE + return + + . = juice_atom(target_holder, user) + + //reccursive juicing to get all them juices + var/result + for(var/obj/item/ingredient as anything in get_all_contents_type(/obj/item)) + if(ingredient == src) + continue + + result = ingredient.juice(target_holder, user) + if(!.) + . = result + + if(. && istype(juicer)) + return juicer.blended(src, grinded = FALSE) + +///Subtypes override his proc for custom juicing +/obj/item/proc/juice_atom(datum/reagents/target_holder, mob/user) + PROTECTED_PROC(TRUE) + + . = FALSE if(ispath(juice_typepath)) reagents.convert_reagent(/datum/reagent/consumable/nutriment, juice_typepath, include_source_subtypes = FALSE) reagents.convert_reagent(/datum/reagent/consumable/nutriment/vitamin, juice_typepath, include_source_subtypes = FALSE) - reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user) + . = TRUE + + if(!QDELETED(target_holder)) + reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user) + +///What should The atom that blended an object do with it afterwards? Default behaviour is to delete it +/atom/movable/proc/blended(obj/item/blended_item, grinded) + qdel(blended_item) return TRUE diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 73ce50bc668..8c3f9483737 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -1899,6 +1899,7 @@ var/input_name = sanitize_name(raw_input, allow_numbers = TRUE) if(!after_input_check(user, item, input_name, scribbled_name)) return + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) scribbled_name = input_name var/list/details = item.get_writing_implement_details() details_colors[INDEX_NAME_COLOR] = details["color"] || COLOR_BLACK @@ -1906,6 +1907,7 @@ var/input_assignment = tgui_input_text(user, "What assignment would you like to put on this card?", "Cardboard card job ssignment", scribbled_assignment || "Assistant", max_length = MAX_NAME_LEN) if(!after_input_check(user, item, input_assignment, scribbled_assignment)) return + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) scribbled_assignment = sanitize(input_assignment) var/list/details = item.get_writing_implement_details() details_colors[INDEX_ASSIGNMENT_COLOR] = details["color"] || COLOR_BLACK @@ -1921,6 +1923,7 @@ var/input_trim = tgui_input_list(user, "Select trim to apply to your card.\nNote: This will not grant any trim accesses.", "Forge Trim", possible_trims) if(!input_trim || !after_input_check(user, item, input_trim, scribbled_trim)) return + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) scribbled_trim = "cardboard_[input_trim]" var/list/details = item.get_writing_implement_details() details_colors[INDEX_TRIM_COLOR] = details["color"] || COLOR_BLACK diff --git a/code/game/objects/items/cigarettes.dm b/code/game/objects/items/cigarettes.dm index 5be266974db..b4ee67ea9d7 100644 --- a/code/game/objects/items/cigarettes.dm +++ b/code/game/objects/items/cigarettes.dm @@ -190,11 +190,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/cigarette/Initialize(mapload) . = ..() - create_reagents(chem_volume, INJECTABLE | NO_REACT) - if(list_reagents) - reagents.add_reagent_list(list_reagents) - if(starts_lit) - light() AddComponent(/datum/component/knockoff, 90, list(BODY_ZONE_PRECISE_MOUTH), slot_flags) //90% to knock off when wearing a mask AddElement(/datum/element/update_icon_updates_onmob) RegisterSignal(src, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(sparks_touched)) @@ -206,15 +201,17 @@ CIGARETTE PACKETS ARE IN FANCY.DM initial_reagents = list_reagents,\ food_flags = FOOD_NO_EXAMINE,\ foodtypes = JUNKFOOD,\ - volume = 50,\ + volume = chem_volume,\ eat_time = 0 SECONDS,\ - tastes = list("a never before experienced flavour.", "finally sitting down after standing your entire life"),\ + tastes = list("a never before experienced flavour", "finally sitting down after standing your entire life"),\ eatverbs = list("taste"),\ - bite_consumption = 50,\ + bite_consumption = chem_volume,\ junkiness = 0,\ reagent_purity = null,\ on_consume = CALLBACK(src, PROC_REF(on_consume)),\ ) + if(starts_lit) + light() /obj/item/cigarette/Destroy() STOP_PROCESSING(SSobj, src) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 8c62f77cde5..8b79d73973f 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -66,7 +66,7 @@ /obj/item/laser_pointer/infinite_range name = "infinite laser pointer" desc = "Used to shine in the eyes of Cyborgs who need a bit of a push, this works through camera consoles." - max_range = INFINITE + max_range = INFINITY /obj/item/laser_pointer/infinite_range/Initialize(mapload) . = ..() @@ -203,7 +203,7 @@ to_chat(user, span_warning("Your fingers can't press the button!")) return - if(max_range != INFINITE) + if(max_range != INFINITY) if(!IN_GIVEN_RANGE(target, user, max_range)) to_chat(user, span_warning("\The [target] is too far away!")) return diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index a191855d0c6..29fde618ba6 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -206,7 +206,7 @@ var/turf/our_turf = get_turf(src) detect_state = PROXIMITY_NONE - for(var/mob/camera/ai_eye/AI_eye as anything in GLOB.aiEyes) + for(var/mob/eye/ai_eye/AI_eye as anything in GLOB.aiEyes) if(!AI_eye.ai_detector_visible) continue @@ -255,7 +255,7 @@ // copied from camera chunks but we are doing a really big edge case here though /obj/item/multitool/ai_detect/proc/surrounding_chunks(turf/epicenter) . = list() - var/static_range = /mob/camera/ai_eye::static_visibility_range + var/static_range = /mob/eye/ai_eye::static_visibility_range var/x1 = max(1, epicenter.x - static_range) var/y1 = max(1, epicenter.y - static_range) var/x2 = min(world.maxx, epicenter.x + static_range) diff --git a/code/game/objects/items/food/lizard.dm b/code/game/objects/items/food/lizard.dm index 2048c997ef9..5e16a1df283 100644 --- a/code/game/objects/items/food/lizard.dm +++ b/code/game/objects/items/food/lizard.dm @@ -551,7 +551,7 @@ /datum/reagent/consumable/nutriment/protein = 10, ) tastes = list("bread" = 1, "meat" = 1) - foodtypes = MEAT | NUTS | RAW | GORE + foodtypes = MEAT | NUTS | GORE crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/pizza/flatbread/stinging diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index 2e26ef4dc2a..40d09e604d5 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -54,7 +54,7 @@ /obj/item/grenade/stingbang name = "stingbang" - icon_state = "timeg" + icon_state = "timeg_locked" inhand_icon_state = "flashbang" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' @@ -122,7 +122,7 @@ /obj/item/grenade/primer name = "rotfrag grenade" desc = "A grenade that generates more shrapnel the more you rotate it in your hand after pulling the pin. This one releases shrapnel shards." - icon_state = "timeg" + icon_state = "timeg_locked" inhand_icon_state = "flashbang" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm index 049ea8928fe..efe1d9e31f1 100644 --- a/code/game/objects/items/holosign_creator.dm +++ b/code/game/objects/items/holosign_creator.dm @@ -35,6 +35,11 @@ return . += span_notice("It is currently maintaining [signs.len]/[max_signs] projections.") +/obj/item/holosign_creator/check_allowed_items(atom/target, not_inside, target_self) + if(HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + return FALSE + return ..() + /obj/item/holosign_creator/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!check_allowed_items(interacting_with, not_inside = TRUE)) return NONE diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm index 0ac1637d6ee..4df3651881a 100644 --- a/code/game/objects/items/implants/implantcase.dm +++ b/code/game/objects/items/implants/implantcase.dm @@ -43,6 +43,7 @@ if((user.get_active_held_item() != used_item) || !user.can_perform_action(src)) return if(new_name) + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) name = "implant case - '[new_name]'" else name = "implant case" diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index b4697664e85..961e0fff88a 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -207,9 +207,6 @@ * * [mob][user]- the user building this structure */ /obj/item/construction/rcd/proc/rcd_create(atom/target, mob/user) - if(HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) - return NONE - var/list/rcd_results = target.rcd_vals(user, src) // does this atom allow for rcd actions? if(!rcd_results) // nope return NONE diff --git a/code/game/objects/items/signs.dm b/code/game/objects/items/signs.dm index 85a71dc0e8f..d0ed3425f97 100644 --- a/code/game/objects/items/signs.dm +++ b/code/game/objects/items/signs.dm @@ -25,6 +25,7 @@ return var/txt = tgui_input_text(user, "What would you like to write on the sign?", "Sign Label", max_length = 30) if(txt && user.can_perform_action(src)) + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) label = txt name = "[label] sign" desc = "It reads: [label]" diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 0d4393efea6..ef3ddb77c0e 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -41,6 +41,8 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \ merge_type = /obj/item/stack/sheet/mineral/sandstone walltype = /turf/closed/wall/mineral/sandstone material_type = /datum/material/sandstone + drop_sound = SFX_STONE_DROP + pickup_sound = SFX_STONE_PICKUP /obj/item/stack/sheet/mineral/sandstone/get_main_recipes() . = ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 18891ebdd93..fd1529eb330 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -135,14 +135,10 @@ return return TRUE -/obj/item/stack/grind(datum/reagents/target_holder, mob/user) +/obj/item/stack/grind_atom(datum/reagents/target_holder, mob/user) var/current_amount = get_amount() if(current_amount <= 0 || QDELETED(src)) //just to get rid of this 0 amount/deleted stack we return success return TRUE - if(on_grind() == -1) - return FALSE - if(isnull(target_holder)) - return TRUE if(reagents) reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user) diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index a2efbe2d4be..34176864492 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -158,10 +158,22 @@ pulseicon = "supermatter_sliver_pulse" layer = ABOVE_MOB_LAYER +/obj/item/nuke_core/supermatter_sliver/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_FISHING_ROD_CAST, PROC_REF(on_hook)) + +/obj/item/nuke_core/supermatter_sliver/proc/on_hook(obj/item/nuke_core/supermatter_sliver/source, obj/item/fishing_rod/rod, mob/user) + SIGNAL_HANDLER + + //hook gets dusted but the rod remains intact + attackby(rod.hook, user) + + return FISHING_ROD_CAST_HANDLED + /obj/item/nuke_core/supermatter_sliver/attack_tk(mob/user) // no TK dusting memes return -/obj/item/nuke_core/supermatter_sliver/can_be_pulled(user) // no drag memes +/obj/item/nuke_core/supermatter_sliver/can_be_pulled(user, force) // no drag memes return FALSE /obj/item/nuke_core/supermatter_sliver/attackby(obj/item/W, mob/living/user, params) diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 8287e7ac8b5..de9553034e7 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -277,11 +277,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool, 0) return if(!item_chair || has_buckled_mobs()) return + if(flags_1 & HOLOGRAM_1) + to_chat(user, span_notice("You try to pick up \the [src], but it fades away!")) + qdel(src) + return + user.visible_message(span_notice("[user] grabs \the [src.name]."), span_notice("You grab \the [src.name].")) - var/obj/item/C = new item_chair(loc) - C.set_custom_materials(custom_materials) - TransferComponents(C) - user.put_in_hands(C) + var/obj/item/chair_item = new item_chair(loc) + chair_item.set_custom_materials(custom_materials) + TransferComponents(chair_item) + user.put_in_hands(chair_item) qdel(src) /obj/structure/chair/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE) @@ -350,6 +355,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) if(isgroundlessturf(T)) to_chat(user, span_warning("You need ground to plant this on!")) return + if(flags_1 & HOLOGRAM_1) + to_chat(user, span_notice("You try to place down \the [src], but it fades away!")) + qdel(src) + return + for(var/obj/A in T) if(istype(A, /obj/structure/chair)) to_chat(user, span_warning("There is already a chair here!")) @@ -359,10 +369,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) return user.visible_message(span_notice("[user] rights \the [src.name]."), span_notice("You right \the [name].")) - var/obj/structure/chair/C = new origin_type(get_turf(loc)) - C.set_custom_materials(custom_materials) - TransferComponents(C) - C.setDir(user.dir) + var/obj/structure/chair/chair = new origin_type(get_turf(loc)) + chair.set_custom_materials(custom_materials) + TransferComponents(chair) + chair.setDir(user.dir) qdel(src) /obj/item/chair/proc/smash(mob/living/user) diff --git a/code/game/objects/structures/construction_console/construction_actions.dm b/code/game/objects/structures/construction_console/construction_actions.dm index 1a6b5deeeae..b3a4e309ffa 100644 --- a/code/game/objects/structures/construction_console/construction_actions.dm +++ b/code/game/objects/structures/construction_console/construction_actions.dm @@ -5,7 +5,7 @@ /datum/action/innate/construction button_icon = 'icons/mob/actions/actions_construction.dmi' ///Console's eye mob - var/mob/camera/ai_eye/remote/base_construction/remote_eye + var/mob/eye/ai_eye/remote/base_construction/remote_eye ///Console itself var/obj/machinery/computer/camera_advanced/base_construction/base_console ///Is this used to build only on the station z level? diff --git a/code/game/objects/structures/construction_console/construction_console.dm b/code/game/objects/structures/construction_console/construction_console.dm index f13dd1d78c6..97b83acccae 100644 --- a/code/game/objects/structures/construction_console/construction_console.dm +++ b/code/game/objects/structures/construction_console/construction_console.dm @@ -1,7 +1,7 @@ /** * Camera console used to control a base building drone * - * Using this console will put the user in control of a [base building drone][/mob/camera/ai_eye/remote/base_construction]. + * Using this console will put the user in control of a [base building drone][/mob/eye/ai_eye/remote/base_construction]. * The drone will appear somewhere within the allowed_area var, or if no area is specified, at the location of the console.area * Upon interacting, the user will be granted a set of base building actions that will generally be carried out at the drone's location. * To create a new base builder system, this class should be the only thing that needs to be subtyped. @@ -61,7 +61,7 @@ var/turf/spawn_spot = find_spawn_spot() if (!spawn_spot) return FALSE - eyeobj = new /mob/camera/ai_eye/remote/base_construction(spawn_spot, src) + eyeobj = new /mob/eye/ai_eye/remote/base_construction(spawn_spot, src) eyeobj.origin = src return TRUE @@ -95,7 +95,7 @@ * The mob is constrained to a given area defined by the base construction console. * */ -/mob/camera/ai_eye/remote/base_construction +/mob/eye/ai_eye/remote/base_construction name = "construction holo-drone" //Allows any curious crew to watch the base after it leaves. (This is safe as the base cannot be modified once it leaves) move_on_shuttle = TRUE @@ -105,20 +105,20 @@ ///Reference to the camera console controlling this drone var/obj/machinery/computer/camera_advanced/base_construction/linked_console -/mob/camera/ai_eye/remote/base_construction/Initialize(mapload, obj/machinery/computer/camera_advanced/console_link) +/mob/eye/ai_eye/remote/base_construction/Initialize(mapload, obj/machinery/computer/camera_advanced/console_link) linked_console = console_link if(!linked_console) stack_trace("A base consturuction drone was created with no linked console") return INITIALIZE_HINT_QDEL return ..() -/mob/camera/ai_eye/remote/base_construction/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/base_construction/setLoc(turf/destination, force_update = FALSE) var/area/curr_area = get_area(destination) //Only move if we're in the allowed area. If no allowed area is defined, then we're free to move wherever. if(!linked_console.allowed_area || istype(curr_area, linked_console.allowed_area)) return ..() -/mob/camera/ai_eye/remote/base_construction/relaymove(mob/living/user, direction) +/mob/eye/ai_eye/remote/base_construction/relaymove(mob/living/user, direction) //This camera eye is visible, and as such needs to keep its dir updated dir = direction return ..() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 7a3fcef368a..6046d356892 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -518,7 +518,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) /obj/structure/closet/proc/insertion_allowed(atom/movable/AM) if(ismob(AM)) - if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets... + if(!isliving(AM)) //let's not put ghosts or eye mobs inside closets... return FALSE var/mob/living/L = AM if(L.anchored || L.buckled || L.incorporeal_move || L.has_buckled_mobs()) diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index 0bb1b564ece..c4aa7391dd6 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -65,6 +65,7 @@ ///Handles renaming of the bodybag's examine tag. /obj/structure/closet/body_bag/proc/handle_tag(new_name) + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) tag_name = new_name name = tag_name ? "[initial(name)] - [tag_name]" : initial(name) update_appearance() diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 5fc9bf674c1..40037944dad 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -297,7 +297,7 @@ if(electronics.shell) door.AddComponent( \ /datum/component/shell, \ - unremovable_circuit_components = list(new /obj/item/circuit_component/airlock, new /obj/item/circuit_component/airlock_access_event), \ + unremovable_circuit_components = list(new /obj/item/circuit_component/airlock, new /obj/item/circuit_component/airlock_access_event, new /obj/item/circuit_component/remotecam/airlock), \ capacity = SHELL_CAPACITY_LARGE, \ shell_flags = SHELL_FLAG_ALLOW_FAILURE_ACTION|SHELL_FLAG_REQUIRE_ANCHOR \ ) diff --git a/code/game/objects/structures/ore_containers.dm b/code/game/objects/structures/ore_containers.dm index 6bc6f680116..75c7a03cfcf 100644 --- a/code/game/objects/structures/ore_containers.dm +++ b/code/game/objects/structures/ore_containers.dm @@ -23,25 +23,16 @@ ui.open() /obj/structure/ore_container/ui_data(mob/user) - var/list/data = list() - data["ores"] = list() + var/list/ores = list() for(var/obj/item/stack/ore/ore_item in contents) - data["ores"] += list(list( + ores += list(list( "id" = REF(ore_item), "name" = ore_item.name, "amount" = ore_item.amount, + "icon" = ore_item::icon, + "icon_state" = ore_item::icon_state, )) - return data - -/obj/structure/ore_container/ui_static_data(mob/user) - var/list/data = list() - data["ore_images"] = list() - for(var/obj/item/stack/ore_item as anything in subtypesof(/obj/item/stack/ore)) - data["ore_images"] += list(list( - "name" = initial(ore_item.name), - "icon" = icon2base64(getFlatIcon(image(icon = initial(ore_item.icon), icon_state = initial(ore_item.icon_state)), no_anim=TRUE)) - )) - return data + return list("ores" = ores) /obj/structure/ore_container/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() diff --git a/code/game/sound.dm b/code/game/sound.dm index c730b582fd6..1e2160c6511 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -754,4 +754,14 @@ 'sound/mobs/humanoids/human/sigh/female_sigh2.ogg', 'sound/mobs/humanoids/human/sigh/female_sigh3.ogg', ) + if(SFX_WRITING_PEN) + soundin = pick( + 'sound/effects/writing_pen/writing_pen1.ogg', + 'sound/effects/writing_pen/writing_pen2.ogg', + 'sound/effects/writing_pen/writing_pen3.ogg', + 'sound/effects/writing_pen/writing_pen4.ogg', + 'sound/effects/writing_pen/writing_pen5.ogg', + 'sound/effects/writing_pen/writing_pen6.ogg', + 'sound/effects/writing_pen/writing_pen7.ogg', + ) return soundin diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 1af42be3071..9b9c739f397 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -165,7 +165,7 @@ place_on_top(new_floor_path, flags = flags) /turf/open/openspace/can_cross_safely(atom/movable/crossing) - return HAS_TRAIT(crossing, TRAIT_MOVE_FLYING) + return HAS_TRAIT(crossing, TRAIT_MOVE_FLYING) || !crossing.can_z_move(DOWN, src, z_move_flags = ZMOVE_FALL_FLAGS) /turf/open/openspace/icemoon name = "ice chasm" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 339e397dc49..92c77e0b12a 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -269,7 +269,7 @@ GLOBAL_LIST_EMPTY(station_turfs) * * type_list - are we checking for types of atoms to ignore and not physical atoms */ /turf/proc/is_blocked_turf(exclude_mobs = FALSE, source_atom = null, list/ignore_atoms, type_list = FALSE) - if((!isnull(source_atom) && !CanPass(source_atom, get_dir(src, source_atom))) || density) + if(density) return TRUE for(var/atom/movable/movable_content as anything in contents) diff --git a/code/modules/admin/smites/imaginary_friend_special.dm b/code/modules/admin/smites/imaginary_friend_special.dm index e670e26fd1f..7e6519ee489 100644 --- a/code/modules/admin/smites/imaginary_friend_special.dm +++ b/code/modules/admin/smites/imaginary_friend_special.dm @@ -104,8 +104,8 @@ if(isliving(client_mob)) client_mob.ghostize() - var/mob/camera/imaginary_friend/friend_mob = client_mob.change_mob_type( - new_type = /mob/camera/imaginary_friend, + var/mob/eye/imaginary_friend/friend_mob = client_mob.change_mob_type( + new_type = /mob/eye/imaginary_friend, location = get_turf(client_mob), delete_old_mob = TRUE, ) diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm index b1be5560d69..7cac42e0b99 100644 --- a/code/modules/admin/verbs/admin_newscaster.dm +++ b/code/modules/admin/verbs/admin_newscaster.dm @@ -128,7 +128,7 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo data["channelLocked"] = current_channel.locked data["channelCensored"] = current_channel.censored - //We send all the information about all channels and all messages in existance. + //We send all the information about all channels and all messages in existence. data["channels"] = channel_list data["messages"] = message_list data["wanted"] = wanted_info diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 5d798a7265e..1aacb1b3096 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -508,7 +508,7 @@ ADMIN_VERB(cmd_admin_pm_panel, R_NONE, "Admin PM", "Show a list of clients to PM return TRUE -/// Notifies all admins about the existance of an admin pm, then logs the pm +/// Notifies all admins about the existence of an admin pm, then logs the pm /// message_target here can be either [EXTERNAL_PM_USER], indicating that this message is intended for some external chat channel /// or a /client, in which case we send in the standard form /// log_message is the raw message to send, it will be filtered and treated to ensure we do not break any text handling diff --git a/code/modules/admin/view_variables/admin_delete.dm b/code/modules/admin/view_variables/admin_delete.dm index c70343c3dcb..c876e1a8588 100644 --- a/code/modules/admin/view_variables/admin_delete.dm +++ b/code/modules/admin/view_variables/admin_delete.dm @@ -17,6 +17,7 @@ log_admin("[key_name(usr)] deleted [D] [coords]") message_admins("[key_name_admin(usr)] deleted [D] [jmp_coords]") BLACKBOX_LOG_ADMIN_VERB("Delete") + SEND_SIGNAL(D, COMSIG_ADMIN_DELETING, src) if(isturf(D)) T = D // NOVA EDIT, orginal: var/turf/T = D T.ScrapeAway() diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm index 09a8fdefa31..f4ddd345075 100644 --- a/code/modules/antagonists/abductor/machinery/camera.dm +++ b/code/modules/antagonists/abductor/machinery/camera.dm @@ -23,7 +23,7 @@ /obj/machinery/computer/camera_advanced/abductor/CreateEye() ..() eyeobj.visible_icon = TRUE - eyeobj.icon = 'icons/mob/silicon/cameramob.dmi' + eyeobj.icon = 'icons/mob/eyemob.dmi' eyeobj.icon_state = "abductor_camera" eyeobj.SetInvisibility(INVISIBILITY_OBSERVER) @@ -57,7 +57,7 @@ to_chat(owner, span_warning("You must wait [DisplayTimeText(use_delay - world.time)] to use the [target] again!")) return var/mob/living/carbon/human/C = owner - var/mob/camera/ai_eye/remote/remote_eye = C.remote_control + var/mob/eye/ai_eye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/pad/P = target var/area/target_area = get_area(remote_eye) @@ -101,7 +101,7 @@ to_chat(owner, span_warning("You can only teleport to one place at a time!")) return var/mob/living/carbon/human/C = owner - var/mob/camera/ai_eye/remote/remote_eye = C.remote_control + var/mob/eye/ai_eye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/pad/P = target var/area/target_area = get_area(remote_eye) @@ -151,7 +151,7 @@ return var/mob/living/carbon/human/C = owner - var/mob/camera/ai_eye/remote/remote_eye = C.remote_control + var/mob/eye/ai_eye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/console/console = target console.SetDroppoint(remote_eye.loc,owner) diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm index 3dcdaf5a5b0..4c5a30c0d9e 100644 --- a/code/modules/antagonists/abductor/machinery/console.dm +++ b/code/modules/antagonists/abductor/machinery/console.dm @@ -94,10 +94,19 @@ "items" = (category == selected_cat ? list() : null)) for(var/gear in possible_gear[category]) var/datum/abductor_gear/AG = possible_gear[category][gear] + + var/atom/gear_path + if(!length(AG.build_path)) + continue + + gear_path = AG.build_path[1] + cat["items"] += list(list( "name" = AG.name, "cost" = AG.cost, "desc" = AG.description, + "icon" = gear_path::icon, + "icon_state" = gear_path::icon_state, )) data["categories"] += list(cat) return data diff --git a/code/modules/antagonists/blob/blob_antag.dm b/code/modules/antagonists/blob/blob_antag.dm index 9f9d97fac8d..25bea4b083e 100644 --- a/code/modules/antagonists/blob/blob_antag.dm +++ b/code/modules/antagonists/blob/blob_antag.dm @@ -18,7 +18,7 @@ var/basic_report = ..() //Display max blobpoints for blebs that lost if(isovermind(owner.current)) //embarrasing if not - var/mob/camera/blob/overmind = owner.current + var/mob/eye/blob/overmind = owner.current if(!overmind.victory_in_progress) //if it won this doesn't really matter var/point_report = "
[owner.name] took over [overmind.max_count] tiles at the height of its growth." return basic_report+point_report @@ -58,7 +58,7 @@ if(!isovermind(user)) return data - var/mob/camera/blob/blob = user + var/mob/eye/blob/blob = user var/datum/blobstrain/reagent/blobstrain = blob.blobstrain if(!blobstrain) @@ -129,7 +129,7 @@ placement_override = BLOB_RANDOM_PLACEMENT to_chat(owner, span_warning("Because your current location is an invalid starting spot and you need to pop, you've been moved to a random location!")) - var/mob/camera/blob/blob_cam = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob) + var/mob/eye/blob/blob_cam = new /mob/eye/blob(get_turf(old_body), blobtag.starting_points_human_blob) owner.mind.transfer_to(blob_cam) old_body.gib() blob_cam.place_blob_core(placement_override, pop_override = TRUE) @@ -147,7 +147,7 @@ /datum/antagonist/blob/antag_listing_status() . = ..() if(owner?.current) - var/mob/camera/blob/blob_cam = owner.current + var/mob/eye/blob/blob_cam = owner.current if(istype(blob_cam)) . += "(Progress: [length(blob_cam.blobs_legit)]/[blob_cam.blobwincount])" diff --git a/code/modules/antagonists/blob/blob_minion.dm b/code/modules/antagonists/blob/blob_minion.dm index 9bf37e961d5..e0ff3beb9f9 100644 --- a/code/modules/antagonists/blob/blob_minion.dm +++ b/code/modules/antagonists/blob/blob_minion.dm @@ -7,7 +7,7 @@ /// The blob core that this minion is attached to var/datum/weakref/overmind -/datum/antagonist/blob_minion/New(mob/camera/blob/overmind) +/datum/antagonist/blob_minion/New(mob/eye/blob/overmind) . = ..() src.overmind = WEAKREF(overmind) @@ -24,7 +24,7 @@ var/datum/weakref/overmind /datum/objective/blob_minion/check_completion() - var/mob/camera/blob/resolved_overmind = overmind.resolve() + var/mob/eye/blob/resolved_overmind = overmind.resolve() if(!resolved_overmind) return FALSE return resolved_overmind.stat != DEAD diff --git a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm index 27d177dde68..54d393780b2 100644 --- a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm +++ b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm @@ -24,7 +24,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ var/resource_delay = 0 /// For blob-mobs and extinguishing-based effects var/fire_based = FALSE - var/mob/camera/blob/overmind + var/mob/eye/blob/overmind /// The amount of health regenned on core_process var/base_core_regen = BLOB_CORE_HP_REGEN /// The amount of points gained on core_process @@ -63,7 +63,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ /// Makes blobbernauts inject a bonus amount of reagents, making their attacks more powerful var/blobbernaut_reagentatk_bonus = 0 -/datum/blobstrain/New(mob/camera/blob/new_overmind) +/datum/blobstrain/New(mob/eye/blob/new_overmind) if (!istype(new_overmind)) stack_trace("blobstrain created without overmind") overmind = new_overmind @@ -155,7 +155,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ /datum/blobstrain/proc/death_reaction(obj/structure/blob/B, damage_flag, coefficient = 1) //when a blob dies, do this return -/datum/blobstrain/proc/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this +/datum/blobstrain/proc/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O, coefficient = 1) //when the blob expands, do this return /datum/blobstrain/proc/tesla_reaction(obj/structure/blob/B, power, coefficient = 1) //when the blob is hit by a tesla bolt, do this diff --git a/code/modules/antagonists/blob/blobstrains/_reagent.dm b/code/modules/antagonists/blob/blobstrains/_reagent.dm index 65a50621b17..bc9c61dd4b1 100644 --- a/code/modules/antagonists/blob/blobstrains/_reagent.dm +++ b/code/modules/antagonists/blob/blobstrains/_reagent.dm @@ -1,7 +1,7 @@ /datum/blobstrain/reagent // Blobs that mess with reagents, all "legacy" ones // what do you mean "legacy" you never added an alternative var/datum/reagent/reagent -/datum/blobstrain/reagent/New(mob/camera/blob/new_overmind) +/datum/blobstrain/reagent/New(mob/eye/blob/new_overmind) . = ..() reagent = new reagent() @@ -42,12 +42,12 @@ description = "[name] is the reagent created by that type of blob." /// Used by blob reagents to calculate the reaction volume they should use when exposing mobs. -/datum/reagent/blob/proc/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/proc/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) return 0 //the dead, and blob mobs, don't cause reactions return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume. /// Exists to earmark the new overmind arg used by blob reagents. -/datum/reagent/blob/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) return ..() diff --git a/code/modules/antagonists/blob/blobstrains/blazing_oil.dm b/code/modules/antagonists/blob/blobstrains/blazing_oil.dm index ded3be1458e..f01f2c2faad 100644 --- a/code/modules/antagonists/blob/blobstrains/blazing_oil.dm +++ b/code/modules/antagonists/blob/blobstrains/blazing_oil.dm @@ -32,7 +32,7 @@ taste_description = "burning oil" color = "#B68D00" -/datum/reagent/blob/blazing_oil/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/blazing_oil/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.adjust_fire_stacks(round(reac_volume/10)) diff --git a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm index acb4d96c23a..64aa9c26f75 100644 --- a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm +++ b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm @@ -16,7 +16,7 @@ color = "#8BA6E9" taste_description = "brain freeze" -/datum/reagent/blob/cryogenic_poison/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/cryogenic_poison/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) if(exposed_mob.reagents) diff --git a/code/modules/antagonists/blob/blobstrains/debris_devourer.dm b/code/modules/antagonists/blob/blobstrains/debris_devourer.dm index 352d7c230a4..1a2cb9fe854 100644 --- a/code/modules/antagonists/blob/blobstrains/debris_devourer.dm +++ b/code/modules/antagonists/blob/blobstrains/debris_devourer.dm @@ -25,7 +25,7 @@ I.forceMove(get_turf(spore)) I.throw_at(get_edge_target_turf(spore,pick(GLOB.alldirs)), 6, 5, spore, TRUE, FALSE, null, 3) -/datum/blobstrain/debris_devourer/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this +/datum/blobstrain/debris_devourer/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O, coefficient = 1) //when the blob expands, do this for (var/obj/item/I in T) I.forceMove(overmind.blob_core) diff --git a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm index ea2bf54d769..cb5f565ef55 100644 --- a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm +++ b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm @@ -22,7 +22,7 @@ color = "#E88D5D" taste_description = "fizzing" -/datum/reagent/blob/distributed_neurons/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/distributed_neurons/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.6*reac_volume, TOX) diff --git a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm index 4a5c49d851a..d4c9da7e0e4 100644 --- a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm +++ b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm @@ -23,7 +23,7 @@ taste_description = "pop rocks" color = "#83ECEC" -/datum/reagent/blob/electromagnetic_web/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/electromagnetic_web/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) if(prob(reac_volume*2)) diff --git a/code/modules/antagonists/blob/blobstrains/energized_jelly.dm b/code/modules/antagonists/blob/blobstrains/energized_jelly.dm index 9fa5ed9ab96..43c18fc8090 100644 --- a/code/modules/antagonists/blob/blobstrains/energized_jelly.dm +++ b/code/modules/antagonists/blob/blobstrains/energized_jelly.dm @@ -26,7 +26,7 @@ taste_description = "gelatin" color = "#EFD65A" -/datum/reagent/blob/energized_jelly/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/energized_jelly/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.losebreath += round(0.2*reac_volume) diff --git a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm index e1ae8294df3..d068373e86b 100644 --- a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm +++ b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm @@ -31,7 +31,7 @@ taste_description = "the bomb" color = "#8B2500" -/datum/reagent/blob/explosive_lattice/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/explosive_lattice/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() var/brute_loss = 0 var/burn_loss = 0 @@ -51,7 +51,7 @@ brute_loss = brute_loss*(2 - round(bomb_armor*0.01, 0.05)) burn_loss = brute_loss - + exposed_mob.take_overall_damage(brute_loss, burn_loss) for(var/mob/living/nearby_mob in orange(epicenter_turf, 1)) @@ -69,6 +69,6 @@ burn_loss = brute_loss nearby_mob.take_overall_damage(brute_loss, burn_loss) - + else exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/multiplex.dm b/code/modules/antagonists/blob/blobstrains/multiplex.dm index aaebf1d0526..aedb571c6b6 100644 --- a/code/modules/antagonists/blob/blobstrains/multiplex.dm +++ b/code/modules/antagonists/blob/blobstrains/multiplex.dm @@ -2,7 +2,7 @@ var/list/blobstrains var/typeshare -/datum/blobstrain/multiplex/New(mob/camera/blob/new_overmind, list/blobstrains) +/datum/blobstrain/multiplex/New(mob/eye/blob/new_overmind, list/blobstrains) . = ..() for (var/bt in blobstrains) if (ispath(bt, /datum/blobstrain)) @@ -21,7 +21,7 @@ for (var/datum/blobstrain/bt in blobstrains) . += bt.death_reaction(B, damage_flag, coefficient*typeshare) -/datum/blobstrain/multiplex/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this +/datum/blobstrain/multiplex/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O, coefficient = 1) //when the blob expands, do this for (var/datum/blobstrain/bt in blobstrains) . += bt.expand_reaction(B, newB, T, O, coefficient*typeshare) diff --git a/code/modules/antagonists/blob/blobstrains/networked_fibers.dm b/code/modules/antagonists/blob/blobstrains/networked_fibers.dm index 4c84eb639d7..1dfb0bf4077 100644 --- a/code/modules/antagonists/blob/blobstrains/networked_fibers.dm +++ b/code/modules/antagonists/blob/blobstrains/networked_fibers.dm @@ -11,7 +11,7 @@ reagent = /datum/reagent/blob/networked_fibers core_regen_bonus = 3 -/datum/blobstrain/reagent/networked_fibers/expand_reaction(obj/structure/blob/spawning_blob, obj/structure/blob/new_blob, turf/chosen_turf, mob/camera/blob/overmind) +/datum/blobstrain/reagent/networked_fibers/expand_reaction(obj/structure/blob/spawning_blob, obj/structure/blob/new_blob, turf/chosen_turf, mob/eye/blob/overmind) if(!overmind && new_blob.overmind) new_blob.overmind.add_points(1) qdel(new_blob) @@ -33,7 +33,7 @@ taste_description = "efficiency" color = "#4F4441" -/datum/reagent/blob/networked_fibers/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/networked_fibers/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm b/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm index d035319219d..40019beb013 100644 --- a/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm +++ b/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm @@ -39,7 +39,7 @@ taste_description = "a sponge" color = "#AAAABB" -/datum/reagent/blob/pressurized_slime/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/pressurized_slime/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) var/turf/open/location_turf = get_turf(exposed_mob) diff --git a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm index 1c8cb893df8..778b1a22784 100644 --- a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm +++ b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm @@ -34,12 +34,12 @@ taste_description = "rock" color = "#9ACD32" -/datum/reagent/blob/reactive_spines/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/reactive_spines/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) return 0 //the dead, and blob mobs, don't cause reactions return reac_volume -/datum/reagent/blob/reactive_spines/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/reactive_spines/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.adjustBruteLoss(reac_volume) diff --git a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm index d9010a96537..101995f23d5 100644 --- a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm +++ b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm @@ -16,7 +16,7 @@ taste_description = "heaven" color = "#A88FB7" -/datum/reagent/blob/regenerative_materia/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/regenerative_materia/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) if(iscarbon(exposed_mob)) diff --git a/code/modules/antagonists/blob/blobstrains/replicating_foam.dm b/code/modules/antagonists/blob/blobstrains/replicating_foam.dm index 83d84618da5..949c945e9c6 100644 --- a/code/modules/antagonists/blob/blobstrains/replicating_foam.dm +++ b/code/modules/antagonists/blob/blobstrains/replicating_foam.dm @@ -21,7 +21,7 @@ return ..() -/datum/blobstrain/reagent/replicating_foam/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O) +/datum/blobstrain/reagent/replicating_foam/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O) if(prob(30)) newB.expand(null, null, 0) //do it again! @@ -30,7 +30,7 @@ taste_description = "duplication" color = "#7B5A57" -/datum/reagent/blob/replicating_foam/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/replicating_foam/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm b/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm index 3db0041b310..8dfe798c57e 100644 --- a/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm +++ b/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm @@ -9,7 +9,7 @@ complementary_color = "#3C6EC8" reagent = /datum/reagent/blob/shifting_fragments -/datum/blobstrain/reagent/shifting_fragments/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O) +/datum/blobstrain/reagent/shifting_fragments/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O) if(istype(B, /obj/structure/blob/normal) || (istype(B, /obj/structure/blob/shield))) newB.forceMove(get_turf(B)) B.forceMove(T) @@ -31,7 +31,7 @@ name = "Shifting Fragments" color = "#C8963C" -/datum/reagent/blob/shifting_fragments/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/shifting_fragments/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm b/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm index 825104ddcc1..1030e447106 100644 --- a/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm +++ b/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm @@ -30,7 +30,7 @@ taste_description = "toxic mold" color = "#65ADA2" -/datum/reagent/blob/synchronous_mesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/synchronous_mesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index 99a27429e61..db40090615b 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -5,11 +5,11 @@ GLOBAL_LIST_EMPTY(overminds) GLOBAL_LIST_EMPTY(blob_nodes) -/mob/camera/blob +/mob/eye/blob name = "Blob Overmind" real_name = "Blob Overmind" desc = "The overmind. It controls the blob." - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' icon_state = "marker" mouse_opacity = MOUSE_OPACITY_ICON move_on_shuttle = TRUE @@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) /// The list of strains the blob can reroll for. var/list/strain_choices -/mob/camera/blob/Initialize(mapload, starting_points = OVERMIND_STARTING_POINTS) +/mob/eye/blob/Initialize(mapload, starting_points = OVERMIND_STARTING_POINTS) ADD_TRAIT(src, TRAIT_BLOB_ALLY, INNATE_TRAIT) validate_location() blob_points = starting_points @@ -74,7 +74,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) START_PROCESSING(SSobj, src) GLOB.blob_telepathy_mobs |= src -/mob/camera/blob/proc/validate_location() +/mob/eye/blob/proc/validate_location() var/turf/T = get_turf(src) if(is_valid_turf(T)) return @@ -96,7 +96,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) CRASH("No blobspawnpoints and blob spawned in nullspace.") forceMove(T) -/mob/camera/blob/proc/set_strain(datum/blobstrain/new_strain) +/mob/eye/blob/proc/set_strain(datum/blobstrain/new_strain) if (!ispath(new_strain)) return FALSE @@ -116,7 +116,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) to_chat(src, span_notice("The [blobstrain.name] strain [blobstrain.effectdesc]")) SEND_SIGNAL(src, COMSIG_BLOB_SELECTED_STRAIN, blobstrain) -/mob/camera/blob/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) +/mob/eye/blob/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) if(placed) // The blob can't expand vertically (yet) return FALSE . = ..() @@ -128,13 +128,13 @@ GLOBAL_LIST_EMPTY(blob_nodes) to_chat(src, span_warning("Your destination is invalid. Move somewhere else and try again.")) return null -/mob/camera/blob/proc/is_valid_turf(turf/tile) +/mob/eye/blob/proc/is_valid_turf(turf/tile) var/area/area = get_area(tile) if((area && !(area.area_flags & BLOBS_ALLOWED)) || !tile || !is_station_level(tile.z) || isgroundlessturf(tile)) return FALSE return TRUE -/mob/camera/blob/process() +/mob/eye/blob/process() if(!blob_core) if(!placed) if(manualplace_min_time && world.time >= manualplace_min_time) @@ -166,27 +166,27 @@ GLOBAL_LIST_EMPTY(blob_nodes) has_announced = TRUE /// Create a blob spore and link it to us -/mob/camera/blob/proc/create_spore(turf/spore_turf, spore_type = /mob/living/basic/blob_minion/spore/minion) +/mob/eye/blob/proc/create_spore(turf/spore_turf, spore_type = /mob/living/basic/blob_minion/spore/minion) var/mob/living/basic/blob_minion/spore/spore = new spore_type(spore_turf) assume_direct_control(spore) return spore /// Give our new minion the properties of a minion -/mob/camera/blob/proc/assume_direct_control(mob/living/minion) +/mob/eye/blob/proc/assume_direct_control(mob/living/minion) minion.AddComponent(/datum/component/blob_minion, src) /// Add something to our list of mobs and wait for it to die -/mob/camera/blob/proc/register_new_minion(mob/living/minion) +/mob/eye/blob/proc/register_new_minion(mob/living/minion) blob_mobs |= minion if (!istype(minion, /mob/living/basic/blob_minion/blobbernaut)) RegisterSignal(minion, COMSIG_LIVING_DEATH, PROC_REF(on_minion_death)) /// When a spore (or zombie) dies then we do this -/mob/camera/blob/proc/on_minion_death(mob/living/spore) +/mob/eye/blob/proc/on_minion_death(mob/living/spore) SIGNAL_HANDLER blobstrain.on_sporedeath(spore) -/mob/camera/blob/proc/victory() +/mob/eye/blob/proc/victory() sound_to_playing_players('sound/announcer/alarm/nuke_alarm.ogg', 70) sleep(10 SECONDS) for(var/mob/living/live_guy as anything in GLOB.mob_living_list) @@ -232,7 +232,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) SSticker.news_report = BLOB_WIN SSticker.force_ending = FORCE_END_ROUND -/mob/camera/blob/Destroy() +/mob/eye/blob/Destroy() QDEL_NULL(blobstrain) for(var/BL in GLOB.blobs) var/obj/structure/blob/B = BL @@ -255,7 +255,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) return ..() -/mob/camera/blob/Login() +/mob/eye/blob/Login() . = ..() if(!. || !client) return FALSE @@ -266,12 +266,12 @@ GLOBAL_LIST_EMPTY(blob_nodes) update_health_hud() add_points(0) -/mob/camera/blob/examine(mob/user) +/mob/eye/blob/examine(mob/user) . = ..() if(blobstrain) . += "Its strain is [blobstrain.name]." -/mob/camera/blob/update_health_hud() +/mob/eye/blob/update_health_hud() if(!blob_core) return FALSE var/current_health = round((blob_core.get_integrity() / blob_core.max_integrity) * 100) @@ -282,11 +282,11 @@ GLOBAL_LIST_EMPTY(blob_nodes) continue using_hud.blobpwrdisplay.maptext = MAPTEXT("
[current_health]%
") -/mob/camera/blob/proc/add_points(points) +/mob/eye/blob/proc/add_points(points) blob_points = clamp(blob_points + points, 0, max_blob_points) hud_used.blobpwrdisplay.maptext = MAPTEXT("
[round(blob_points)]
") -/mob/camera/blob/say( +/mob/eye/blob/say( message, bubble_type, list/spans = list(), @@ -314,7 +314,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) blob_talk(message) -/mob/camera/blob/proc/blob_talk(message) +/mob/eye/blob/proc/blob_talk(message) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) @@ -327,10 +327,10 @@ GLOBAL_LIST_EMPTY(blob_nodes) var/rendered = span_big(span_blob("\[Blob Telepathy\] [name]([blobstrain.name]) [message_a]")) relay_to_list_and_observers(rendered, GLOB.blob_telepathy_mobs, src) -/mob/camera/blob/blob_act(obj/structure/blob/B) +/mob/eye/blob/blob_act(obj/structure/blob/B) return -/mob/camera/blob/get_status_tab_items() +/mob/eye/blob/get_status_tab_items() . = ..() if(blob_core) . += "Core Health: [blob_core.get_integrity()]" @@ -343,7 +343,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) . += "Time Before Manual Placement: [max(round((manualplace_min_time - world.time)*0.1, 0.1), 0)]" . += "Time Before Automatic Placement: [max(round((autoplace_max_time - world.time)*0.1, 0.1), 0)]" -/mob/camera/blob/Move(NewLoc, Dir = 0) +/mob/eye/blob/Move(NewLoc, Dir = 0) if(placed) var/obj/structure/blob/B = locate() in range(OVERMIND_MAX_CAMERA_STRAY, NewLoc) if(B) @@ -357,7 +357,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) forceMove(NewLoc) return TRUE -/mob/camera/blob/mind_initialize() +/mob/eye/blob/mind_initialize() . = ..() var/datum/antagonist/blob/blob = mind.has_antag_datum(/datum/antagonist/blob) if(!blob) diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 2f3b51741f9..58e25cdd620 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -1,7 +1,7 @@ #define BLOB_REROLL_RADIUS 60 /** Simple price check */ -/mob/camera/blob/proc/can_buy(cost = 15) +/mob/eye/blob/proc/can_buy(cost = 15) if(blob_points < cost) to_chat(src, span_warning("You cannot afford this, you need at least [cost] resources!")) balloon_alert(src, "need [cost-blob_points] more resource\s!") @@ -10,7 +10,7 @@ return TRUE /** Places the core itself */ -/mob/camera/blob/proc/place_blob_core(placement_override = BLOB_NORMAL_PLACEMENT, pop_override = FALSE) +/mob/eye/blob/proc/place_blob_core(placement_override = BLOB_NORMAL_PLACEMENT, pop_override = FALSE) if(placed && placement_override != BLOB_FORCE_PLACEMENT) return TRUE @@ -50,7 +50,7 @@ return TRUE /** Checks proximity for mobs */ -/mob/camera/blob/proc/check_core_visibility() +/mob/eye/blob/proc/check_core_visibility() for(var/mob/living/player in range(7, src)) if(ROLE_BLOB in player.faction) continue @@ -69,7 +69,7 @@ /** Checks for previous blobs or denose objects on the tile. */ -/mob/camera/blob/proc/check_objects_tile(turf/placement) +/mob/eye/blob/proc/check_objects_tile(turf/placement) for(var/obj/object in placement) if(istype(object, /obj/structure/blob)) if(istype(object, /obj/structure/blob/normal)) @@ -85,12 +85,12 @@ return TRUE /** Moves the core elsewhere. */ -/mob/camera/blob/proc/transport_core() +/mob/eye/blob/proc/transport_core() if(blob_core) forceMove(blob_core.drop_location()) /** Jumps to a node */ -/mob/camera/blob/proc/jump_to_node() +/mob/eye/blob/proc/jump_to_node() if(!length(GLOB.blob_nodes)) return FALSE @@ -108,7 +108,7 @@ forceMove(chosen_node.loc) /** Places important blob structures */ -/mob/camera/blob/proc/create_special(price, blobstrain, min_separation, needs_node, turf/tile) +/mob/eye/blob/proc/create_special(price, blobstrain, min_separation, needs_node, turf/tile) if(!tile) tile = get_turf(src) var/obj/structure/blob/blob = (locate(/obj/structure/blob) in tile) @@ -142,7 +142,7 @@ return node /** Toggles requiring nodes */ -/mob/camera/blob/proc/toggle_node_req() +/mob/eye/blob/proc/toggle_node_req() nodes_required = !nodes_required if(nodes_required) to_chat(src, span_warning("You now require a nearby node or core to place factory and resource blobs.")) @@ -150,7 +150,7 @@ to_chat(src, span_warning("You no longer require a nearby node or core to place factory and resource blobs.")) /** Creates a shield to reflect projectiles */ -/mob/camera/blob/proc/create_shield(turf/tile) +/mob/eye/blob/proc/create_shield(turf/tile) var/obj/structure/blob/shield/shield = locate(/obj/structure/blob/shield) in tile if(!shield) shield = create_special(BLOB_UPGRADE_STRONG_COST, /obj/structure/blob/shield, 0, FALSE, tile) @@ -170,7 +170,7 @@ shield.balloon_alert(src, "upgraded to [shield.name]!") /** Preliminary check before polling ghosts. */ -/mob/camera/blob/proc/create_blobbernaut() +/mob/eye/blob/proc/create_blobbernaut() var/turf/current_turf = get_turf(src) var/obj/structure/blob/special/factory/factory = locate(/obj/structure/blob/special/factory) in current_turf if(!factory) @@ -190,7 +190,7 @@ pick_blobbernaut_candidate(factory) /// Polls ghosts to get a blobbernaut candidate. -/mob/camera/blob/proc/pick_blobbernaut_candidate(obj/structure/blob/special/factory/factory) +/mob/eye/blob/proc/pick_blobbernaut_candidate(obj/structure/blob/special/factory/factory) if(isnull(factory)) return var/icon/blobbernaut_icon = icon(icon, "blobbernaut") @@ -209,7 +209,7 @@ on_poll_concluded(factory, chosen_one) /// Called when the ghost poll concludes -/mob/camera/blob/proc/on_poll_concluded(obj/structure/blob/special/factory/factory, mob/dead/observer/ghost) +/mob/eye/blob/proc/on_poll_concluded(obj/structure/blob/special/factory/factory, mob/dead/observer/ghost) if(isnull(ghost)) to_chat(src, span_warning("You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later.")) add_points(BLOBMOB_BLOBBERNAUT_RESOURCE_COST) @@ -223,14 +223,14 @@ RegisterSignal(blobber, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(on_blobbernaut_attacked)) /// When one of our boys attacked something, we sometimes want to perform extra effects -/mob/camera/blob/proc/on_blobbernaut_attacked(mob/living/basic/blobbynaut, atom/target, success) +/mob/eye/blob/proc/on_blobbernaut_attacked(mob/living/basic/blobbynaut, atom/target, success) SIGNAL_HANDLER if (!success) return blobstrain.blobbernaut_attack(target, blobbynaut) /** Moves the core */ -/mob/camera/blob/proc/relocate_core() +/mob/eye/blob/proc/relocate_core() var/turf/tile = get_turf(src) var/obj/structure/blob/special/node/blob = locate(/obj/structure/blob/special/node) in tile @@ -258,7 +258,7 @@ blob.setDir(old_dir) /** Searches the tile for a blob and removes it. */ -/mob/camera/blob/proc/remove_blob(turf/tile) +/mob/eye/blob/proc/remove_blob(turf/tile) var/obj/structure/blob/blob = locate() in tile if(!blob) @@ -283,7 +283,7 @@ return TRUE /** Expands to nearby tiles */ -/mob/camera/blob/proc/expand_blob(turf/tile) +/mob/eye/blob/proc/expand_blob(turf/tile) if(world.time < last_attack) return FALSE var/list/possible_blobs = list() @@ -327,7 +327,7 @@ /** Finds cardinal and diagonal attack directions */ -/mob/camera/blob/proc/directional_attack(turf/tile, list/possible_blobs, attack_success = FALSE) +/mob/eye/blob/proc/directional_attack(turf/tile, list/possible_blobs, attack_success = FALSE) var/list/cardinal_blobs = list() var/list/diagonal_blobs = list() @@ -353,7 +353,7 @@ return TRUE /** Rally spores to a location */ -/mob/camera/blob/proc/rally_spores(turf/tile) +/mob/eye/blob/proc/rally_spores(turf/tile) to_chat(src, "You rally your spores.") var/list/surrounding_turfs = TURF_NEIGHBORS(tile) if(!length(surrounding_turfs)) @@ -365,7 +365,7 @@ blob_mob.ai_controller.set_blackboard_key(BB_TRAVEL_DESTINATION, pick(surrounding_turfs)) /** Opens the reroll menu to change strains */ -/mob/camera/blob/proc/strain_reroll() +/mob/eye/blob/proc/strain_reroll() if (!free_strain_rerolls && blob_points < BLOB_POWER_REROLL_COST) to_chat(src, span_warning("You need at least [BLOB_POWER_REROLL_COST] resources to reroll your strain again!")) return FALSE @@ -373,7 +373,7 @@ open_reroll_menu() /** Controls changing strains */ -/mob/camera/blob/proc/open_reroll_menu() +/mob/eye/blob/proc/open_reroll_menu() if (!strain_choices) strain_choices = list() diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index ce1b016dcb0..4d401a52189 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -29,7 +29,7 @@ var/ignore_syncmesh_share = 0 /// If the blob blocks atmos and heat spread var/atmosblock = FALSE - var/mob/camera/blob/overmind + var/mob/eye/blob/overmind /datum/armor/structure_blob @@ -144,7 +144,7 @@ O.setDir(dir) var/area/my_area = get_area(src) if(controller) - var/mob/camera/blob/BO = controller + var/mob/eye/blob/BO = controller O.color = BO.blobstrain.color if(!(my_area.area_flags & BLOBS_ALLOWED)) O.color = BlendRGB(O.color, COLOR_WHITE, 0.5) //lighten it to indicate an off-station blob @@ -416,7 +416,7 @@ if(SPT_PROB(BLOB_REINFORCE_CHANCE, seconds_per_tick)) B.change_to(/obj/structure/blob/shield/reflective/core, overmind) -/obj/structure/blob/special/proc/pulse_area(mob/camera/blob/pulsing_overmind, claim_range = 10, pulse_range = 3, expand_range = 2) +/obj/structure/blob/special/proc/pulse_area(mob/eye/blob/pulsing_overmind, claim_range = 10, pulse_range = 3, expand_range = 2) if(QDELETED(pulsing_overmind)) pulsing_overmind = overmind Be_Pulsed() diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index 67b8f7b881d..6cef8b6e5cf 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -60,19 +60,6 @@ var/rust_strength = 0 /// Wether we are allowed to ascend var/feast_of_owls = FALSE - /// Static list of what each path converts to in the UI (colors are TGUI colors) - var/static/list/path_to_ui_bgr = list( - PATH_START = "node_side", - PATH_SIDE = "node_side", - PATH_RUST = "node_rust", - PATH_FLESH = "node_flesh", - PATH_ASH = "node_ash", - PATH_VOID = "node_void", - PATH_BLADE = "node_blade", - PATH_COSMIC = "node_cosmos", - PATH_LOCK = "node_lock", - PATH_MOON = "node_moon", - ) /// List that keeps track of which items have been gifted to the heretic after a cultist was sacrificed. Used to alter drop chances to reduce dupes. var/list/unlocked_heretic_items = list( @@ -150,7 +137,7 @@ knowledge_data["gainFlavor"] = initial(knowledge.gain_text) knowledge_data["cost"] = initial(knowledge.cost) knowledge_data["disabled"] = (!done) && (initial(knowledge.cost) > knowledge_points) - knowledge_data["bgr"] = (path_to_ui_bgr[initial(knowledge.route)] || "side") + knowledge_data["bgr"] = GLOB.heretic_research_tree[knowledge][HKT_UI_BGR] knowledge_data["finished"] = done knowledge_data["ascension"] = ispath(knowledge,/datum/heretic_knowledge/ultimate) @@ -178,10 +165,10 @@ for(var/datum/heretic_knowledge/knowledge as anything in researched_knowledge) var/list/knowledge_data = get_knowledge_data(knowledge,TRUE) - while(initial(knowledge.depth) > tiers.len) + while(GLOB.heretic_research_tree[knowledge][HKT_DEPTH] > tiers.len) tiers += list(list("nodes"=list())) - tiers[initial(knowledge.depth)]["nodes"] += list(knowledge_data) + tiers[GLOB.heretic_research_tree[knowledge][HKT_DEPTH]]["nodes"] += list(knowledge_data) for(var/datum/heretic_knowledge/knowledge as anything in get_researchable_knowledge()) var/list/knowledge_data = get_knowledge_data(knowledge,FALSE) @@ -190,10 +177,10 @@ if(ispath(knowledge, /datum/heretic_knowledge/ultimate)) knowledge_data["disabled"] ||= !can_ascend() - while(initial(knowledge.depth) > tiers.len) + while(GLOB.heretic_research_tree[knowledge][HKT_DEPTH] > tiers.len) tiers += list(list("nodes"=list())) - tiers[initial(knowledge.depth)]["nodes"] += list(knowledge_data) + tiers[GLOB.heretic_research_tree[knowledge][HKT_DEPTH]]["nodes"] += list(knowledge_data) data["knowledge_tiers"] = tiers @@ -272,6 +259,9 @@ return ..() /datum/antagonist/heretic/on_gain() + if(!GLOB.heretic_research_tree) + GLOB.heretic_research_tree = generate_heretic_research_tree() + if(give_objectives) forge_primary_objectives() @@ -831,8 +821,8 @@ var/list/banned_knowledge = list() for(var/knowledge_index in researched_knowledge) var/datum/heretic_knowledge/knowledge = researched_knowledge[knowledge_index] - researchable_knowledge |= knowledge.next_knowledge - banned_knowledge |= knowledge.banned_knowledge + researchable_knowledge |= GLOB.heretic_research_tree[knowledge_index][HKT_NEXT] + banned_knowledge |= GLOB.heretic_research_tree[knowledge_index][HKT_BAN] banned_knowledge |= knowledge.type researchable_knowledge -= banned_knowledge return researchable_knowledge @@ -948,7 +938,7 @@ // (All the main paths are (should be) the same length, so it doesn't matter.) var/rust_paths_found = 0 for(var/datum/heretic_knowledge/knowledge as anything in subtypesof(/datum/heretic_knowledge)) - if(initial(knowledge.route) == PATH_RUST) + if(GLOB.heretic_research_tree[knowledge][HKT_ROUTE] == PATH_RUST) rust_paths_found++ main_path_length = rust_paths_found diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index fcdb1f19458..007dc15bbc4 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -17,12 +17,6 @@ var/gain_text /// The abstract parent type of the knowledge, used in determine mutual exclusivity in some cases var/datum/heretic_knowledge/abstract_parent_type = /datum/heretic_knowledge - /// If TRUE, populates the banned_knowledge list of every other subtype of this knowledge's abstract_parent_type - var/mutually_exclusive = FALSE - /// The knowledge this unlocks next after learning. - var/list/next_knowledge = list() - /// What knowledge is incompatible with this. Knowledge in this list cannot be researched with this current knowledge. - var/list/banned_knowledge = list() /// Assoc list of [typepaths we need] to [amount needed]. /// If set, this knowledge allows the heretic to do a ritual on a transmutation rune with the components set. /// If one of the items in the list is a list, it's treated as 'any of these items will work' @@ -36,30 +30,18 @@ /// The priority of the knowledge. Higher priority knowledge appear higher in the ritual list. /// Number itself is completely arbitrary. Does not need to be set for non-ritual knowledge. var/priority = 0 - /// What path is this on. If set to "null", assumed to be unreachable (or abstract). - var/route + ///If this is considered starting knowledge, TRUE if yes + var/is_starting_knowledge = FALSE /// In case we want to override the default UI icon getter and plug in our own icon instead. /// if research_tree_icon_path is not null, research_tree_icon_state must also be specified or things may break var/research_tree_icon_path var/research_tree_icon_state var/research_tree_icon_frame = 1 var/research_tree_icon_dir = SOUTH - /// Level of knowledge tree where this knowledge should be in the UI - var/depth = 1 ///Determines what kind of monster ghosts will ignore from here on out. Defaults to POLL_IGNORE_HERETIC_MONSTER, but we define other types of monsters for more granularity. var/poll_ignore_define = POLL_IGNORE_HERETIC_MONSTER -/datum/heretic_knowledge/New() - if(!mutually_exclusive) - return - - for(var/knowledge_type in subtypesof(abstract_parent_type)) - if(knowledge_type == type) - continue - banned_knowledge += knowledge_type - -/** - * Called when the knowledge is first researched. +/** Called when the knowledge is first researched. * This is only ever called once per heretic. * * Arguments @@ -269,24 +251,14 @@ */ /datum/heretic_knowledge/limited_amount/starting abstract_parent_type = /datum/heretic_knowledge/limited_amount/starting - mutually_exclusive = TRUE limit = 2 cost = 1 priority = MAX_KNOWLEDGE_PRIORITY - 5 - depth = 2 - -/datum/heretic_knowledge/limited_amount/starting/New() - . = ..() - // Starting path also determines the final knowledge we're limited too - for(var/datum/heretic_knowledge/final_knowledge_type as anything in subtypesof(/datum/heretic_knowledge/ultimate)) - if(initial(final_knowledge_type.route) == route) - continue - banned_knowledge += final_knowledge_type /datum/heretic_knowledge/limited_amount/starting/on_research(mob/user, datum/antagonist/heretic/our_heretic) . = ..() - our_heretic.heretic_path = route - SSblackbox.record_feedback("tally", "heretic_path_taken", 1, route) + our_heretic.heretic_path = GLOB.heretic_research_tree[type][HKT_ROUTE] + SSblackbox.record_feedback("tally", "heretic_path_taken", 1, our_heretic.heretic_path) /** * A knowledge subtype for heretic knowledge @@ -296,9 +268,7 @@ */ /datum/heretic_knowledge/mark abstract_parent_type = /datum/heretic_knowledge/mark - mutually_exclusive = TRUE cost = 2 - depth = 5 /// The status effect typepath we apply on people on mansus grasp. var/datum/status_effect/eldritch/mark_type @@ -364,9 +334,7 @@ */ /datum/heretic_knowledge/blade_upgrade abstract_parent_type = /datum/heretic_knowledge/blade_upgrade - mutually_exclusive = TRUE cost = 2 - depth = 9 /datum/heretic_knowledge/blade_upgrade/on_gain(mob/user, datum/antagonist/heretic/our_heretic) RegisterSignal(user, COMSIG_HERETIC_BLADE_ATTACK, PROC_REF(on_eldritch_blade)) @@ -603,10 +571,8 @@ desc = "A randomly generated transmutation ritual that rewards knowledge points and can only be completed once." gain_text = "Everything can be a key to unlocking the secrets behind the Gates. I must be wary and wise." abstract_parent_type = /datum/heretic_knowledge/knowledge_ritual - mutually_exclusive = TRUE cost = 1 priority = MAX_KNOWLEDGE_PRIORITY - 10 // A pretty important midgame ritual. - depth = 6 research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "book_open" /// Whether we've done the ritual. Only doable once. @@ -696,11 +662,9 @@ */ /datum/heretic_knowledge/ultimate abstract_parent_type = /datum/heretic_knowledge/ultimate - mutually_exclusive = TRUE // I guess, but it doesn't really matter by this point cost = 2 priority = MAX_KNOWLEDGE_PRIORITY + 1 // Yes, the final ritual should be ABOVE the max priority. required_atoms = list(/mob/living/carbon/human = 3) - depth = 11 //use this to store the achievement typepath var/datum/award/achievement/misc/ascension_achievement @@ -756,7 +720,7 @@ human_user.physiology.brute_mod *= 0.5 human_user.physiology.burn_mod *= 0.5 - SSblackbox.record_feedback("tally", "heretic_ascended", 1, route) + SSblackbox.record_feedback("tally", "heretic_ascended", 1, GLOB.heretic_research_tree[type][HKT_ROUTE]) log_heretic_knowledge("[key_name(user)] completed their final ritual at [worldtime2text()].") notify_ghosts( "[user] has completed an ascension ritual!", diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm index 1c9fa131a9b..d0b46f4011f 100644 --- a/code/modules/antagonists/heretic/influences.dm +++ b/code/modules/antagonists/heretic/influences.dm @@ -117,7 +117,7 @@ their_poor_arm.dismember() qdel(their_poor_arm) else - to_chat(human_user,span_danger("You pull your hand away from the hole as the eldritch energy flails, trying to latch onto existance itself!")) + to_chat(human_user,span_danger("You pull your hand away from the hole as the eldritch energy flails, trying to latch onto existence itself!")) return TRUE /obj/effect/visible_heretic_influence/attack_tk(mob/user) diff --git a/code/modules/antagonists/heretic/knowledge/_heretic_paths.dm b/code/modules/antagonists/heretic/knowledge/_heretic_paths.dm new file mode 100644 index 00000000000..5e3583e14b3 --- /dev/null +++ b/code/modules/antagonists/heretic/knowledge/_heretic_paths.dm @@ -0,0 +1,199 @@ +//Global typecache of all heretic knowledges -> instantiate the tree columns -> make them link themselves -> replace the old heretic stuff + +//heretic research tree is a directional graph so we can use some basic graph stuff to make internally handling it easier +GLOBAL_LIST(heretic_research_tree) + +//HKT = Heretic Knowledge Tree (Heretic Research Tree :3) these objects really only exist for a short period of time at startup and then get deleted +/datum/heretic_knowledge_tree_column + ///Route that symbolizes what path this is + var/route + ///Used to determine if this is a side path or a main path + var/abstract_parent_type = /datum/heretic_knowledge_tree_column + ///IDs od neighbours (to left and right) + var/neighbour_type_left + var/neighbour_type_right + ///Tier1 knowledge (or knowledges) + var/tier1 + ///Tier2 knowledge (or knowledges) + var/tier2 + ///Tier3 knowledge (or knowledges) + var/tier3 + ///UI background + var/ui_bgr = "node_side" + +/datum/heretic_knowledge_tree_column/main + abstract_parent_type = /datum/heretic_knowledge_tree_column/main + + ///Starting knowledge - first thing you pick + var/start + ///Grasp upgrade + var/grasp + ///Mark upgrade + var/mark + ///Unique ritual of knoweldge + var/ritual_of_knowledge + ///Path specific unique ability + var/unique_ability + ///Blade upgrade + var/blade + ///Ascension + var/ascension + +/proc/generate_heretic_research_tree() + var/list/heretic_research_tree = list() + + //Initialize the data structure + for(var/type in subtypesof(/datum/heretic_knowledge)) + heretic_research_tree[type] = list() + heretic_research_tree[type][HKT_NEXT] = list() + heretic_research_tree[type][HKT_BAN] = list() + heretic_research_tree[type][HKT_DEPTH] = 1 + heretic_research_tree[type][HKT_UI_BGR] = "node_side" + + var/datum/heretic_knowledge/knowledge = type + if(initial(knowledge.is_starting_knowledge)) + heretic_research_tree[type][HKT_ROUTE] = PATH_START + continue + + heretic_research_tree[type][HKT_ROUTE] = null + + var/list/paths = list() + for(var/type in subtypesof(/datum/heretic_knowledge_tree_column)) + var/datum/heretic_knowledge_tree_column/column_path = type + if(initial(column_path.abstract_parent_type) == column_path) + continue + + var/datum/heretic_knowledge_tree_column/column = new type() + paths[column.type] = column + + var/list/start_blacklist = list() + var/list/grasp_blacklist = list() + var/list/mark_blacklist = list() + var/list/blade_blacklist = list() + var/list/asc_blacklist = list() + + for(var/id in paths) + if(!istype(paths[id],/datum/heretic_knowledge_tree_column/main)) + continue + var/datum/heretic_knowledge_tree_column/main/column = paths[id] + + start_blacklist += column.start + grasp_blacklist += column.grasp + mark_blacklist += column.mark + blade_blacklist += column.blade + asc_blacklist += column.ascension + + heretic_research_tree[/datum/heretic_knowledge/spell/basic][HKT_NEXT] += start_blacklist + + for(var/id in paths) + var/datum/heretic_knowledge_tree_column/this_column = paths[id] + var/datum/heretic_knowledge_tree_column/neighbour_0 = paths[this_column.neighbour_type_left] + var/datum/heretic_knowledge_tree_column/neighbour_1 = paths[this_column.neighbour_type_right] + //horizontal (two way) + var/list/tier1 = this_column.tier1 + var/list/tier2 = this_column.tier2 + var/list/tier3 = this_column.tier3 + + //Tier1, 2 and 3 can technically be lists so we handle them here + if(!islist(this_column.tier1)) + tier1 = list(this_column.tier1) + + if(!islist(this_column.tier2)) + tier2 = list(this_column.tier2) + + if(!islist(this_column.tier3)) + tier3 = list(this_column.tier3) + + for(var/t1_knowledge in tier1) + heretic_research_tree[t1_knowledge][HKT_NEXT] += neighbour_0.tier1 + heretic_research_tree[t1_knowledge][HKT_NEXT] += neighbour_1.tier1 + heretic_research_tree[t1_knowledge][HKT_ROUTE] = this_column.route + heretic_research_tree[t1_knowledge][HKT_UI_BGR] = this_column.ui_bgr + heretic_research_tree[t1_knowledge][HKT_DEPTH] = 4 + + for(var/t2_knowledge in tier2) + heretic_research_tree[t2_knowledge][HKT_NEXT] += neighbour_0.tier2 + heretic_research_tree[t2_knowledge][HKT_NEXT] += neighbour_1.tier2 + heretic_research_tree[t2_knowledge][HKT_ROUTE] = this_column.route + heretic_research_tree[t2_knowledge][HKT_UI_BGR] = this_column.ui_bgr + heretic_research_tree[t2_knowledge][HKT_DEPTH] = 8 + + for(var/t3_knowledge in tier3) + heretic_research_tree[t3_knowledge][HKT_NEXT] += neighbour_0.tier3 + heretic_research_tree[t3_knowledge][HKT_NEXT] += neighbour_1.tier3 + heretic_research_tree[t3_knowledge][HKT_ROUTE] = this_column.route + heretic_research_tree[t3_knowledge][HKT_UI_BGR] = this_column.ui_bgr + heretic_research_tree[t3_knowledge][HKT_DEPTH] = 10 + + //Everything below this line is considered to be a "main path" and not a side path + //Since we are handling the heretic research tree column by column this is required + if(this_column.abstract_parent_type != /datum/heretic_knowledge_tree_column/main) + continue + + var/datum/heretic_knowledge_tree_column/main/main_column = this_column + //vertical (one way) + heretic_research_tree[/datum/heretic_knowledge/spell/basic] += main_column.start + heretic_research_tree[main_column.start][HKT_NEXT] += main_column.grasp + heretic_research_tree[main_column.grasp][HKT_NEXT] += main_column.tier1 + //t1 handling + for(var/t1_knowledge in tier1) + heretic_research_tree[t1_knowledge][HKT_NEXT] += main_column.mark + + heretic_research_tree[main_column.mark][HKT_NEXT] += main_column.ritual_of_knowledge + heretic_research_tree[main_column.ritual_of_knowledge][HKT_NEXT] += main_column.unique_ability + heretic_research_tree[main_column.unique_ability][HKT_NEXT] += main_column.tier2 + //t2 handling + for(var/t2_knowledge in tier2) + heretic_research_tree[t2_knowledge][HKT_NEXT] += main_column.blade + + heretic_research_tree[main_column.blade][HKT_NEXT] += main_column.tier3 + //t3 handling + for(var/t3_knowledge in tier3) + heretic_research_tree[t3_knowledge][HKT_NEXT] += main_column.ascension + + //blacklist + heretic_research_tree[main_column.start][HKT_BAN] += (start_blacklist - main_column.start) + (asc_blacklist - main_column.ascension) + heretic_research_tree[main_column.grasp][HKT_BAN] += (grasp_blacklist - main_column.grasp) + heretic_research_tree[main_column.mark][HKT_BAN] += (mark_blacklist - main_column.mark) + heretic_research_tree[main_column.blade][HKT_BAN] += (blade_blacklist - main_column.blade) + + //route stuff + heretic_research_tree[main_column.start][HKT_ROUTE] = main_column.route + heretic_research_tree[main_column.grasp][HKT_ROUTE] = main_column.route + heretic_research_tree[main_column.mark][HKT_ROUTE] = main_column.route + heretic_research_tree[main_column.ritual_of_knowledge][HKT_ROUTE] = main_column.route + heretic_research_tree[main_column.unique_ability][HKT_ROUTE] = main_column.route + heretic_research_tree[main_column.blade][HKT_ROUTE] = main_column.route + heretic_research_tree[main_column.ascension][HKT_ROUTE] = main_column.route + + heretic_research_tree[main_column.start][HKT_UI_BGR] = main_column.ui_bgr + heretic_research_tree[main_column.grasp][HKT_UI_BGR] = main_column.ui_bgr + heretic_research_tree[main_column.mark][HKT_UI_BGR] = main_column.ui_bgr + heretic_research_tree[main_column.ritual_of_knowledge][HKT_UI_BGR] = main_column.ui_bgr + heretic_research_tree[main_column.unique_ability][HKT_UI_BGR] = main_column.ui_bgr + heretic_research_tree[main_column.blade][HKT_UI_BGR] = main_column.ui_bgr + heretic_research_tree[main_column.ascension][HKT_UI_BGR] = main_column.ui_bgr + //depth stuff + heretic_research_tree[main_column.start][HKT_DEPTH] = 2 + heretic_research_tree[main_column.grasp][HKT_DEPTH] = 3 + heretic_research_tree[main_column.mark][HKT_DEPTH] = 5 + heretic_research_tree[main_column.ritual_of_knowledge][HKT_DEPTH] = 6 + heretic_research_tree[main_column.unique_ability][HKT_DEPTH] = 7 + heretic_research_tree[main_column.blade][HKT_DEPTH] = 9 + heretic_research_tree[main_column.ascension][HKT_DEPTH] = 11 + + //Per path bullshit goes here \/\/\/ + for(var/t2_knowledge in tier2) + heretic_research_tree[t2_knowledge][HKT_NEXT] += /datum/heretic_knowledge/reroll_targets + + // If you want to do any custom bullshit put it here \/\/\/ + heretic_research_tree[/datum/heretic_knowledge/reroll_targets][HKT_ROUTE] = PATH_SIDE + heretic_research_tree[/datum/heretic_knowledge/reroll_targets][HKT_DEPTH] = 8 + + heretic_research_tree[/datum/heretic_knowledge/rifle][HKT_NEXT] += /datum/heretic_knowledge/rifle_ammo + heretic_research_tree[/datum/heretic_knowledge/rifle_ammo][HKT_ROUTE] = PATH_SIDE + heretic_research_tree[/datum/heretic_knowledge/rifle_ammo][HKT_DEPTH] = heretic_research_tree[/datum/heretic_knowledge/rifle][HKT_DEPTH] + + //and we're done + QDEL_LIST_ASSOC_VAL(paths) + return heretic_research_tree diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm index f897aebc3fb..99f0eeaeba2 100644 --- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm @@ -1,44 +1,32 @@ -/** - * # The path of Ash. - * - * Goes as follows: - * - * Nightwatcher's Secret - * Grasp of Ash - * Ashen Passage - * > Sidepaths: - * Scorching Shark - * Ashen Eyes - * - * Mark of Ash - * Ritual of Knowledge - * Fire Blast - * Mask of Madness - * > Sidepaths: - * Space Phase - * Curse of Paralysis - * - * Fiery Blade - * Nightwatcher's Rebirth - * > Sidepaths: - * Ashen Ritual - * Eldritch Coin - * - * Ashlord's Rite - */ + +/datum/heretic_knowledge_tree_column/main/ash + neighbour_type_left = /datum/heretic_knowledge_tree_column/cosmic_to_ash + neighbour_type_right = /datum/heretic_knowledge_tree_column/ash_to_moon + + route = PATH_ASH + ui_bgr = "node_ash" + start = /datum/heretic_knowledge/limited_amount/starting/base_ash + grasp = /datum/heretic_knowledge/ashen_grasp + tier1 = /datum/heretic_knowledge/spell/ash_passage + mark = /datum/heretic_knowledge/mark/ash_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/ash + unique_ability = /datum/heretic_knowledge/spell/fire_blast + tier2 = /datum/heretic_knowledge/mad_mask + blade = /datum/heretic_knowledge/blade_upgrade/ash + tier3 = /datum/heretic_knowledge/spell/flame_birth + ascension = /datum/heretic_knowledge/ultimate/ash_final + /datum/heretic_knowledge/limited_amount/starting/base_ash name = "Nightwatcher's Secret" desc = "Opens up the Path of Ash to you. \ Allows you to transmute a match and a knife into an Ashen Blade. \ You can only create five at a time." //NOVA EDIT two to five gain_text = "The City Guard know their watch. If you ask them at night, they may tell you about the ashy lantern." - next_knowledge = list(/datum/heretic_knowledge/ashen_grasp) required_atoms = list( /obj/item/knife = 1, /obj/item/match = 1, ) result_atoms = list(/obj/item/melee/sickly_blade/ash) - route = PATH_ASH research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "ash_blade" @@ -47,10 +35,7 @@ desc = "Your Mansus Grasp will burn the eyes of the victim, damaging them and blurring their vision." gain_text = "The Nightwatcher was the first of them, his treason started it all. \ Their lantern, expired to ash - their watch, absent." - next_knowledge = list(/datum/heretic_knowledge/spell/ash_passage) cost = 1 - route = PATH_ASH - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_ash" @@ -77,15 +62,10 @@ name = "Ashen Passage" desc = "Grants you Ashen Passage, a spell that lets you phase out of reality and traverse a short distance, passing though any walls." gain_text = "He knew how to walk between the planes." - next_knowledge = list( - /datum/heretic_knowledge/mark/ash_mark, - /datum/heretic_knowledge/summon/fire_shark, - /datum/heretic_knowledge/medallion, - ) + spell_to_add = /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash cost = 1 - route = PATH_ASH - depth = 4 + /datum/heretic_knowledge/mark/ash_mark name = "Mark of Ash" @@ -96,8 +76,6 @@ gain_text = "He was a very particular man, always watching in the dead of night. \ But in spite of his duty, he regularly tranced through the Manse with his blazing lantern held high. \ He shone brightly in the darkness, until the blaze begin to die." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/ash) - route = PATH_ASH mark_type = /datum/status_effect/eldritch/ash /datum/heretic_knowledge/mark/ash_mark/trigger_mark(mob/living/source, mob/living/target) @@ -112,8 +90,8 @@ grasp.build_all_button_icons() /datum/heretic_knowledge/knowledge_ritual/ash - next_knowledge = list(/datum/heretic_knowledge/spell/fire_blast) - route = PATH_ASH + + /datum/heretic_knowledge/spell/fire_blast name = "Volcano Blast" @@ -121,11 +99,8 @@ at a nearby enemy, setting them on fire and burning them. If they do not extinguish themselves, \ the beam will continue to another target." gain_text = "No fire was hot enough to rekindle them. No fire was bright enough to save them. No fire is eternal." - next_knowledge = list(/datum/heretic_knowledge/mad_mask) spell_to_add = /datum/action/cooldown/spell/charged/beam/fire_blast cost = 1 - route = PATH_ASH - depth = 7 research_tree_icon_frame = 7 @@ -135,12 +110,6 @@ The mask instills fear into heathens who witness it, causing stamina damage, hallucinations, and insanity. \ It can also be forced onto a heathen, to make them unable to take it off..." gain_text = "The Nightwatcher was lost. That's what the Watch believed. Yet he walked the world, unnoticed by the masses." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/ash, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/spell/space_phase, - /datum/heretic_knowledge/curse/paralysis, - ) required_atoms = list( /obj/item/organ/internal/liver = 1, /obj/item/melee/baton/security = 1, // Technically means a cattleprod is valid @@ -149,18 +118,16 @@ ) result_atoms = list(/obj/item/clothing/mask/madness_mask) cost = 1 - route = PATH_ASH research_tree_icon_path = 'icons/obj/clothing/masks.dmi' research_tree_icon_state = "mad_mask" - depth = 8 /datum/heretic_knowledge/blade_upgrade/ash name = "Fiery Blade" desc = "Your blade now lights enemies ablaze on attack." gain_text = "He returned, blade in hand, he swung and swung as the ash fell from the skies. \ His city, the people he swore to watch... and watch he did, as they all burnt to cinders." - next_knowledge = list(/datum/heretic_knowledge/spell/flame_birth) - route = PATH_ASH + + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_ash" @@ -178,15 +145,8 @@ If any victims afflicted are in critical condition, they will also instantly die." gain_text = "The fire was inescapable, and yet, life remained in his charred body. \ The Nightwatcher was a particular man, always watching." - next_knowledge = list( - /datum/heretic_knowledge/ultimate/ash_final, - /datum/heretic_knowledge/summon/ashy, - /datum/heretic_knowledge/eldritch_coin, - ) spell_to_add = /datum/action/cooldown/spell/aoe/fiery_rebirth cost = 1 - route = PATH_ASH - depth = 10 research_tree_icon_frame = 5 /datum/heretic_knowledge/ultimate/ash_final @@ -201,7 +161,7 @@ gain_text = "The Watch is dead, the Nightwatcher burned with it. Yet his fire burns evermore, \ for the Nightwatcher brought forth the rite to mankind! His gaze continues, as now I am one with the flames, \ WITNESS MY ASCENSION, THE ASHY LANTERN BLAZES ONCE MORE!" - route = PATH_ASH + ascension_achievement = /datum/award/achievement/misc/ash_ascension /// A static list of all traits we apply on ascension. var/static/list/traits_to_apply = list( diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index c24ed2c273f..5cffc7bc304 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -1,48 +1,34 @@ -/** - * # The path of Blades. Stab stab. - * - * Goes as follows: - * - * The Cutting Edge - * Grasp of the Blade - * Dance of the Brand - * > Sidepaths: - * Shattered Risen - * Armorer's Ritual - * - * Mark of the Blade - * Ritual of Knowledge - * Realignment - * > Sidepaths: - * Lionhunter Rifle - * - * Stance of the Scarred Duelist - * > Sidepaths: - * Carving Knife - * Mawed Crucible - * - * Swift Blades - * Furious Steel - * > Sidepaths: - * Maid in the Mirror - * Rust Charge - * - * Maelstrom of Silver - */ + +/datum/heretic_knowledge_tree_column/main/blade + neighbour_type_left = /datum/heretic_knowledge_tree_column/void_to_blade + neighbour_type_right = /datum/heretic_knowledge_tree_column/blade_to_rust + + route = PATH_BLADE + ui_bgr = "node_blade" + + start = /datum/heretic_knowledge/limited_amount/starting/base_blade + grasp = /datum/heretic_knowledge/blade_grasp + tier1 = /datum/heretic_knowledge/blade_dance + mark = /datum/heretic_knowledge/mark/blade_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/blade + unique_ability = /datum/heretic_knowledge/spell/realignment + tier2 = /datum/heretic_knowledge/duel_stance + blade = /datum/heretic_knowledge/blade_upgrade/blade + tier3 = /datum/heretic_knowledge/spell/furious_steel + ascension = /datum/heretic_knowledge/ultimate/blade_final + /datum/heretic_knowledge/limited_amount/starting/base_blade name = "The Cutting Edge" desc = "Opens up the Path of Blades to you. \ Allows you to transmute a knife with one bar of silver or titanium to create a Sundered Blade. \ You can create up to four at a time." gain_text = "Our great ancestors forged swords and practiced sparring on the eve of great battles." - next_knowledge = list(/datum/heretic_knowledge/blade_grasp) required_atoms = list( /obj/item/knife = 1, list(/obj/item/stack/sheet/mineral/silver, /obj/item/stack/sheet/mineral/titanium) = 1, ) result_atoms = list(/obj/item/melee/sickly_blade/dark) limit = 4 // It's the blade path, it's a given - route = PATH_BLADE research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "dark_blade" @@ -51,10 +37,7 @@ desc = "Your Mansus Grasp will cause a short stun when used on someone lying down or facing away from you." gain_text = "The story of the footsoldier has been told since antiquity. It is one of blood and valor, \ and is championed by sword, steel and silver." - next_knowledge = list(/datum/heretic_knowledge/blade_dance) cost = 1 - route = PATH_BLADE - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_blade" @@ -85,14 +68,7 @@ towards your attacker. This effect can only trigger once every 20 seconds." gain_text = "The footsoldier was known to be a fearsome duelist. \ Their general quickly appointed them as their personal Champion." - next_knowledge = list( - /datum/heretic_knowledge/limited_amount/risen_corpse, - /datum/heretic_knowledge/mark/blade_mark, - /datum/heretic_knowledge/armor, - ) cost = 1 - route = PATH_BLADE - depth = 4 research_tree_icon_path = 'icons/mob/actions/actions_ecult.dmi' research_tree_icon_state = "shatter" /// Whether the counter-attack is ready or not. @@ -183,8 +159,6 @@ The knife will block any attack directed towards you, but is consumed on use." gain_text = "His general wished to end the war, but the Champion knew there could be no life without death. \ He would slay the coward himself, and anyone who tried to run." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/blade) - route = PATH_BLADE mark_type = /datum/status_effect/eldritch/blade /datum/heretic_knowledge/mark/blade_mark/create_mark(mob/living/source, mob/living/target) @@ -202,8 +176,8 @@ source.apply_status_effect(/datum/status_effect/protective_blades, 60 SECONDS, 1, 20, 0 SECONDS) /datum/heretic_knowledge/knowledge_ritual/blade - next_knowledge = list(/datum/heretic_knowledge/spell/realignment) - route = PATH_BLADE + + /datum/heretic_knowledge/spell/realignment name = "Realignment" @@ -211,11 +185,9 @@ During this process, you will rapidly regenerate stamina and quickly recover from stuns, however, you will be unable to attack. \ This spell can be cast in rapid succession, but doing so will increase the cooldown." gain_text = "In the flurry of death, he found peace within himself. Despite insurmountable odds, he forged on." - next_knowledge = list(/datum/heretic_knowledge/duel_stance) spell_to_add = /datum/action/cooldown/spell/realignment cost = 1 - route = PATH_BLADE - depth = 7 + /// The amount of blood flow reduced per level of severity of gained bleeding wounds for Stance of the Torn Champion. #define BLOOD_FLOW_PER_SEVEIRTY -1 @@ -227,16 +199,7 @@ you gain increased resistance to gaining wounds and resistance to batons." gain_text = "In time, it was he who stood alone among the bodies of his former comrades, awash in blood, none of it his own. \ He was without rival, equal, or purpose." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/blade, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/rune_carver, - /datum/heretic_knowledge/crucible, - /datum/heretic_knowledge/rifle, - ) cost = 1 - route = PATH_BLADE - depth = 8 research_tree_icon_path = 'icons/effects/blood.dmi' research_tree_icon_state = "suitblood" research_tree_icon_dir = SOUTH @@ -298,8 +261,6 @@ You are able to infuse your mansus grasp directly into your blades, and your blades are more effective against structures." gain_text = "I found him cleaved in twain, halves locked in a duel without end; \ a flurry of blades, neither hitting their mark, for the Champion was indomitable." - next_knowledge = list(/datum/heretic_knowledge/spell/furious_steel) - route = PATH_BLADE research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_blade" /// How much force do we apply to the offhand? @@ -403,15 +364,8 @@ at a target, dealing damage and causing bleeding." gain_text = "Without thinking, I took the knife of a fallen soldier and threw with all my might. My aim was true! \ The Torn Champion smiled at their first taste of agony, and with a nod, their blades became my own." - next_knowledge = list( - /datum/heretic_knowledge/summon/maid_in_mirror, - /datum/heretic_knowledge/ultimate/blade_final, - /datum/heretic_knowledge/spell/rust_charge, - ) spell_to_add = /datum/action/cooldown/spell/pointed/projectile/furious_steel cost = 1 - route = PATH_BLADE - depth = 10 /datum/heretic_knowledge/ultimate/blade_final name = "Maelstrom of Silver" @@ -424,7 +378,7 @@ Your Sundered Blades deal bonus damage and heal you on attack for a portion of the damage dealt." gain_text = "The Torn Champion is freed! I will become the blade reunited, and with my greater ambition, \ I AM UNMATCHED! A STORM OF STEEL AND SILVER IS UPON US! WITNESS MY ASCENSION!" - route = PATH_BLADE + ascension_achievement = /datum/award/achievement/misc/blade_ascension /datum/heretic_knowledge/ultimate/blade_final/is_valid_sacrifice(mob/living/carbon/human/sacrifice) @@ -444,7 +398,7 @@ ) ADD_TRAIT(user, TRAIT_NEVER_WOUNDED, name) RegisterSignal(user, COMSIG_HERETIC_BLADE_ATTACK, PROC_REF(on_eldritch_blade)) - user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, 1 MINUTES) + user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, /obj/effect/floating_blade, 1 MINUTES) user.add_stun_absorption( source = name, message = span_warning("%EFFECT_OWNER throws off the stun!"), diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index af92a55f499..6a895a7ffdf 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -1,43 +1,33 @@ -/** - * # The path of Cosmos. - * - * Goes as follows: - * - * Eternal Gate - * Grasp of Cosmos - * Cosmic Runes - * > Sidepaths: - * Priest's Ritual - * Scorching Shark - * - * Mark of Cosmos - * Ritual of Knowledge - * Star Touch - * Star Blast - * > Sidepaths: - * Curse of Corrosion - * Space Phase - * - * Cosmic Blade - * Cosmic Expansion - * > Sidepaths: - * Eldritch Coin - * - * Creators's Gift - */ + +/datum/heretic_knowledge_tree_column/main/cosmic + neighbour_type_left = /datum/heretic_knowledge_tree_column/rust_to_cosmic + neighbour_type_right = /datum/heretic_knowledge_tree_column/cosmic_to_ash + + route = PATH_COSMIC + ui_bgr = "node_cosmos" + + start = /datum/heretic_knowledge/limited_amount/starting/base_cosmic + grasp = /datum/heretic_knowledge/cosmic_grasp + tier1 = /datum/heretic_knowledge/spell/cosmic_runes + mark = /datum/heretic_knowledge/mark/cosmic_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/cosmic + unique_ability = /datum/heretic_knowledge/spell/star_touch + tier2 = /datum/heretic_knowledge/spell/star_blast + blade = /datum/heretic_knowledge/blade_upgrade/cosmic + tier3 = /datum/heretic_knowledge/spell/cosmic_expansion + ascension = /datum/heretic_knowledge/ultimate/cosmic_final + /datum/heretic_knowledge/limited_amount/starting/base_cosmic name = "Eternal Gate" desc = "Opens up the Path of Cosmos to you. \ Allows you to transmute a sheet of plasma and a knife into an Cosmic Blade. \ You can only create two at a time." gain_text = "A nebula appeared in the sky, its infernal birth shone upon me. This was the start of a great transcendence." - next_knowledge = list(/datum/heretic_knowledge/cosmic_grasp) required_atoms = list( /obj/item/knife = 1, /obj/item/stack/sheet/mineral/plasma = 1, ) result_atoms = list(/obj/item/melee/sickly_blade/cosmic) - route = PATH_COSMIC research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "cosmic_blade" @@ -47,10 +37,7 @@ People with a star mark can not pass cosmic fields." gain_text = "Some stars dimmed, others' magnitude increased. \ With newfound strength I could channel the nebula's power into myself." - next_knowledge = list(/datum/heretic_knowledge/spell/cosmic_runes) cost = 1 - route = PATH_COSMIC - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_cosmos" @@ -75,15 +62,9 @@ However, people with a star mark will get transported along with another person using the rune." gain_text = "The distant stars crept into my dreams, roaring and screaming without reason. \ I spoke, and heard my own words echoed back." - next_knowledge = list( - /datum/heretic_knowledge/summon/fire_shark, - /datum/heretic_knowledge/mark/cosmic_mark, - /datum/heretic_knowledge/essence, - ) spell_to_add = /datum/action/cooldown/spell/cosmic_rune cost = 1 - route = PATH_COSMIC - depth = 4 + /datum/heretic_knowledge/mark/cosmic_mark name = "Mark of Cosmos" @@ -93,13 +74,9 @@ They will then be paralyzed for 2 seconds." gain_text = "The Beast now whispered to me occasionally, only small tidbits of their circumstances. \ I can help them, I have to help them." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/cosmic) - route = PATH_COSMIC mark_type = /datum/status_effect/eldritch/cosmic /datum/heretic_knowledge/knowledge_ritual/cosmic - next_knowledge = list(/datum/heretic_knowledge/spell/star_touch) - route = PATH_COSMIC /datum/heretic_knowledge/spell/star_touch name = "Star Touch" @@ -109,28 +86,16 @@ The beam lasts a minute, until the beam is obstructed or until a new target has been found." gain_text = "After waking in a cold sweat I felt a palm on my scalp, a sigil burned onto me. \ My veins now emitted a strange purple glow, the Beast knows I will surpass its expectations." - next_knowledge = list(/datum/heretic_knowledge/spell/star_blast) spell_to_add = /datum/action/cooldown/spell/touch/star_touch cost = 1 - route = PATH_COSMIC - depth = 7 /datum/heretic_knowledge/spell/star_blast name = "Star Blast" desc = "Fires a projectile that moves very slowly, raising a short-lived wall of cosmic fields where it goes. \ Anyone hit by the projectile will receive burn damage, a knockdown, and give people in a three tile range a star mark." gain_text = "The Beast was behind me now at all times, with each sacrifice words of affirmation coursed through me." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/cosmic, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/curse/corrosion, - /datum/heretic_knowledge/summon/rusty, - /datum/heretic_knowledge/spell/space_phase, - ) spell_to_add = /datum/action/cooldown/spell/pointed/projectile/star_blast cost = 1 - route = PATH_COSMIC - depth = 8 /datum/heretic_knowledge/blade_upgrade/cosmic name = "Cosmic Blade" @@ -141,8 +106,6 @@ a cosmic trail and increase your combo timer up to ten seconds." gain_text = "The Beast took my blades in their hand, I kneeled and felt a sharp pain. \ The blades now glistened with fragmented power. I fell to the ground and wept at the beast's feet." - next_knowledge = list(/datum/heretic_knowledge/spell/cosmic_expansion) - route = PATH_COSMIC research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_cosmos" /// Storage for the second target. @@ -236,14 +199,8 @@ desc = "Grants you Cosmic Expansion, a spell that creates a 3x3 area of cosmic fields around you. \ Nearby beings will also receive a star mark." gain_text = "The ground now shook beneath me. The Beast inhabited me, and their voice was intoxicating." - next_knowledge = list( - /datum/heretic_knowledge/ultimate/cosmic_final, - /datum/heretic_knowledge/eldritch_coin, - ) spell_to_add = /datum/action/cooldown/spell/conjure/cosmic_expansion cost = 1 - route = PATH_COSMIC - depth = 10 /datum/heretic_knowledge/ultimate/cosmic_final name = "Creators's Gift" @@ -260,7 +217,7 @@ I clung on to them, they would protect me, and I would protect it. \ I closed my eyes with my head laid against their form. I was safe. \ WITNESS MY ASCENSION!" - route = PATH_COSMIC + ascension_achievement = /datum/award/achievement/misc/cosmic_ascension /// A static list of command we can use with our mob. var/static/list/star_gazer_commands = list( diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index decea3b16fd..33bedad5195 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -3,47 +3,36 @@ /// The max amount of health a voiceless dead has. #define MUTE_MAX_HEALTH 50 -/** - * # The path of Flesh. - * - * Goes as follows: - * - * Principle of Hunger - * Grasp of Flesh - * Imperfect Ritual - * > Sidepaths: - * Void Cloak - * - * Mark of Flesh - * Ritual of Knowledge - * Flesh Surgery - * Raw Ritual - * > Sidepaths: - * Blood Siphon - * Opening Blast - * - * Bleeding Steel - * Lonely Ritual - * > Sidepaths: - * Cleave - * Aptera Vulnera - * - * Priest's Final Hymn - */ +/datum/heretic_knowledge_tree_column/main/flesh + neighbour_type_left = /datum/heretic_knowledge_tree_column/lock_to_flesh + neighbour_type_right = /datum/heretic_knowledge_tree_column/flesh_to_void + + route = PATH_FLESH + ui_bgr = "node_flesh" + + start = /datum/heretic_knowledge/limited_amount/starting/base_flesh + grasp = /datum/heretic_knowledge/limited_amount/flesh_grasp + tier1 = /datum/heretic_knowledge/limited_amount/flesh_ghoul + mark = /datum/heretic_knowledge/mark/flesh_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/flesh + unique_ability = /datum/heretic_knowledge/spell/flesh_surgery + tier2 = /datum/heretic_knowledge/summon/raw_prophet + blade = /datum/heretic_knowledge/blade_upgrade/flesh + tier3 = /datum/heretic_knowledge/summon/stalker + ascension = /datum/heretic_knowledge/ultimate/flesh_final + /datum/heretic_knowledge/limited_amount/starting/base_flesh name = "Principle of Hunger" desc = "Opens up the Path of Flesh to you. \ Allows you to transmute a knife and a pool of blood into a Bloody Blade. \ You can only create twenty at a time." //NOVA EDIT three to twenty gain_text = "Hundreds of us starved, but not me... I found strength in my greed." - next_knowledge = list(/datum/heretic_knowledge/limited_amount/flesh_grasp) required_atoms = list( /obj/item/knife = 1, /obj/effect/decal/cleanable/blood = 1, ) result_atoms = list(/obj/item/melee/sickly_blade/flesh) limit = 3 // Bumped up so they can arm up their ghouls too. - route = PATH_FLESH research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "flesh_blade" @@ -62,11 +51,11 @@ Ghouls have only 25 health and look like husks to the heathens' eyes, but can use Bloody Blades effectively. \ You can only create one at a time by this method." gain_text = "My new found desires drove me to greater and greater heights." - next_knowledge = list(/datum/heretic_knowledge/limited_amount/flesh_ghoul) + limit = 1 cost = 1 - route = PATH_FLESH - depth = 3 + + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_flesh" @@ -131,21 +120,16 @@ Voiceless Dead are mute ghouls and only have 50 health, but can use Bloody Blades effectively. \ You can only create two at a time." gain_text = "I found notes of a dark ritual, unfinished... yet still, I pushed forward." - next_knowledge = list( - /datum/heretic_knowledge/mark/flesh_mark, - /datum/heretic_knowledge/void_cloak, - ) required_atoms = list( /mob/living/carbon/human = 1, /obj/item/food/grown/poppy = 1, ) limit = 2 cost = 1 - route = PATH_FLESH research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "ghoul_voiceless" - depth = 4 + /datum/heretic_knowledge/limited_amount/flesh_ghoul/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) . = ..() @@ -217,13 +201,11 @@ desc = "Your Mansus Grasp now applies the Mark of Flesh. The mark is triggered from an attack with your Bloody Blade. \ When triggered, the victim begins to bleed significantly." gain_text = "That's when I saw them, the marked ones. They were out of reach. They screamed, and screamed." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/flesh) - route = PATH_FLESH + + mark_type = /datum/status_effect/eldritch/flesh /datum/heretic_knowledge/knowledge_ritual/flesh - next_knowledge = list(/datum/heretic_knowledge/spell/flesh_surgery) - route = PATH_FLESH /datum/heretic_knowledge/spell/flesh_surgery name = "Knitting of Flesh" @@ -232,11 +214,8 @@ This spell also allows you to heal your minions and summons, or restore failing organs to acceptable status." gain_text = "But they were not out of my reach for long. With every step, the screams grew, until at last \ I learned that they could be silenced." - next_knowledge = list(/datum/heretic_knowledge/summon/raw_prophet) spell_to_add = /datum/action/cooldown/spell/touch/flesh_surgery cost = 1 - route = PATH_FLESH - depth = 7 /datum/heretic_knowledge/summon/raw_prophet name = "Raw Ritual" @@ -245,12 +224,6 @@ the ability to link minds to communicate with ease, but are very fragile and weak in combat." gain_text = "I could not continue alone. I was able to summon The Uncanny Man to help me see more. \ The screams... once constant, now silenced by their wretched appearance. Nothing was out of reach." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/flesh, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/spell/blood_siphon, - /datum/heretic_knowledge/spell/opening_blast, - ) required_atoms = list( /obj/item/organ/internal/eyes = 1, /obj/effect/decal/cleanable/blood = 1, @@ -258,17 +231,14 @@ ) mob_to_summon = /mob/living/basic/heretic_summon/raw_prophet cost = 1 - route = PATH_FLESH poll_ignore_define = POLL_IGNORE_RAW_PROPHET - depth = 8 + /datum/heretic_knowledge/blade_upgrade/flesh name = "Bleeding Steel" desc = "Your Bloody Blade now causes enemies to bleed heavily on attack." gain_text = "The Uncanny Man was not alone. They led me to the Marshal. \ I finally began to understand. And then, blood rained from the heavens." - next_knowledge = list(/datum/heretic_knowledge/summon/stalker) - route = PATH_FLESH research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_flesh" ///What type of wound do we apply on hit @@ -289,11 +259,7 @@ Stalkers can jaunt, release EMPs, shapeshift into animals or automatons, and are strong in combat." gain_text = "I was able to combine my greed and desires to summon an eldritch beast I had never seen before. \ An ever shapeshifting mass of flesh, it knew well my goals. The Marshal approved." - next_knowledge = list( - /datum/heretic_knowledge/ultimate/flesh_final, - /datum/heretic_knowledge/spell/apetra_vulnera, - /datum/heretic_knowledge/spell/cleave, - ) + required_atoms = list( /obj/item/organ/external/tail = 1, /obj/item/organ/internal/stomach = 1, @@ -303,9 +269,9 @@ ) mob_to_summon = /mob/living/basic/heretic_summon/stalker cost = 1 - route = PATH_FLESH + poll_ignore_define = POLL_IGNORE_STALKER - depth = 10 + /datum/heretic_knowledge/ultimate/flesh_final name = "Priest's Final Hymn" @@ -321,7 +287,6 @@ Men of this world, hear me, for the time has come! The Marshal guides my army! \ Reality will bend to THE LORD OF THE NIGHT or be unraveled! WITNESS MY ASCENSION!" required_atoms = list(/mob/living/carbon/human = 4) - route = PATH_FLESH ascension_achievement = /datum/award/achievement/misc/flesh_ascension /datum/heretic_knowledge/ultimate/flesh_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc) diff --git a/code/modules/antagonists/heretic/knowledge/general_side.dm b/code/modules/antagonists/heretic/knowledge/general_side.dm index 10ff108c5f8..e2f445cb8a6 100644 --- a/code/modules/antagonists/heretic/knowledge/general_side.dm +++ b/code/modules/antagonists/heretic/knowledge/general_side.dm @@ -11,8 +11,6 @@ /obj/item/clothing/under = 1, ) cost = 1 - route = PATH_SIDE - depth = 8 research_tree_icon_path = 'icons/mob/actions/actions_animal.dmi' research_tree_icon_state = "gaze" diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm index 00946bea682..28e02112fd7 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -1,29 +1,22 @@ -/** - * # The path of Lock. - * - * Goes as follows: - * - * A Steward's Secret - * Grasp of Lock - * Key Keeper’s Burden - * > Sidepaths: - * Mindgate - * Concierge's Rite - * Mark Of Lock - * Ritual of Knowledge - * Burglar's Finesse - * > Sidepaths: - * Opening Blast - * Unfathomable Curio - * Unsealed arts - * - * Opening Blade - * Caretaker’s Last Refuge - * > Sidepaths: - * Apetra Vulnera - * - * Unlock the Labyrinth - */ + +/datum/heretic_knowledge_tree_column/main/lock + neighbour_type_left = /datum/heretic_knowledge_tree_column/moon_to_lock + neighbour_type_right = /datum/heretic_knowledge_tree_column/lock_to_flesh + + route = PATH_LOCK + ui_bgr = "node_lock" + + start = /datum/heretic_knowledge/limited_amount/starting/base_knock + grasp = /datum/heretic_knowledge/lock_grasp + tier1 = /datum/heretic_knowledge/key_ring + mark = /datum/heretic_knowledge/mark/lock_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/lock + unique_ability = /datum/heretic_knowledge/limited_amount/concierge_rite + tier2 = /datum/heretic_knowledge/spell/burglar_finesse + blade = /datum/heretic_knowledge/blade_upgrade/flesh/lock + tier3 = /datum/heretic_knowledge/spell/caretaker_refuge + ascension = /datum/heretic_knowledge/ultimate/lock_final + /datum/heretic_knowledge/limited_amount/starting/base_knock name = "A Steward's Secret" desc = "Opens up the Path of Lock to you. \ @@ -31,14 +24,12 @@ You can only create two at a time and they function as fast crowbars. \ In addition, they can fit into utility belts." gain_text = "The Locked Labyrinth leads to freedom. But only the trapped Stewards know the correct path." - next_knowledge = list(/datum/heretic_knowledge/lock_grasp) required_atoms = list( /obj/item/knife = 1, /obj/item/crowbar = 1, ) result_atoms = list(/obj/item/melee/sickly_blade/lock) limit = 2 - route = PATH_LOCK research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "key_blade" @@ -48,10 +39,7 @@ DNA locks on mechs will be removed, and any pilot will be ejected. Works on consoles. \ Makes a distinctive knocking sound on use." gain_text = "Nothing may remain closed from my touch." - next_knowledge = list(/datum/heretic_knowledge/key_ring) cost = 1 - route = PATH_LOCK - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_lock" @@ -112,15 +100,10 @@ /obj/item/card/id = 1, ) result_atoms = list(/obj/item/card/id/advanced/heretic) - next_knowledge = list( - /datum/heretic_knowledge/mark/lock_mark, - /datum/heretic_knowledge/spell/mind_gate, - ) cost = 1 - route = PATH_LOCK research_tree_icon_path = 'icons/obj/card.dmi' research_tree_icon_state = "card_gold" - depth = 4 + /datum/heretic_knowledge/mark/lock_mark name = "Mark of Lock" @@ -128,13 +111,9 @@ Attack a marked person to bar them from all passages for the duration of the mark. \ This will make it so that they have no access whatsoever, even public access doors will reject them." gain_text = "The Gatekeeper was a corrupt Steward. She hindered her fellows for her own twisted amusement." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/lock) - route = PATH_LOCK mark_type = /datum/status_effect/eldritch/lock /datum/heretic_knowledge/knowledge_ritual/lock - next_knowledge = list(/datum/heretic_knowledge/limited_amount/concierge_rite) - route = PATH_LOCK /datum/heretic_knowledge/limited_amount/concierge_rite // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass name = "Concierge's Rite" @@ -147,36 +126,23 @@ /obj/item/multitool = 1, ) result_atoms = list(/obj/item/heretic_labyrinth_handbook) - next_knowledge = list(/datum/heretic_knowledge/spell/burglar_finesse) cost = 1 - route = PATH_LOCK research_tree_icon_path = 'icons/obj/service/library.dmi' research_tree_icon_state = "heretichandbook" - depth = 7 /datum/heretic_knowledge/spell/burglar_finesse name = "Burglar's Finesse" desc = "Grants you Burglar's Finesse, a single-target spell \ that puts a random item from the victims backpack into your hand." gain_text = "Consorting with Burglar spirits is frowned upon, but a Steward will always want to learn about new doors." - next_knowledge = list( - /datum/heretic_knowledge/spell/opening_blast, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/blade_upgrade/flesh/lock, - /datum/heretic_knowledge/unfathomable_curio, - /datum/heretic_knowledge/painting, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/burglar_finesse cost = 1 - route = PATH_LOCK - depth = 8 /datum/heretic_knowledge/blade_upgrade/flesh/lock //basically a chance-based weeping avulsion version of the former name = "Opening Blade" desc = "Your blade has a chance to cause a weeping avulsion on attack." gain_text = "The Pilgrim-Surgeon was not an Steward. Nonetheless, its blades and sutures proved a match for their keys." - next_knowledge = list(/datum/heretic_knowledge/spell/caretaker_refuge) - route = PATH_LOCK wound_type = /datum/wound/slash/flesh/critical research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_lock" @@ -192,14 +158,8 @@ While in refuge, you cannot use your hands or spells, and you are immune to slowdown. \ You are invincible but unable to harm anything. Cancelled by being hit with an anti-magic item." gain_text = "Jealously, the Guard and the Hound hunted me. But I unlocked my form, and was but a haze, untouchable." - next_knowledge = list( - /datum/heretic_knowledge/ultimate/lock_final, - /datum/heretic_knowledge/spell/apetra_vulnera, - ) - route = PATH_LOCK spell_to_add = /datum/action/cooldown/spell/caretaker cost = 1 - depth = 10 /datum/heretic_knowledge/ultimate/lock_final name = "Unlock the Labyrinth" @@ -215,7 +175,6 @@ My foes were the Locks and my blades were the Key! \ The Labyrinth will be Locked no more, and freedom will be ours! WITNESS US!" required_atoms = list(/mob/living/carbon/human = 3) - route = PATH_LOCK ascension_achievement = /datum/award/achievement/misc/lock_ascension /datum/heretic_knowledge/ultimate/lock_final/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) diff --git a/code/modules/antagonists/heretic/knowledge/moon_lore.dm b/code/modules/antagonists/heretic/knowledge/moon_lore.dm index 78041a5b9d7..499d2444048 100644 --- a/code/modules/antagonists/heretic/knowledge/moon_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/moon_lore.dm @@ -1,48 +1,37 @@ -/** - * # The path of Moon. - * - * Goes as follows: - * - * Moonlight Troupe - * Grasp of Lunacy - * Smile of the moon - * > Sidepaths: - * Mind Gate - * Ashen Eyes - * - * Mark of Moon - * Ritual of Knowledge - * Lunar Parade - * Moonlight Amulet - * > Sidepaths: - * Curse of Paralasys - * Unfathomable Curio - * Unsealed Arts - * - * Moonlight blade - * Ringleaders Rise - * > Sidepaths: - * Ashen Ritual - * - * Last Act - */ + +/datum/heretic_knowledge_tree_column/main/moon + neighbour_type_left = /datum/heretic_knowledge_tree_column/ash_to_moon + neighbour_type_right = /datum/heretic_knowledge_tree_column/moon_to_lock + + route = PATH_MOON + ui_bgr = "node_moon" + + start = /datum/heretic_knowledge/limited_amount/starting/base_moon + grasp = /datum/heretic_knowledge/moon_grasp + tier1 = /datum/heretic_knowledge/spell/moon_smile + mark = /datum/heretic_knowledge/mark/moon_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/moon + unique_ability = /datum/heretic_knowledge/spell/moon_parade + tier2 = /datum/heretic_knowledge/moon_amulet + blade = /datum/heretic_knowledge/blade_upgrade/moon + tier3 = /datum/heretic_knowledge/spell/moon_ringleader + ascension = /datum/heretic_knowledge/ultimate/moon_final + /datum/heretic_knowledge/limited_amount/starting/base_moon name = "Moonlight Troupe" desc = "Opens up the Path of Moon to you. \ Allows you to transmute 2 sheets of iron and a knife into an Lunar Blade. \ You can only create two at a time." gain_text = "Under the light of the moon the laughter echoes." - next_knowledge = list(/datum/heretic_knowledge/moon_grasp) required_atoms = list( /obj/item/knife = 1, /obj/item/stack/sheet/iron = 2, ) result_atoms = list(/obj/item/melee/sickly_blade/moon) - route = PATH_MOON research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "moon_blade" -/datum/heretic_knowledge/base_moon/on_gain(mob/user, datum/antagonist/heretic/our_heretic) +/datum/heretic_knowledge/limited_amount/starting/base_moon/on_gain(mob/user, datum/antagonist/heretic/our_heretic) add_traits(user ,TRAIT_EMPATH, REF(src)) /datum/heretic_knowledge/moon_grasp @@ -50,10 +39,7 @@ desc = "Your Mansus Grasp will cause your victims to hallucinate everyone as lunar mass, \ and hides your identity for a short duration." gain_text = "The troupe on the side of the moon showed me truth, and I took it." - next_knowledge = list(/datum/heretic_knowledge/spell/moon_smile) cost = 1 - route = PATH_MOON - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_moon" @@ -83,15 +69,9 @@ desc = "Grants you Smile of the moon, a ranged spell muting, blinding, deafening and knocking down the target for a\ duration based on their sanity." gain_text = "The moon smiles upon us all and those who see its true side can bring its joy." - next_knowledge = list( - /datum/heretic_knowledge/mark/moon_mark, - /datum/heretic_knowledge/medallion, - /datum/heretic_knowledge/spell/mind_gate, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/moon_smile cost = 1 - route = PATH_MOON - depth = 4 /datum/heretic_knowledge/mark/moon_mark name = "Mark of Moon" @@ -100,25 +80,17 @@ gain_text = "The troupe on the moon would dance all day long \ and in that dance the moon would smile upon us \ but when the night came its smile would dull forced to gaze on the earth." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/moon) - route = PATH_MOON mark_type = /datum/status_effect/eldritch/moon /datum/heretic_knowledge/knowledge_ritual/moon - next_knowledge = list(/datum/heretic_knowledge/spell/moon_parade) - route = PATH_MOON /datum/heretic_knowledge/spell/moon_parade name = "Lunar Parade" desc = "Grants you Lunar Parade, a spell that - after a short charge - sends a carnival forward \ when hitting someone they are forced to join the parade and suffer hallucinations." gain_text = "The music like a reflection of the soul compelled them, like moths to a flame they followed" - next_knowledge = list(/datum/heretic_knowledge/moon_amulet) spell_to_add = /datum/action/cooldown/spell/pointed/projectile/moon_parade cost = 1 - route = PATH_MOON - depth = 7 - /datum/heretic_knowledge/moon_amulet name = "Moonlight Amulet" @@ -126,13 +98,7 @@ If the item is used on someone with low sanity they go berserk attacking everyone, \ if their sanity isn't low enough it decreases their mood." gain_text = "At the head of the parade he stood, the moon condensed into one mass, a reflection of the soul." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/moon, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/unfathomable_curio, - /datum/heretic_knowledge/curse/paralysis, - /datum/heretic_knowledge/painting, - ) + required_atoms = list( /obj/item/organ/internal/heart = 1, /obj/item/stack/sheet/glass = 2, @@ -140,8 +106,8 @@ ) result_atoms = list(/obj/item/clothing/neck/heretic_focus/moon_amulet) cost = 1 - route = PATH_MOON - depth = 8 + + research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "moon_amulette" research_tree_icon_frame = 9 @@ -150,8 +116,8 @@ name = "Moonlight Blade" desc = "Your blade now deals brain damage, causes random hallucinations and does sanity damage." gain_text = "His wit was sharp as a blade, cutting through the lie to bring us joy." - next_knowledge = list(/datum/heretic_knowledge/spell/moon_ringleader) - route = PATH_MOON + + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_moon" @@ -177,14 +143,11 @@ If their sanity is low enough this turns them insane, the spell then halves their sanity." gain_text = "I grabbed his hand and we rose, those who saw the truth rose with us. \ The ringleader pointed up and the dim light of truth illuminated us further." - next_knowledge = list( - /datum/heretic_knowledge/ultimate/moon_final, - /datum/heretic_knowledge/summon/ashy, - ) + spell_to_add = /datum/action/cooldown/spell/aoe/moon_ringleader cost = 1 - route = PATH_MOON - depth = 10 + + research_tree_icon_frame = 5 /datum/heretic_knowledge/ultimate/moon_final @@ -197,7 +160,7 @@ gain_text = "We dived down towards the crowd, his soul splitting off in search of greater venture \ for where the Ringleader had started the parade, I shall continue it unto the suns demise \ WITNESS MY ASCENSION, THE MOON SMILES ONCE MORE AND FOREVER MORE IT SHALL!" - route = PATH_MOON + ascension_achievement = /datum/award/achievement/misc/moon_ascension /datum/heretic_knowledge/ultimate/moon_final/is_valid_sacrifice(mob/living/sacrifice) diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index 9d45e8bb55b..a2f0a91e69a 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -1,47 +1,33 @@ -/** - * # The path of Rust. - * - * Goes as follows: - * - * Blacksmith's Tale - * Grasp of Rust - * Leeching Walk - * > Sidepaths: - * Priest's Ritual - * Armorer's Ritual - * - * Mark of Rust - * Ritual of Knowledge - * Rust Construction - * > Sidepaths: - * Lionhunter Rifle - * - * Aggressive Spread - * > Sidepaths: - * Curse of Corrosion - * Mawed Crucible - * - * Toxic Blade - * Entropic Plume - * > Sidepaths: - * Rusted Ritual - * Rust Charge - * - * Rustbringer's Oath - */ + +/datum/heretic_knowledge_tree_column/main/rust + neighbour_type_left = /datum/heretic_knowledge_tree_column/blade_to_rust + neighbour_type_right = /datum/heretic_knowledge_tree_column/rust_to_cosmic + + route = PATH_RUST + ui_bgr = "node_rust" + + start = /datum/heretic_knowledge/limited_amount/starting/base_rust + grasp = /datum/heretic_knowledge/rust_fist + tier1 = /datum/heretic_knowledge/rust_regen + mark = /datum/heretic_knowledge/mark/rust_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/rust + unique_ability = /datum/heretic_knowledge/spell/rust_construction + tier2 = /datum/heretic_knowledge/spell/area_conversion + blade = /datum/heretic_knowledge/blade_upgrade/rust + tier3 = /datum/heretic_knowledge/spell/entropic_plume + ascension = /datum/heretic_knowledge/ultimate/rust_final + /datum/heretic_knowledge/limited_amount/starting/base_rust name = "Blacksmith's Tale" desc = "Opens up the Path of Rust to you. \ Allows you to transmute a knife with any trash item into a Rusty Blade. \ You can only create two at a time." gain_text = "\"Let me tell you a story\", said the Blacksmith, as he gazed deep into his rusty blade." - next_knowledge = list(/datum/heretic_knowledge/rust_fist) required_atoms = list( /obj/item/knife = 1, /obj/item/trash = 1, ) result_atoms = list(/obj/item/melee/sickly_blade/rust) - route = PATH_RUST research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "rust_blade" @@ -51,10 +37,7 @@ Already rusted surfaces are destroyed. Surfaces and structures can only be rusted by using Right-Click. \ Allows you to rust basic iron walls and floors." gain_text = "On the ceiling of the Mansus, rust grows as moss does on a stone." - next_knowledge = list(/datum/heretic_knowledge/rust_regen) cost = 1 - route = PATH_RUST - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_rust" @@ -90,17 +73,10 @@ name = "Leeching Walk" desc = "Grants you passive healing and resistance to batons while standing over rust." gain_text = "The speed was unparalleled, the strength unnatural. The Blacksmith was smiling." - next_knowledge = list( - /datum/heretic_knowledge/mark/rust_mark, - /datum/heretic_knowledge/armor, - /datum/heretic_knowledge/essence, - /datum/heretic_knowledge/entropy_pulse, - ) cost = 1 - route = PATH_RUST research_tree_icon_path = 'icons/effects/eldritch.dmi' research_tree_icon_state = "cloud_swirl" - depth = 4 + /datum/heretic_knowledge/rust_regen/on_gain(mob/user, datum/antagonist/heretic/our_heretic) user.AddElement(/datum/element/leeching_walk) @@ -114,8 +90,6 @@ When triggered, your victim will suffer heavy disgust and confusion. \ Allows you to rust reinforced walls and floors as well as plasteel." gain_text = "The Blacksmith looks away. To a place lost long ago. \"Rusted Hills help those in dire need... at a cost.\"" - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/rust) - route = PATH_RUST mark_type = /datum/status_effect/eldritch/rust /datum/heretic_knowledge/mark/rust_mark/on_gain(mob/user, datum/antagonist/heretic/our_heretic) @@ -123,8 +97,6 @@ our_heretic.increase_rust_strength() /datum/heretic_knowledge/knowledge_ritual/rust - next_knowledge = list(/datum/heretic_knowledge/spell/rust_construction) - route = PATH_RUST /datum/heretic_knowledge/spell/rust_construction name = "Rust Construction" @@ -132,29 +104,16 @@ Anyone overtop the wall will be throw aside (or upwards) and sustain damage." gain_text = "Images of foreign and ominous structures began to dance in my mind. Covered head to toe in thick rust, \ they no longer looked man made. Or perhaps they never were in the first place." - next_knowledge = list(/datum/heretic_knowledge/spell/area_conversion) spell_to_add = /datum/action/cooldown/spell/pointed/rust_construction cost = 1 - route = PATH_RUST - depth = 7 /datum/heretic_knowledge/spell/area_conversion name = "Aggressive Spread" desc = "Grants you Aggressive Spread, a spell that spreads rust to nearby surfaces. \ Already rusted surfaces are destroyed \ Also improves the rusting abilities of non rust-heretics." gain_text = "All wise men know well not to visit the Rusted Hills... Yet the Blacksmith's tale was inspiring." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/rust, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/curse/corrosion, - /datum/heretic_knowledge/summon/rusty, - /datum/heretic_knowledge/crucible, - /datum/heretic_knowledge/rifle, - ) spell_to_add = /datum/action/cooldown/spell/aoe/rust_conversion cost = 1 - route = PATH_RUST - depth = 8 research_tree_icon_frame = 5 /datum/heretic_knowledge/spell/area_conversion/on_gain(mob/user, datum/antagonist/heretic/our_heretic) @@ -166,8 +125,6 @@ desc = "Your Rusty Blade now disgusts enemies on attack \ Allows you to rust Titanium and Plastitanium.." gain_text = "The Blacksmith hands you their blade. \"The Blade will guide you through the flesh, should you let it.\" \ The heavy rust weights it down. You stare deeply into it. The Rusted Hills call for you, now." - next_knowledge = list(/datum/heretic_knowledge/spell/entropic_plume) - route = PATH_RUST research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_rust" @@ -189,14 +146,11 @@ at friend or foe wildly. Also rusts and destroys and surfaces it hits and improves the rusting abilities of non-rust heretics." gain_text = "The corrosion was unstoppable. The rust was unpleasable. \ The Blacksmith was gone, and you hold their blade. Champions of hope, the Rustbringer is nigh!" - next_knowledge = list( - /datum/heretic_knowledge/ultimate/rust_final, - /datum/heretic_knowledge/spell/rust_charge, - ) + spell_to_add = /datum/action/cooldown/spell/cone/staggered/entropic_plume cost = 1 - route = PATH_RUST - depth = 10 + + /datum/heretic_knowledge/spell/entropic_plume/on_gain(mob/user) . = ..() @@ -212,7 +166,7 @@ and becoming immune to many effects and dangers \ You will be able to rust almost anything upon ascending." gain_text = "Champion of rust. Corruptor of steel. Fear the dark, for the RUSTBRINGER has come! \ The Blacksmith forges ahead! Rusted Hills, CALL MY NAME! WITNESS MY ASCENSION!" - route = PATH_RUST + ascension_achievement = /datum/award/achievement/misc/rust_ascension /// If TRUE, then immunities are currently active. var/immunities_active = FALSE diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm index 7f8b783caed..5ce9c89ab2a 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm @@ -15,7 +15,7 @@ required_atoms = list(/mob/living/carbon/human = 1) cost = 0 priority = MAX_KNOWLEDGE_PRIORITY // Should be at the top - route = PATH_START + is_starting_knowledge = TRUE research_tree_icon_path = 'icons/effects/eldritch.dmi' research_tree_icon_state = "eye_close" research_tree_icon_frame = 1 diff --git a/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm b/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm index 3ed3f110a80..6672c9e7da8 100644 --- a/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm +++ b/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm @@ -1,13 +1,20 @@ +/datum/heretic_knowledge_tree_column/ash_to_moon + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/ash + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/moon + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/medallion + tier2 = /datum/heretic_knowledge/curse/paralysis + tier3 = /datum/heretic_knowledge/summon/ashy + // Sidepaths for knowledge between Ash and Flesh. /datum/heretic_knowledge/medallion name = "Ashen Eyes" desc = "Allows you to transmute a pair of eyes, a candle, and a glass shard into an Eldritch Medallion. \ The Eldritch Medallion grants you thermal vision while worn, and also functions as a focus." gain_text = "Piercing eyes guided them through the mundane. Neither darkness nor terror could stop them." - next_knowledge = list( - /datum/heretic_knowledge/spell/ash_passage, - /datum/heretic_knowledge/spell/moon_smile, - ) + required_atoms = list( /obj/item/organ/internal/eyes = 1, /obj/item/shard = 1, @@ -15,10 +22,8 @@ ) result_atoms = list(/obj/item/clothing/neck/eldritch_amulet) cost = 1 - route = PATH_SIDE research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "eye_medalion" - depth = 4 /datum/heretic_knowledge/curse/paralysis name = "Curse of Paralysis" @@ -26,10 +31,7 @@ While cursed, the victim will be unable to walk. You can additionally supply an item that a victim has touched \ or is covered in the victim's blood to make the curse last longer." gain_text = "The flesh of humanity is weak. Make them bleed. Show them their fragility." - next_knowledge = list( - /datum/heretic_knowledge/mad_mask, - /datum/heretic_knowledge/moon_amulet, - ) + required_atoms = list( /obj/item/bodypart/leg/left = 1, /obj/item/bodypart/leg/right = 1, @@ -39,10 +41,10 @@ duration_modifier = 2 curse_color = "#f19a9a" cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "curse_paralysis" - depth = 8 + /datum/heretic_knowledge/curse/paralysis/curse(mob/living/carbon/human/chosen_mob, boosted = FALSE) if(chosen_mob.usable_legs <= 0) // What're you gonna do, curse someone who already can't walk? @@ -68,10 +70,7 @@ Ash Spirits have a short range jaunt and the ability to cause bleeding in foes at range. \ They also have the ability to create a ring of fire around themselves for a length of time." gain_text = "I combined my principle of hunger with my desire for destruction. The Marshal knew my name, and the Nightwatcher gazed on." - next_knowledge = list( - /datum/heretic_knowledge/spell/flame_birth, - /datum/heretic_knowledge/spell/moon_ringleader, - ) + required_atoms = list( /obj/effect/decal/cleanable/ash = 1, /obj/item/bodypart/head = 1, @@ -79,6 +78,6 @@ ) mob_to_summon = /mob/living/basic/heretic_summon/ash_spirit cost = 1 - route = PATH_SIDE + poll_ignore_define = POLL_IGNORE_ASH_SPIRIT - depth = 10 + diff --git a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm index 8a1fe6b5a87..05b414fe346 100644 --- a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm +++ b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm @@ -1,3 +1,13 @@ +/datum/heretic_knowledge_tree_column/blade_to_rust + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/blade + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/rust + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/armor + tier2 = list(/datum/heretic_knowledge/crucible, /datum/heretic_knowledge/rifle) + tier3 = /datum/heretic_knowledge/spell/rust_charge + // Sidepaths for knowledge between Rust and Blade. /datum/heretic_knowledge/armor name = "Armorer's Ritual" @@ -5,21 +15,18 @@ Eldritch Armor provides great protection while also acting as a focus when hooded." gain_text = "The Rusted Hills welcomed the Blacksmith in their generosity. And the Blacksmith \ returned their generosity in kind." - next_knowledge = list( - /datum/heretic_knowledge/rust_regen, - /datum/heretic_knowledge/blade_dance, - ) + required_atoms = list( /obj/structure/table = 1, /obj/item/clothing/mask/gas = 1, ) result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/eldritch) cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/clothing/suits/armor.dmi' research_tree_icon_state = "eldritch_armor" research_tree_icon_frame = 12 - depth = 4 + /datum/heretic_knowledge/crucible name = "Mawed Crucible" @@ -27,20 +34,17 @@ The Mawed Crucible can brew powerful potions for combat and utility, but must be fed bodyparts and organs between uses." gain_text = "This is pure agony. I wasn't able to summon the figure of the Aristocrat, \ but with the Priest's attention I stumbled upon a different recipe..." - next_knowledge = list( - /datum/heretic_knowledge/duel_stance, - /datum/heretic_knowledge/spell/area_conversion, - ) + required_atoms = list( /obj/structure/reagent_dispensers/watertank = 1, /obj/structure/table = 1, ) result_atoms = list(/obj/structure/destructible/eldritch_crucible) cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "crucible" - depth = 8 + /datum/heretic_knowledge/rifle name = "Lionhunter's Rifle" @@ -52,11 +56,7 @@ causing the shot to mark your victim with your grasp and teleport you directly to them." gain_text = "I met an old man in an antique shop who wielded a very unusual weapon. \ I could not purchase it at the time, but they showed me how they made it ages ago." - next_knowledge = list( - /datum/heretic_knowledge/duel_stance, - /datum/heretic_knowledge/spell/area_conversion, - /datum/heretic_knowledge/rifle_ammo, - ) + required_atoms = list( /obj/item/stack/sheet/mineral/wood = 1, /obj/item/stack/sheet/animalhide = 1, @@ -64,8 +64,8 @@ ) result_atoms = list(/obj/item/gun/ballistic/rifle/lionhunter) cost = 1 - route = PATH_SIDE - depth = 8 + + research_tree_icon_path = 'icons/obj/weapons/guns/ballistic.dmi' research_tree_icon_state = "goldrevolver" @@ -81,10 +81,10 @@ ) result_atoms = list(/obj/item/ammo_box/strilka310/lionhunter) cost = 0 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/weapons/guns/ammo.dmi' research_tree_icon_state = "310_strip" - depth = 8 + /// A list of calibers that the ritual will deny. Only ballistic calibers are allowed. var/static/list/caliber_blacklist = list( CALIBER_LASER, @@ -111,11 +111,8 @@ name = "Rust Charge" desc = "A charge that must be started on a rusted tile and will destroy any rusted objects you come into contact with, will deal high damage to others and rust around you during the charge." gain_text = "The hills sparkled now, as I neared them my mind began to wander. I quickly regained my resolve and pushed forward, this last leg would be the most treacherous." - next_knowledge = list( - /datum/heretic_knowledge/spell/furious_steel, - /datum/heretic_knowledge/spell/entropic_plume, - ) + spell_to_add = /datum/action/cooldown/mob_cooldown/charge/rust cost = 1 - route = PATH_SIDE - depth = 10 + + diff --git a/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm b/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm index 1a08236aee6..f4d9d80717b 100644 --- a/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm +++ b/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm @@ -1,3 +1,14 @@ +/datum/heretic_knowledge_tree_column/cosmic_to_ash + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/cosmic + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/ash + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/summon/fire_shark + tier2 = /datum/heretic_knowledge/spell/space_phase + tier3 = /datum/heretic_knowledge/eldritch_coin + + // Sidepaths for knowledge between Cosmos and Ash. /datum/heretic_knowledge/summon/fire_shark @@ -6,10 +17,7 @@ Fire Sharks are fast and strong in groups, but die quickly. They are also highly resistant against fire attacks. \ Fire Sharks inject phlogiston into its victims and spawn plasma once they die." gain_text = "The cradle of the nebula was cold, but not dead. Light and heat flits even through the deepest darkness, and is hunted by its own predators." - next_knowledge = list( - /datum/heretic_knowledge/spell/cosmic_runes, - /datum/heretic_knowledge/spell/ash_passage, - ) + required_atoms = list( /obj/effect/decal/cleanable/ash = 1, /obj/item/organ/internal/liver = 1, @@ -17,9 +25,9 @@ ) mob_to_summon = /mob/living/basic/heretic_summon/fire_shark cost = 1 - route = PATH_SIDE + poll_ignore_define = POLL_IGNORE_FIRE_SHARK - depth = 4 + research_tree_icon_dir = EAST /datum/heretic_knowledge/spell/space_phase @@ -27,14 +35,11 @@ desc = "Grants you Space Phase, a spell that allows you to move freely through space. \ You can only phase in and out when you are on a space or misc turf." gain_text = "You feel like your body can move through space as if you where dust." - next_knowledge = list( - /datum/heretic_knowledge/spell/star_blast, - /datum/heretic_knowledge/mad_mask, - ) + spell_to_add = /datum/action/cooldown/spell/jaunt/space_crawl cost = 1 - route = PATH_SIDE - depth = 8 + + research_tree_icon_frame = 6 /datum/heretic_knowledge/eldritch_coin @@ -44,17 +49,14 @@ when landing on tails. If you insert the coin into an airlock, it will be consumed \ to fry its electronics, opening the airlock permanently unless bolted. " gain_text = "The Mansus is a place of all sorts of sins. But greed held a special role." - next_knowledge = list( - /datum/heretic_knowledge/spell/cosmic_expansion, - /datum/heretic_knowledge/spell/flame_birth, - ) + required_atoms = list( /obj/item/stack/sheet/mineral/diamond = 1, /obj/item/stack/sheet/mineral/plasma = 1, ) result_atoms = list(/obj/item/coin/eldritch) cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/economy.dmi' research_tree_icon_state = "coin_heretic" - depth = 10 + diff --git a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm index d54646fe103..7891b50aabc 100644 --- a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm +++ b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm @@ -1,3 +1,13 @@ +/datum/heretic_knowledge_tree_column/flesh_to_void + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/flesh + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/void + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/void_cloak + tier2 = /datum/heretic_knowledge/spell/blood_siphon + tier3 = list(/datum/heretic_knowledge/spell/void_prison, /datum/heretic_knowledge/spell/cleave) + // Sidepaths for knowledge between Flesh and Void. /datum/heretic_knowledge/void_cloak @@ -7,10 +17,7 @@ and while the hood is up, the cloak is completely invisible. It also provide decent armor and \ has pockets which can hold one of your blades, various ritual components (such as organs), and small heretical trinkets." gain_text = "The Owl is the keeper of things that are not quite in practice, but in theory are. Many things are." - next_knowledge = list( - /datum/heretic_knowledge/limited_amount/flesh_ghoul, - /datum/heretic_knowledge/cold_snap, - ) + required_atoms = list( /obj/item/shard = 1, /obj/item/clothing/suit = 1, @@ -18,24 +25,18 @@ ) result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/void) cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/clothing/suits/armor.dmi' research_tree_icon_state = "void_cloak" - depth = 4 /datum/heretic_knowledge/spell/blood_siphon name = "Blood Siphon" desc = "Grants you Blood Siphon, a spell that drains a victim of blood and health, transferring it to you. \ Also has a chance to transfer wounds from you to the victim." gain_text = "\"No matter the man, we bleed all the same.\" That's what the Marshal told me." - next_knowledge = list( - /datum/heretic_knowledge/spell/void_phase, - /datum/heretic_knowledge/summon/raw_prophet, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/blood_siphon cost = 1 - route = PATH_SIDE - depth = 8 /datum/heretic_knowledge/spell/void_prison name = "Void Prison" @@ -45,14 +46,9 @@ I try to yell, grab hold of this fool and tell them to run. \ But the only welts made are on my own beating fist. \ My smiling face turns to regard me, reflecting back in glassy eyes the empty path I have been lead down." - next_knowledge = list( - /datum/heretic_knowledge/spell/void_phase, - /datum/heretic_knowledge/summon/raw_prophet, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/void_prison cost = 1 - route = PATH_SIDE - depth = 8 /datum/heretic_knowledge/spell/cleave name = "Blood Cleave" @@ -60,11 +56,8 @@ that causes heavy bleeding and blood loss to anyone afflicted." gain_text = "At first I didn't understand these instruments of war, but the Priest \ told me to use them regardless. Soon, he said, I would know them well." - next_knowledge = list( - /datum/heretic_knowledge/summon/stalker, - /datum/heretic_knowledge/spell/void_pull, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/cleave cost = 1 - route = PATH_SIDE - depth = 10 + + diff --git a/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm index 706b83abac7..aa85f31d006 100644 --- a/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm +++ b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm @@ -1,3 +1,19 @@ +/datum/heretic_knowledge_tree_column/lock_to_flesh + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/lock + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/flesh + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/dummy_lock_to_flesh + tier2 = /datum/heretic_knowledge/spell/opening_blast + tier3 = /datum/heretic_knowledge/spell/apetra_vulnera + +/datum/heretic_knowledge/dummy_lock_to_flesh + name = "Flesh and Lock ways" + desc = "Research this to gain access to the other path" + gain_text = "There are ways from feasting to wounding, the power of birth is close to the power of opening." + cost = 1 + // Sidepaths for knowledge between Knock and Flesh. /datum/heretic_knowledge/spell/opening_blast name = "Wave Of Desperation" @@ -5,14 +21,9 @@ It removes your restraints, repels and knocks down adjacent people, and applies the Mansus Grasp to everything nearby. \ However, you will fall unconscious a short time after casting this spell." gain_text = "My shackles undone in dark fury, their feeble bindings crumble before my power." - next_knowledge = list( - /datum/heretic_knowledge/summon/raw_prophet, - /datum/heretic_knowledge/spell/burglar_finesse, - ) + spell_to_add = /datum/action/cooldown/spell/aoe/wave_of_desperation cost = 1 - route = PATH_SIDE - depth = 8 /datum/heretic_knowledge/spell/apetra_vulnera name = "Apetra Vulnera" @@ -20,11 +31,8 @@ which causes heavy bleeding on all bodyparts of the victim that have more than 15 brute damage. \ Wounds a random limb if no limb is sufficiently damaged." gain_text = "Flesh opens, and blood spills. My master seeks sacrifice, and I shall appease." - next_knowledge = list( - /datum/heretic_knowledge/summon/stalker, - /datum/heretic_knowledge/spell/caretaker_refuge, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/apetra_vulnera cost = 1 - route = PATH_SIDE - depth = 10 + + diff --git a/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm b/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm index 1e265b97498..5a3a042e609 100644 --- a/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm +++ b/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm @@ -1,19 +1,32 @@ +/datum/heretic_knowledge_tree_column/moon_to_lock + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/moon + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/lock + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/spell/mind_gate + tier2 = list(/datum/heretic_knowledge/unfathomable_curio, /datum/heretic_knowledge/painting) + tier3 = /datum/heretic_knowledge/dummy_moon_to_lock + // Sidepaths for knowledge between Knock and Moon. +/datum/heretic_knowledge/dummy_moon_to_lock + name = "Lock and Moon ways" + desc = "Research this to gain access to the other path" + gain_text = "The powers of Madness are like a wound in one's soul, and every wound can be opened and closed." + cost = 1 + + + /datum/heretic_knowledge/spell/mind_gate name = "Mind Gate" desc = "Grants you Mind Gate, a spell which inflicts hallucinations, \ confusion, oxygen loss and brain damage to its target over 10 seconds.\ The caster takes 20 brain damage per use." gain_text = "My mind swings open like a gate, and its insight will let me perceive the truth." - next_knowledge = list( - /datum/heretic_knowledge/key_ring, - /datum/heretic_knowledge/spell/moon_smile, - ) + spell_to_add = /datum/action/cooldown/spell/pointed/mind_gate cost = 1 - route = PATH_SIDE - depth = 4 /datum/heretic_knowledge/unfathomable_curio name = "Unfathomable Curio" @@ -22,10 +35,7 @@ veil you, allowing you to take 5 hits without suffering damage, this veil will recharge very slowly \ outside of combat." gain_text = "The mansus holds many a curio, some are not meant for the mortal eye." - next_knowledge = list( - /datum/heretic_knowledge/spell/burglar_finesse, - /datum/heretic_knowledge/moon_amulet, - ) + required_atoms = list( /obj/item/organ/internal/lungs = 1, /obj/item/stack/rods = 3, @@ -33,10 +43,10 @@ ) result_atoms = list(/obj/item/storage/belt/unfathomable_curio) cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/clothing/belts.dmi' research_tree_icon_state = "unfathomable_curio" - depth = 8 + /datum/heretic_knowledge/painting name = "Unsealed Arts" @@ -49,17 +59,14 @@ Master of the Rusted Mountain: Requires a piece of Trash. Curses non-heretics to rust the floor they walk on." gain_text = "A wind of inspiration blows through me. Beyond the veil and past the gate great works exist, yet to be painted. \ They yearn for mortal eyes, so I shall give them an audience." - next_knowledge = list( - /datum/heretic_knowledge/spell/burglar_finesse, - /datum/heretic_knowledge/moon_amulet, - ) + required_atoms = list(/obj/item/canvas = 1) result_atoms = list(/obj/item/canvas) cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/obj/signs.dmi' research_tree_icon_state = "eldritch_painting_weeping" - depth = 8 + /datum/heretic_knowledge/painting/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) if(locate(/obj/item/organ/internal/eyes) in atoms) diff --git a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm index 0a4f7fbe86a..3818aeb7224 100644 --- a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm +++ b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm @@ -1,3 +1,14 @@ +/datum/heretic_knowledge_tree_column/rust_to_cosmic + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/rust + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/cosmic + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/essence + tier2 = list(/datum/heretic_knowledge/curse/corrosion, /datum/heretic_knowledge/entropy_pulse) + tier3 = /datum/heretic_knowledge/summon/rusty + + // Sidepaths for knowledge between Rust and Cosmos. /datum/heretic_knowledge/essence @@ -6,18 +17,15 @@ Eldritch water can be consumed for potent healing, or given to heathens for deadly poisoning." gain_text = "This is an old recipe. The Owl whispered it to me. \ Created by the Priest - the Liquid that both was and is not." - next_knowledge = list( - /datum/heretic_knowledge/rust_regen, - /datum/heretic_knowledge/spell/cosmic_runes, - ) + required_atoms = list( /obj/structure/reagent_dispensers/watertank = 1, /obj/item/shard = 1, ) result_atoms = list(/obj/item/reagent_containers/cup/beaker/eldritch) cost = 1 - route = PATH_SIDE - depth = 4 + + research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "eldritch_flask" @@ -30,11 +38,11 @@ /obj/item/trash = 1, ) cost = 0 - route = PATH_SIDE + research_tree_icon_path = 'icons/mob/actions/actions_ecult.dmi' research_tree_icon_state = "corrode" research_tree_icon_frame = 10 - depth = 4 + var/rusting_range = 8 /datum/heretic_knowledge/entropy_pulse/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc) @@ -53,10 +61,7 @@ While cursed, the victim will repeatedly vomit while their organs will take constant damage. You can additionally supply an item \ that a victim has touched or is covered in the victim's blood to make the curse last longer." gain_text = "The body of humanity is temporary. Their weaknesses cannot be stopped, like iron falling to rust. Show them all." - next_knowledge = list( - /datum/heretic_knowledge/spell/area_conversion, - /datum/heretic_knowledge/spell/star_blast, - ) + required_atoms = list( /obj/item/wirecutters = 1, /obj/effect/decal/cleanable/vomit = 1, @@ -66,10 +71,10 @@ duration_modifier = 4 curse_color = "#c1ffc9" cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "curse_corrosion" - depth = 8 + /datum/heretic_knowledge/curse/corrosion/curse(mob/living/carbon/human/chosen_mob, boosted = FALSE) to_chat(chosen_mob, span_danger("You feel very ill...")) @@ -89,10 +94,7 @@ desc = "Allows you to transmute a pool of vomit, some cable coil, and 10 sheets of iron into a Rust Walker. \ Rust Walkers excel at spreading rust and are moderately strong in combat." gain_text = "I combined my knowledge of creation with my desire for corruption. The Marshal knew my name, and the Rusted Hills echoed out." - next_knowledge = list( - /datum/heretic_knowledge/spell/area_conversion, - /datum/heretic_knowledge/spell/star_blast, - ) + required_atoms = list( /obj/effect/decal/cleanable/vomit = 1, /obj/item/stack/sheet/iron = 10, @@ -100,7 +102,7 @@ ) mob_to_summon = /mob/living/basic/heretic_summon/rust_walker cost = 1 - route = PATH_SIDE + poll_ignore_define = POLL_IGNORE_RUST_SPIRIT - depth = 8 + diff --git a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm index 56945262e3c..110cbbeb28e 100644 --- a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm +++ b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm @@ -1,5 +1,17 @@ // Sidepaths for knowledge between Void and Blade. +/datum/heretic_knowledge_tree_column/void_to_blade + neighbour_type_left = /datum/heretic_knowledge_tree_column/main/void + neighbour_type_right = /datum/heretic_knowledge_tree_column/main/blade + + route = PATH_SIDE + + tier1 = /datum/heretic_knowledge/limited_amount/risen_corpse + tier2 = /datum/heretic_knowledge/rune_carver + tier3 = /datum/heretic_knowledge/summon/maid_in_mirror + + + /// The max health given to Shattered Risen #define RISEN_MAX_HEALTH 125 @@ -12,20 +24,17 @@ gain_text = "I witnessed a cold, rending force drag this corpse back to near-life. \ When it moves, it crunches like broken glass. Its hands are no longer recognizable as human - \ each clenched fist contains a brutal nest of sharp bone-shards instead." - next_knowledge = list( - /datum/heretic_knowledge/cold_snap, - /datum/heretic_knowledge/blade_dance, - ) + required_atoms = list( /obj/item/clothing/suit = 1, /obj/item/clothing/gloves/latex = 1, ) limit = 1 cost = 1 - route = PATH_SIDE + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "ghoul_shattered" - depth = 4 + /datum/heretic_knowledge/limited_amount/risen_corpse/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) . = ..() @@ -130,10 +139,7 @@ Also makes for a handy throwing weapon." gain_text = "Etched, carved... eternal. There is power hidden in everything. I can unveil it! \ I can carve the monolith to reveal the chains!" - next_knowledge = list( - /datum/heretic_knowledge/spell/void_phase, - /datum/heretic_knowledge/duel_stance, - ) + required_atoms = list( /obj/item/knife = 1, /obj/item/shard = 1, @@ -141,8 +147,8 @@ ) result_atoms = list(/obj/item/melee/rune_carver) cost = 1 - route = PATH_SIDE - depth = 8 + + research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "rune_carver" @@ -154,10 +160,7 @@ However, they are weak to mortal gaze and take damage by being examined." gain_text = "Within each reflection, lies a gateway into an unimaginable world of colors never seen and \ people never met. The ascent is glass, and the walls are knives. Each step is blood, if you do not have a guide." - next_knowledge = list( - /datum/heretic_knowledge/spell/void_pull, - /datum/heretic_knowledge/spell/furious_steel, - ) + required_atoms = list( /obj/item/stack/sheet/mineral/titanium = 5, /obj/item/clothing/suit/armor = 1, @@ -165,7 +168,7 @@ /obj/item/organ/internal/lungs = 1, ) cost = 1 - route = PATH_SIDE + mob_to_summon = /mob/living/basic/heretic_summon/maid_in_the_mirror poll_ignore_define = POLL_IGNORE_MAID_IN_MIRROR - depth = 10 + diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm index 2b5186bb550..8c61f13f495 100644 --- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm @@ -1,6 +1,6 @@ // Heretic starting knowledge. -/// Global list of all heretic knowledge that have route = PATH_START. List of PATHS. +/// Global list of all heretic knowledge that have is_starting_knowledge = TRUE. List of PATHS. GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) /** @@ -10,7 +10,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) /proc/initialize_starting_knowledge() . = list() for(var/datum/heretic_knowledge/knowledge as anything in subtypesof(/datum/heretic_knowledge)) - if(initial(knowledge.route) == PATH_START) + if(initial(knowledge.is_starting_knowledge) == TRUE) . += knowledge /* @@ -23,11 +23,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) disabling spell that can be cast regardless of having a focus." spell_to_add = /datum/action/cooldown/spell/touch/mansus_grasp cost = 0 - route = PATH_START - -/datum/heretic_knowledge/spell/basic/New() - . = ..() - next_knowledge = subtypesof(/datum/heretic_knowledge/limited_amount/starting) + is_starting_knowledge = TRUE /** * The Living Heart heretic knowledge. @@ -47,7 +43,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) ) cost = 0 priority = MAX_KNOWLEDGE_PRIORITY - 1 // Knowing how to remake your heart is important - route = PATH_START + is_starting_knowledge = TRUE research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' research_tree_icon_state = "living_heart" research_tree_icon_frame = 1 @@ -207,7 +203,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) result_atoms = list(/obj/item/clothing/neck/heretic_focus) cost = 0 priority = MAX_KNOWLEDGE_PRIORITY - 2 // Not as important as making a heart or sacrificing, but important enough. - route = PATH_START + is_starting_knowledge = TRUE research_tree_icon_path = 'icons/obj/clothing/neck.dmi' research_tree_icon_state = "eldritch_necklace" @@ -217,7 +213,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) for three minutes, assisting you in keeping secrecy. Requires a focus to cast." spell_to_add = /datum/action/cooldown/spell/shadow_cloak cost = 0 - route = PATH_START + is_starting_knowledge = TRUE /** * Codex Cicatrixi is available at the start: @@ -241,7 +237,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) banned_atom_types = list(/obj/item/pen) result_atoms = list(/obj/item/codex_cicatrix) cost = 1 - route = PATH_START + is_starting_knowledge = TRUE priority = MAX_KNOWLEDGE_PRIORITY - 3 // Least priority out of the starting knowledges, as it's an optional boon. var/static/list/non_mob_bindings = typecacheof(list(/obj/item/stack/sheet/leather, /obj/item/stack/sheet/animalhide)) research_tree_icon_path = 'icons/obj/antags/eldritch.dmi' @@ -306,7 +302,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) name = "Feast of Owls" desc = "Allows you to undergo a ritual that gives you 5 knowledge points but locks you out of ascension. This can only be done once and cannot be reverted." gain_text = "Under the soft glow of unreason there is a beast that stalks the night. I shall bring it forth and let it enter my presence. It will feast upon my amibitions and leave knowledge in its wake." - route = PATH_START + is_starting_knowledge = TRUE required_atoms = list() research_tree_icon_path = 'icons/mob/actions/actions_animal.dmi' research_tree_icon_state = "god_transmit" diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm index 1bca358c3aa..071284ac193 100644 --- a/code/modules/antagonists/heretic/knowledge/void_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm @@ -1,32 +1,22 @@ -/** - * # The path of VOID. - * - * Goes as follows: - * - * Glimmer of Winter - * Grasp of Void - * Aristocrat's Way - * > Sidepaths: - * Void Cloak - * Shattered Ritual - * - * Mark of Void - * Ritual of Knowledge - * Void Conduit - * Void Phase - * > Sidepaths: - * Void Stasis - * Carving Knife - * Blood Siphon - * - * Seeking blade - * Void Pull - * > Sidepaths: - * Cleave - * Maid in the Mirror - * - * Waltz at the End of Time - */ + +/datum/heretic_knowledge_tree_column/main/void + neighbour_type_left = /datum/heretic_knowledge_tree_column/flesh_to_void + neighbour_type_right = /datum/heretic_knowledge_tree_column/void_to_blade + + route = PATH_VOID + ui_bgr = "node_void" + + start = /datum/heretic_knowledge/limited_amount/starting/base_void + grasp = /datum/heretic_knowledge/void_grasp + tier1 = /datum/heretic_knowledge/cold_snap + mark = /datum/heretic_knowledge/mark/void_mark + ritual_of_knowledge = /datum/heretic_knowledge/knowledge_ritual/void + unique_ability = /datum/heretic_knowledge/spell/void_conduit + tier2 = /datum/heretic_knowledge/spell/void_phase + blade = /datum/heretic_knowledge/blade_upgrade/void + tier3 = /datum/heretic_knowledge/spell/void_pull + ascension = /datum/heretic_knowledge/ultimate/void_final + /datum/heretic_knowledge/limited_amount/starting/base_void name = "Glimmer of Winter" desc = "Opens up the Path of Void to you. \ @@ -34,10 +24,8 @@ You can only create five at a time." //NOVA EDIT two to five gain_text = "I feel a shimmer in the air, the air around me gets colder. \ I start to realize the emptiness of existence. Something's watching me." - next_knowledge = list(/datum/heretic_knowledge/void_grasp) required_atoms = list(/obj/item/knife = 1) result_atoms = list(/obj/item/melee/sickly_blade/void) - route = PATH_VOID research_tree_icon_path = 'icons/obj/weapons/khopesh.dmi' research_tree_icon_state = "void_blade" @@ -58,10 +46,7 @@ desc = "Your Mansus Grasp will temporarily mute and chill the victim." gain_text = "I saw the cold watcher who observes me. The chill mounts within me. \ They are quiet. This isn't the end of the mystery." - next_knowledge = list(/datum/heretic_knowledge/cold_snap) cost = 1 - route = PATH_VOID - depth = 3 research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "grasp_void" @@ -87,16 +72,10 @@ You can still take damage due to a lack of pressure." gain_text = "I found a thread of cold breath. It lead me to a strange shrine, all made of crystals. \ Translucent and white, a depiction of a nobleman stood before me." - next_knowledge = list( - /datum/heretic_knowledge/mark/void_mark, - /datum/heretic_knowledge/void_cloak, - /datum/heretic_knowledge/limited_amount/risen_corpse, - ) cost = 1 - route = PATH_VOID research_tree_icon_path = 'icons/effects/effects.dmi' research_tree_icon_state = "the_freezer" - depth = 4 + /// Traits we apply to become immune to the environment var/static/list/gain_traits = list(TRAIT_NO_SLIP_ICE, TRAIT_NO_SLIP_SLIDE) @@ -127,13 +106,9 @@ When triggered, further silences the victim and swiftly lowers the temperature of their body and the air around them." gain_text = "A gust of wind? A shimmer in the air? The presence is overwhelming, \ my senses began to betray me. My mind is my own enemy." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/void) - route = PATH_VOID mark_type = /datum/status_effect/eldritch/void /datum/heretic_knowledge/knowledge_ritual/void - next_knowledge = list(/datum/heretic_knowledge/spell/void_conduit) - route = PATH_VOID /datum/heretic_knowledge/spell/void_conduit name = "Void Conduit" @@ -141,11 +116,8 @@ gain_text = "The hum in the still, cold air turns to a cacophonous rattle. \ Over the noise, there is no distinction to the clattering of window panes and the yawning knowledge that ricochets through my skull. \ The doors won't close. I can't keep the cold out now." - next_knowledge = list(/datum/heretic_knowledge/spell/void_phase) spell_to_add = /datum/action/cooldown/spell/conjure/void_conduit cost = 1 - route = PATH_VOID - depth = 7 /datum/heretic_knowledge/spell/void_phase name = "Void Phase" @@ -153,25 +125,16 @@ Additionally causes damage to heathens around your original and target destination." gain_text = "The entity calls themself the Aristocrat. They effortlessly walk through air like \ nothing - leaving a harsh, cold breeze in their wake. They disappear, and I am left in the blizzard." - next_knowledge = list( - /datum/heretic_knowledge/blade_upgrade/void, - /datum/heretic_knowledge/reroll_targets, - /datum/heretic_knowledge/spell/blood_siphon, - /datum/heretic_knowledge/spell/void_prison, - /datum/heretic_knowledge/rune_carver, - ) spell_to_add = /datum/action/cooldown/spell/pointed/void_phase cost = 1 - route = PATH_VOID - depth = 8 research_tree_icon_frame = 7 /datum/heretic_knowledge/blade_upgrade/void name = "Seeking Blade" desc = "Your blade now freezes enemies. Additionally, you can now attack distant marked targets with your Void Blade, teleporting directly next to them." gain_text = "Fleeting memories, fleeting feet. I mark my way with frozen blood upon the snow. Covered and forgotten." - next_knowledge = list(/datum/heretic_knowledge/spell/void_pull) - route = PATH_VOID + + research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_void" @@ -198,15 +161,11 @@ desc = "Grants you Void Pull, a spell that pulls all nearby heathens towards you, stunning them briefly." gain_text = "All is fleeting, but what else stays? I'm close to ending what was started. \ The Aristocrat reveals themselves to me again. They tell me I am late. Their pull is immense, I cannot turn back." - next_knowledge = list( - /datum/heretic_knowledge/ultimate/void_final, - /datum/heretic_knowledge/spell/cleave, - /datum/heretic_knowledge/summon/maid_in_mirror, - ) + spell_to_add = /datum/action/cooldown/spell/aoe/void_pull cost = 1 - route = PATH_VOID - depth = 10 + + research_tree_icon_frame = 6 /datum/heretic_knowledge/ultimate/void_final @@ -219,7 +178,7 @@ gain_text = "The world falls into darkness. I stand in an empty plane, small flakes of ice fall from the sky. \ The Aristocrat stands before me, beckoning. We will play a waltz to the whispers of dying reality, \ as the world is destroyed before our eyes. The void will return all to nothing, WITNESS MY ASCENSION!" - route = PATH_VOID + ascension_achievement = /datum/award/achievement/misc/void_ascension ///soundloop for the void theme var/datum/looping_sound/void_loop/sound_loop diff --git a/code/modules/antagonists/heretic/magic/furious_steel.dm b/code/modules/antagonists/heretic/magic/furious_steel.dm index d61ce5d1a39..9414ca9d711 100644 --- a/code/modules/antagonists/heretic/magic/furious_steel.dm +++ b/code/modules/antagonists/heretic/magic/furious_steel.dm @@ -19,7 +19,7 @@ active_msg = "You summon forth three blades of furious silver." deactive_msg = "You conceal the blades of furious silver." cast_range = 20 - projectile_type = /obj/projectile/floating_blade + projectile_type = /obj/effect/floating_blade projectile_amount = 3 /// A ref to the status effect surrounding our heretic on activation. diff --git a/code/modules/antagonists/heretic/magic/shadow_cloak.dm b/code/modules/antagonists/heretic/magic/shadow_cloak.dm index ed26c94aa20..d69af522540 100644 --- a/code/modules/antagonists/heretic/magic/shadow_cloak.dm +++ b/code/modules/antagonists/heretic/magic/shadow_cloak.dm @@ -123,7 +123,7 @@ /datum/status_effect/shadow_cloak id = "shadow_cloak" alert_type = null - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK /// How much damage we've been hit with var/damage_sustained = 0 /// How much damage we can be hit with before it starts rolling reveal chances diff --git a/code/modules/antagonists/heretic/magic/space_crawl.dm b/code/modules/antagonists/heretic/magic/space_crawl.dm index cce9f46085b..74b02c59c10 100644 --- a/code/modules/antagonists/heretic/magic/space_crawl.dm +++ b/code/modules/antagonists/heretic/magic/space_crawl.dm @@ -7,7 +7,7 @@ */ /datum/action/cooldown/spell/jaunt/space_crawl name = "Space Phase" - desc = "Allows you to phase in and out of existance while in space or misc tiles." + desc = "Allows you to phase in and out of existence while in space or misc tiles." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm index d9cd5a05eab..e8e824cc718 100644 --- a/code/modules/antagonists/heretic/magic/star_touch.dm +++ b/code/modules/antagonists/heretic/magic/star_touch.dm @@ -201,35 +201,6 @@ if(current_target) on_beam_hit(current_target) -/// Checks if the beam is going through an invalid turf -/datum/status_effect/cosmic_beam/proc/los_check(atom/movable/user, mob/target) - var/turf/user_turf = user.loc - if(!istype(user_turf)) - return FALSE - var/obj/dummy = new(user_turf) - dummy.pass_flags |= PASSTABLE|PASSGLASS|PASSGRILLE //Grille/Glass so it can be used through common windows - var/turf/previous_step = user_turf - var/first_step = TRUE - for(var/turf/next_step as anything in (get_line(user_turf, target) - user_turf)) - if(first_step) - for(var/obj/blocker in user_turf) - if(!blocker.density || !(blocker.flags_1 & ON_BORDER_1)) - continue - if(blocker.CanPass(dummy, get_dir(user_turf, next_step))) - continue - return FALSE // Could not leave the first turf. - first_step = FALSE - if(next_step.density) - qdel(dummy) - return FALSE - for(var/atom/movable/movable as anything in next_step) - if(!movable.CanPass(dummy, get_dir(next_step, previous_step))) - qdel(dummy) - return FALSE - previous_step = next_step - qdel(dummy) - return TRUE - /// What to add when the beam connects to a target /datum/status_effect/cosmic_beam/proc/on_beam_hit(mob/living/target) if(!istype(target, /mob/living/basic/heretic_summon/star_gazer)) diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm index d82d145b3ef..3004bdd9ee0 100644 --- a/code/modules/antagonists/heretic/status_effects/buffs.dm +++ b/code/modules/antagonists/heretic/status_effects/buffs.dm @@ -138,7 +138,7 @@ id = "Silver Knives" alert_type = null status_type = STATUS_EFFECT_MULTIPLE - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK /// The number of blades we summon up to. var/max_num_blades = 4 /// The radius of the blade's orbit. @@ -148,13 +148,13 @@ /// If TRUE, we self-delete our status effect after all the blades are deleted. var/delete_on_blades_gone = TRUE /// What blade type to create - var/blade_type = /obj/effect/floating_blade + var/obj/effect/floating_blade/blade_type /// A list of blade effects orbiting / protecting our owner var/list/obj/effect/floating_blade/blades = list() /datum/status_effect/protective_blades/on_creation( mob/living/new_owner, - new_duration = -1, + new_duration = STATUS_EFFECT_PERMANENT, max_num_blades = 4, blade_orbit_radius = 20, time_between_initial_blades = 0.25 SECONDS, @@ -190,8 +190,7 @@ if(QDELETED(src) || QDELETED(owner)) return - var/obj/effect/floating_blade/blade - blade = new blade_type(get_turf(owner)) + var/obj/effect/floating_blade/blade = new blade_type(get_turf(owner)) blades += blade blade.orbit(owner, blade_orbit_radius) RegisterSignal(blade, COMSIG_QDELETING, PROC_REF(remove_blade)) @@ -257,12 +256,12 @@ /datum/status_effect/protective_blades/recharging/on_creation( mob/living/new_owner, - new_duration = -1, + new_duration = STATUS_EFFECT_PERMANENT, max_num_blades = 4, blade_orbit_radius = 20, time_between_initial_blades = 0.25 SECONDS, - blade_recharge_time = 1 MINUTES, blade_type = /obj/effect/floating_blade, + blade_recharge_time = 1 MINUTES, ) src.blade_recharge_time = blade_recharge_time @@ -279,7 +278,7 @@ /datum/status_effect/caretaker_refuge id = "Caretaker’s Last Refuge" status_type = STATUS_EFFECT_REFRESH - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null var/static/list/caretaking_traits = list(TRAIT_GODMODE, TRAIT_HANDS_BLOCKED, TRAIT_IGNORESLOWDOWN, TRAIT_SECLUDED_LOCATION) diff --git a/code/modules/antagonists/heretic/status_effects/debuffs.dm b/code/modules/antagonists/heretic/status_effects/debuffs.dm index 8b1751bccde..7bb2ebbd0e7 100644 --- a/code/modules/antagonists/heretic/status_effects/debuffs.dm +++ b/code/modules/antagonists/heretic/status_effects/debuffs.dm @@ -161,7 +161,7 @@ alert_type = /atom/movable/screen/alert/status_effect/heretic_lastresort duration = 12 SECONDS status_type = STATUS_EFFECT_REPLACE - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK /atom/movable/screen/alert/status_effect/heretic_lastresort name = "Last Resort" @@ -183,7 +183,7 @@ /datum/status_effect/moon_converted id = "moon converted" alert_type = /atom/movable/screen/alert/status_effect/moon_converted - duration = -1 + duration = STATUS_EFFECT_PERMANENT status_type = STATUS_EFFECT_REPLACE ///used to track damage var/damage_sustained = 0 diff --git a/code/modules/antagonists/heretic/status_effects/ghoul.dm b/code/modules/antagonists/heretic/status_effects/ghoul.dm index b212f1a024a..34778d380fb 100644 --- a/code/modules/antagonists/heretic/status_effects/ghoul.dm +++ b/code/modules/antagonists/heretic/status_effects/ghoul.dm @@ -1,7 +1,7 @@ /datum/status_effect/ghoul id = "ghoul" status_type = STATUS_EFFECT_UNIQUE - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = /atom/movable/screen/alert/status_effect/ghoul /// The new max health value set for the ghoul, if supplied var/new_max_health diff --git a/code/modules/antagonists/heretic/status_effects/void_chill.dm b/code/modules/antagonists/heretic/status_effects/void_chill.dm index ed4bf1f3cb5..c286fcd2982 100644 --- a/code/modules/antagonists/heretic/status_effects/void_chill.dm +++ b/code/modules/antagonists/heretic/status_effects/void_chill.dm @@ -84,7 +84,7 @@ /datum/status_effect/void_chill/lasting id = "lasting_void_chill" - duration = -1 + duration = STATUS_EFFECT_PERMANENT /datum/movespeed_modifier/void_chill variable = TRUE diff --git a/code/modules/antagonists/heretic/structures/lock_final.dm b/code/modules/antagonists/heretic/structures/lock_final.dm index 295ecbb3a2b..cd187641f73 100644 --- a/code/modules/antagonists/heretic/structures/lock_final.dm +++ b/code/modules/antagonists/heretic/structures/lock_final.dm @@ -1,7 +1,7 @@ /obj/structure/lock_tear name = "???" desc = "It stares back. There's no reason to remain. Run." - max_integrity = INFINITE + max_integrity = INFINITY resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF icon = 'icons/obj/anomaly.dmi' icon_state = "bhole3" diff --git a/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm b/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm index 7934e757077..6b7f733265c 100644 --- a/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm +++ b/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm @@ -5,7 +5,7 @@ /// Regenerate in space /datum/status_effect/space_regeneration id = "space_regeneration" - duration = INFINITE + duration = STATUS_EFFECT_PERMANENT alert_type = null // How much do we heal per tick? var/healing = 1.5 @@ -20,7 +20,7 @@ /datum/status_effect/planet_allergy id = "planet_allergy" - duration = INFINITE + duration = STATUS_EFFECT_PERMANENT alert_type = /atom/movable/screen/alert/status_effect/veryhighgravity /datum/status_effect/planet_allergy/tick() diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm index 18e2dae715c..28432b1ada8 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm @@ -31,10 +31,10 @@ /// Whether the spell requires wizard garb or not var/requires_wizard_garb = FALSE /// Used so you can't have specific spells together - var/list/no_coexistance_typecache + var/list/no_coexistence_typecache /datum/spellbook_entry/New() - no_coexistance_typecache = typecacheof(no_coexistance_typecache) + no_coexistence_typecache = typecacheof(no_coexistence_typecache) if(ispath(spell_type)) if(isnull(limit)) @@ -68,13 +68,13 @@ if(!isnull(limit) && times >= limit) return FALSE for(var/spell in user.actions) - if(is_type_in_typecache(spell, no_coexistance_typecache)) + if(is_type_in_typecache(spell, no_coexistence_typecache)) return FALSE var/datum/antagonist/wizard/wizard_datum = user.mind.has_antag_datum(/datum/antagonist/wizard) if(!wizard_datum) return TRUE for(var/perks in wizard_datum.perks) - if(is_type_in_typecache(perks, no_coexistance_typecache)) + if(is_type_in_typecache(perks, no_coexistence_typecache)) return FALSE if(is_type_in_list(src, wizard_datum.perks)) to_chat(user, span_warning("This perk already learned!")) diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm index e7c204a39e2..585385e9d2d 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm @@ -55,7 +55,7 @@ it will become easier for others to find your item of power." spell_type = /datum/action/cooldown/spell/lichdom category = SPELLBOOK_CATEGORY_DEFENSIVE - no_coexistance_typecache = list(/datum/action/cooldown/spell/splattercasting, /datum/spellbook_entry/perks/wormborn) + no_coexistence_typecache = list(/datum/action/cooldown/spell/splattercasting, /datum/spellbook_entry/perks/wormborn) /datum/spellbook_entry/chuunibyou name = "Chuuni Invocations" diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm index 6b8272ed5b7..d65e14578ec 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm @@ -77,7 +77,7 @@ spell_type = /datum/action/cooldown/spell/conjure_item/infinite_guns/gun category = SPELLBOOK_CATEGORY_OFFENSIVE cost = 3 - no_coexistance_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/arcane_barrage) + no_coexistence_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/arcane_barrage) /datum/spellbook_entry/arcane_barrage name = "Arcane Barrage" @@ -85,7 +85,7 @@ spell_type = /datum/action/cooldown/spell/conjure_item/infinite_guns/arcane_barrage category = SPELLBOOK_CATEGORY_OFFENSIVE cost = 3 - no_coexistance_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/gun) + no_coexistence_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/gun) /datum/spellbook_entry/barnyard name = "Barnyard Curse" @@ -99,7 +99,7 @@ draining from you over time. You can replenish it from your victims, specifically their necks." spell_type = /datum/action/cooldown/spell/splattercasting category = SPELLBOOK_CATEGORY_OFFENSIVE - no_coexistance_typecache = list(/datum/action/cooldown/spell/lichdom) + no_coexistence_typecache = list(/datum/action/cooldown/spell/lichdom) /datum/spellbook_entry/sanguine_strike name = "Exsanguinating Strike" diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm index 07c152d113d..6c4947639f6 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm @@ -60,7 +60,7 @@ desc = "Your soul is infested with mana worms. When you die, you will be reborn as a large worm. \ When the worm dies, it has no such luck. Parasitic infection prevents you from binding your soul to objects." hud_icon = "wormborn" - no_coexistance_typecache = list(/datum/action/cooldown/spell/lichdom) + no_coexistence_typecache = list(/datum/action/cooldown/spell/lichdom) /datum/spellbook_entry/perks/wormborn/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy) . = ..() diff --git a/code/modules/antagonists/wizard/equipment/teleport_rod.dm b/code/modules/antagonists/wizard/equipment/teleport_rod.dm index e0a5ce31145..47187dcc4f7 100644 --- a/code/modules/antagonists/wizard/equipment/teleport_rod.dm +++ b/code/modules/antagonists/wizard/equipment/teleport_rod.dm @@ -174,7 +174,7 @@ particle_effect.alpha = 200 var/original_duration = initial(duration) - if(original_duration == -1) + if(original_duration == STATUS_EFFECT_PERMANENT) return animate(particle_effect, alpha = 50, time = original_duration) @@ -185,7 +185,7 @@ /datum/status_effect/teleport_flux/perma id = "perma_teleport_flux" status_type = STATUS_EFFECT_REPLACE - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = /atom/movable/screen/alert/status_effect/teleport_flux/perma remove_on_fullheal = FALSE diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm index 3f9c106a40b..d3719be5cb9 100644 --- a/code/modules/cargo/bounties/assistant.dm +++ b/code/modules/cargo/bounties/assistant.dm @@ -187,7 +187,7 @@ name = "Crayons" description = "Dr. Jones's kid ate all of our crayons again. Please send us yours." reward = CARGO_CRATE_VALUE * 4 - required_count = 24 + required_count = 8 wanted_types = list(/obj/item/toy/crayon = TRUE) */ // NOVA EDIT REMOVAL END diff --git a/code/modules/cargo/markets/market_items/misc.dm b/code/modules/cargo/markets/market_items/misc.dm index b0ea8948580..c53076f737c 100644 --- a/code/modules/cargo/markets/market_items/misc.dm +++ b/code/modules/cargo/markets/market_items/misc.dm @@ -134,12 +134,3 @@ stock_min = 3 stock_max = 8 availability_prob = 90 - -/datum/market_item/misc/giant_wrench_parts - name = "Big Slappy parts" - desc = "Cheap illegal Big Slappy parts. The fastest and statistically most dangerous wrench." - item = /obj/item/weaponcrafting/giant_wrench - price_min = CARGO_CRATE_VALUE * 2 - price_max = CARGO_CRATE_VALUE * 5 - stock_max = 1 - availability_prob = 25 diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm index 12241450ba5..94aa533c26e 100644 --- a/code/modules/cargo/markets/market_items/weapons.dm +++ b/code/modules/cargo/markets/market_items/weapons.dm @@ -92,3 +92,12 @@ price_max = CARGO_CRATE_VALUE * 50 stock_max = 1 availability_prob = 15 + +/datum/market_item/weapon/giant_wrench_parts + name = "Big Slappy parts" + desc = "Cheap illegal Big Slappy parts. The fastest and statistically most dangerous wrench." + item = /obj/item/weaponcrafting/giant_wrench + price_min = CARGO_CRATE_VALUE * 2 + price_max = CARGO_CRATE_VALUE * 5 + stock_max = 1 + availability_prob = 25 diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index 991f270ac6d..532e06625f7 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -449,7 +449,7 @@ if(ismob(to_insert)) if(!reverse_option_list["Mobs"]) return FALSE - if(!isliving(to_insert)) //let's not put ghosts or camera mobs inside + if(!isliving(to_insert)) //let's not put ghosts or eye mobs inside return FALSE var/mob/living/mob_to_insert = to_insert if(mob_to_insert.anchored || mob_to_insert.incorporeal_move) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index c8e9e9a64c2..fe559b2b71b 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -269,3 +269,7 @@ ///Which ambient sound this client is currently being provided. var/current_ambient_sound + + /// Does this client's mob need to rebuild its plane masters after login? + /// This is currently only used so a client can switch between 515 and 516 without breaking their rendering. + var/rebuild_plane_masters = FALSE diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 3b449372b17..08e98bb2af3 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -333,10 +333,20 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(GLOB.player_details[ckey]) reconnecting = TRUE player_details = GLOB.player_details[ckey] - player_details.byond_version = full_version + var/old_version = player_details.byond_version + player_details.byond_version = byond_version + player_details.byond_build = byond_build + +#if MIN_COMPILER_VERSION > 516 + #warn Fully change default relay_loc to "1,1", rather than changing it based on client version +#endif + if(old_version != byond_version) + rebuild_plane_masters = TRUE + else player_details = new(ckey) - player_details.byond_version = full_version + player_details.byond_version = byond_version + player_details.byond_build = byond_build GLOB.player_details[ckey] = player_details diff --git a/code/modules/client/player_details.dm b/code/modules/client/player_details.dm index 3a880dcdbb5..d0982a0c312 100644 --- a/code/modules/client/player_details.dm +++ b/code/modules/client/player_details.dm @@ -1,6 +1,6 @@ ///assoc list of ckey -> /datum/player_details -GLOBAL_LIST_EMPTY(player_details) +GLOBAL_LIST_EMPTY_TYPED(player_details, /datum/player_details) /// Tracks information about a client between log in and log outs /datum/player_details @@ -18,8 +18,10 @@ GLOBAL_LIST_EMPTY(player_details) /// Lazylist of preference slots this client has joined the round under /// Numbers are stored as strings var/list/joined_as_slots - /// Version of byond this client is using - var/byond_version = "Unknown" + /// Major version of BYOND this client is using. + var/byond_version + /// Build number of BYOND this client is using. + var/byond_build /// Tracks achievements they have earned var/datum/achievement_data/achievements /// World.time this player last died @@ -35,6 +37,12 @@ GLOBAL_LIST_EMPTY(player_details) previous_names += html_encode("[previous_name] ([played_names[previous_name]])") return previous_names.Join("; ") +/// Returns the full version string (i.e 515.1642) of the BYOND version and build. +/datum/player_details/proc/full_byond_version() + if(!byond_version) + return "Unknown" + return "[byond_version].[byond_build || "xxx"]" + /// Adds the new names to the player's played_names list on their /datum/player_details for use of admins. /// `ckey` should be their ckey, and `data` should be an associative list with the keys being the names they played under and the values being the unique mob ID tied to that name. /proc/log_played_names(ckey, data) diff --git a/code/modules/client/preferences/darkened_flash.dm b/code/modules/client/preferences/accessibility.dm similarity index 51% rename from code/modules/client/preferences/darkened_flash.dm rename to code/modules/client/preferences/accessibility.dm index ef89467bf35..26f0a790985 100644 --- a/code/modules/client/preferences/darkened_flash.dm +++ b/code/modules/client/preferences/accessibility.dm @@ -4,3 +4,10 @@ default_value = FALSE savefile_key = "darkened_flash" savefile_identifier = PREFERENCE_PLAYER + +/// When toggled, will darken the screen on screen shake +/datum/preference/toggle/screen_shake_darken + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + default_value = FALSE + savefile_key = "screen_shake_darken" + savefile_identifier = PREFERENCE_PLAYER diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 418f8358f4d..7d990e1ace5 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -12,7 +12,6 @@ siemens_coefficient = 0.5 body_parts_covered = HANDS slot_flags = ITEM_SLOT_GLOVES - equip_sound = 'sound/items/equip/glove_equip.ogg' drop_sound = 'sound/items/handling/glove_drop.ogg' pickup_sound = 'sound/items/handling/glove_pick_up.ogg' attack_verb_continuous = list("challenges") diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm index ab6e03ae493..3c8edb4de73 100644 --- a/code/modules/clothing/gloves/boxing.dm +++ b/code/modules/clothing/gloves/boxing.dm @@ -6,6 +6,7 @@ equip_delay_other = 60 species_exception = list(/datum/species/golem) // now you too can be a golem boxing champion clothing_traits = list(TRAIT_CHUNKYFINGERS) + equip_sound = 'sound/items/equip/glove_equip.ogg' /// Determines the version of boxing (or any martial art for that matter) that the boxing gloves gives var/style_to_give = /datum/martial_art/boxing diff --git a/code/modules/clothing/gloves/insulated.dm b/code/modules/clothing/gloves/insulated.dm index c7acc7f87e2..10791ad09f7 100644 --- a/code/modules/clothing/gloves/insulated.dm +++ b/code/modules/clothing/gloves/insulated.dm @@ -13,6 +13,7 @@ custom_price = PAYCHECK_CREW * 10 custom_premium_price = PAYCHECK_COMMAND * 6 cut_type = /obj/item/clothing/gloves/cut + equip_sound = 'sound/items/equip/glove_equip.ogg' /obj/item/clothing/gloves/color/yellow/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/gloves/plasmaman.dm b/code/modules/clothing/gloves/plasmaman.dm index d429ab10fd8..36fd467282b 100644 --- a/code/modules/clothing/gloves/plasmaman.dm +++ b/code/modules/clothing/gloves/plasmaman.dm @@ -9,6 +9,7 @@ max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE armor_type = /datum/armor/color_plasmaman + equip_sound = 'sound/items/equip/glove_equip.ogg' /datum/armor/color_plasmaman bio = 100 diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm index d9b888fcd0e..f084b7e9a91 100644 --- a/code/modules/clothing/gloves/special.dm +++ b/code/modules/clothing/gloves/special.dm @@ -115,6 +115,7 @@ armor_type = /datum/armor/latex_gloves clothing_traits = list(TRAIT_QUICK_CARRY) resistance_flags = NONE + equip_sound = 'sound/items/equip/glove_equip.ogg' /datum/armor/latex_gloves bio = 100 diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm index ce3db5ab654..9564c20bfde 100644 --- a/code/modules/clothing/gloves/tacklers.dm +++ b/code/modules/clothing/gloves/tacklers.dm @@ -8,6 +8,7 @@ resistance_flags = NONE custom_premium_price = PAYCHECK_COMMAND * 3.5 clothing_traits = list(TRAIT_FINGERPRINT_PASSTHROUGH,TRAIT_FAST_CUFFING) + equip_sound = 'sound/items/equip/glove_equip.ogg' /// For storing our tackler datum so we can remove it after var/datum/component/tackler /// See: [/datum/component/tackler/var/stamina_cost] diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index c3072ac1355..69010c0a688 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -39,6 +39,7 @@ drop_sound = 'sound/items/handling/helmet/helmet_drop1.ogg' visor_toggle_up_sound = SFX_VISOR_UP visor_toggle_down_sound = SFX_VISOR_DOWN + hair_mask = HAIR_MASK_HIDE_ABOVE_45_DEG_LOW /obj/item/clothing/head/helmet/sec/Initialize(mapload) . = ..() @@ -68,6 +69,17 @@ return ..() +/obj/item/clothing/head/helmet/sec/attack_self(mob/user) + . = ..() + if(.) + return + balloon_alert(user, "[flags_inv & HIDEHAIR ? "loosening" : "tightening"] straps...") + if(!do_after(user, 3 SECONDS, src)) + return + flags_inv ^= HIDEHAIR + balloon_alert(user, "[flags_inv & HIDEHAIR ? "tightened" : "loosened"] straps") + return TRUE + /obj/item/clothing/head/helmet/sec/click_alt(mob/user) flipped_visor = !flipped_visor balloon_alert(user, "visor flipped") @@ -685,7 +697,6 @@ dog_fashion = /datum/dog_fashion/head/holymelon armor_type = /datum/armor/helmet_watermelon max_integrity = 15 - var/decayed = FALSE /obj/item/clothing/head/helmet/durability/holymelon/fire_resist resistance_flags = FIRE_PROOF @@ -693,13 +704,10 @@ /obj/item/clothing/head/helmet/durability/holymelon/Initialize(mapload) . = ..() - if(decayed) - decay() - return AddComponent( /datum/component/anti_magic, \ - antimagic_flags = MAGIC_RESISTANCE_HOLY, \ + antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, \ inventory_flags = ITEM_SLOT_OCLOTHING, \ charges = 1, \ drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index d8ba970c69c..d35c6a2bf88 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -94,9 +94,6 @@ GLOBAL_LIST_INIT(clown_mask_options, list( var/valid_wearer = ismob(loc) var/mob/wearer = loc if(istype(tool, /obj/item/cigarette)) - if(flags_cover & MASKCOVERSMOUTH) - balloon_alert(user, "mask's mouth is covered!") - return ..() if(max_filters <= 0 || cig) balloon_alert(user, "can't hold that!") diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index ee788b54580..4dc74aacd94 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -827,7 +827,6 @@ equip_delay_other = 40 clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) max_integrity = 15 - var/decayed = FALSE /obj/item/clothing/suit/armor/durability/holymelon/fire_resist resistance_flags = FIRE_PROOF @@ -835,13 +834,10 @@ /obj/item/clothing/suit/armor/durability/holymelon/Initialize(mapload) . = ..() - if(decayed) - decay() - return AddComponent( /datum/component/anti_magic, \ - antimagic_flags = MAGIC_RESISTANCE_HOLY, \ + antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, \ inventory_flags = ITEM_SLOT_OCLOTHING, \ charges = 1, \ drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ diff --git a/code/modules/deathmatch/deathmatch_modifier.dm b/code/modules/deathmatch/deathmatch_modifier.dm index 9faafa91a48..9671f19c92a 100644 --- a/code/modules/deathmatch/deathmatch_modifier.dm +++ b/code/modules/deathmatch/deathmatch_modifier.dm @@ -519,7 +519,7 @@ modifiers_pool -= modpath ///Pick global modifiers at random. - for(var/iteration in rand(3, 5)) + for(var/iteration in 1 to rand(3, 5)) var/datum/deathmatch_modifier/modifier = GLOB.deathmatch_game.modifiers[pick_n_take(modifiers_pool)] modifier.on_select(lobby) modifier.on_start_game(lobby) diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index 29a64c2b98a..59e2f0feb86 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -8,6 +8,9 @@ inhand_icon_state = "" w_class = WEIGHT_CLASS_TINY item_flags = NOBLUDGEON + drop_sound = 'sound/items/evidence_bag/evidence_bag_drop.ogg' + pickup_sound = 'sound/items/evidence_bag/evidence_bag_pickup.ogg' + sound_vary = TRUE /obj/item/evidencebag/Initialize(mapload) . = ..() @@ -15,20 +18,12 @@ max_slots = 1, max_specific_storage = WEIGHT_CLASS_NORMAL, ) + atom_storage.allow_quick_gather = TRUE + atom_storage.collection_mode = COLLECT_ONE RegisterSignal(atom_storage, COMSIG_STORAGE_STORED_ITEM, PROC_REF(on_insert)) RegisterSignal(atom_storage, COMSIG_STORAGE_REMOVED_ITEM, PROC_REF(on_remove)) - -/obj/item/evidencebag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - if(interacting_with == loc || !isitem(interacting_with) || HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) - return NONE - if(atom_storage.attempt_insert(interacting_with, user)) - return ITEM_INTERACT_SUCCESS - return NONE - -/obj/item/evidencebag/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if(atom_storage.attempt_insert(tool, user)) - return ITEM_INTERACT_SUCCESS - return NONE + atom_storage.rustle_sound = 'sound/items/evidence_bag/evidence_bag_zip.ogg' + atom_storage.remove_rustle_sound = 'sound/items/evidence_bag/evidence_bag_unzip.ogg' /obj/item/evidencebag/update_desc(updates) . = ..() @@ -60,12 +55,15 @@ /obj/item/evidencebag/proc/on_insert(datum/storage/storage, obj/item/to_insert, mob/user, force) SIGNAL_HANDLER + update_weight_class(to_insert.w_class) /obj/item/evidencebag/proc/on_remove(datum/storage/storage, obj/item/to_remove, atom/remove_to_loc, silent) SIGNAL_HANDLER + if(!atom_storage.get_total_weight()) return + update_weight_class(WEIGHT_CLASS_TINY) /obj/item/evidencebag/attack_self(mob/user) @@ -74,6 +72,7 @@ return user.visible_message(span_notice("[user] empties [src]."), span_notice("You empty [src]."),\ span_hear("You hear someone rustle around in a plastic bag, and remove something.")) + playsound(src,'sound/items/evidence_bag/evidence_bag_unzip.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, ignore_walls = FALSE) atom_storage.remove_all() /obj/item/storage/box/evidence diff --git a/code/modules/events/ghost_role/blob.dm b/code/modules/events/ghost_role/blob.dm index 8e83351f5c0..097620646d8 100644 --- a/code/modules/events/ghost_role/blob.dm +++ b/code/modules/events/ghost_role/blob.dm @@ -37,7 +37,7 @@ if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS var/mob/dead/observer/new_blob = chosen_one - var/mob/camera/blob/BC = new_blob.become_overmind() + var/mob/eye/blob/BC = new_blob.become_overmind() spawned_mobs += BC message_admins("[ADMIN_LOOKUPFLW(BC)] has been made into a blob overmind by an event.") BC.log_message("was spawned as a blob overmind by an event.", LOG_GAME) diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index 83028d129c4..5db33818d12 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -65,7 +65,7 @@ GLOBAL_LIST_EMPTY(all_wormholes) // So we can pick wormholes to teleport to . = ..() GLOB.all_wormholes -= src -/obj/effect/portal/wormhole/teleport(atom/movable/M) +/obj/effect/portal/wormhole/teleport(atom/movable/M, force = FALSE) if(iseffect(M)) //sparks don't teleport return if(M.anchored) diff --git a/code/modules/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm index ea37c9dc759..9d5180d37f0 100644 --- a/code/modules/fishing/aquarium/aquarium.dm +++ b/code/modules/fishing/aquarium/aquarium.dm @@ -318,7 +318,7 @@ var/obj/item/fish/fish = item .["fishData"] += list(list( "fish_ref" = REF(fish), - "fish_name" = fish.name, + "fish_name" = uppertext(fish.name), "fish_happiness" = fish.get_happiness_value(), "fish_icon" = fish::icon, "fish_icon_state" = fish::icon_state, diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index ba0f637827e..971b46df8b7 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -824,9 +824,11 @@ if(isaquarium(loc)) var/obj/structure/aquarium/aquarium = loc if(!aquarium.reproduction_and_growth) + last_feeding = world.time return var/hunger = get_hunger() if(hunger < 0.05) //don't bother growing for very small amounts. + last_feeding = world.time return last_feeding = world.time var/new_size = size @@ -1147,7 +1149,7 @@ var/list/available_fishes = list() var/types_to_mate_with = aquarium.tracked_fish_by_type if(!HAS_TRAIT(src, TRAIT_FISH_CROSSBREEDER)) - var/list/types_to_check = list(src) + var/list/types_to_check = list(type) if(compatible_types) types_to_check |= compatible_types types_to_mate_with = types_to_mate_with & types_to_check diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index 75fa7b5f981..90a0aa2e757 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -802,6 +802,8 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) /datum/fish_trait/camouflage/proc/reset_alpha(obj/item/fish/source) SIGNAL_HANDLER + if(QDELETED(source)) + return var/init_alpha = initial(source.alpha) if(init_alpha != source.alpha) animate(source.alpha, alpha = init_alpha, time = 1.2 SECONDS, easing = CIRCULAR_EASING|EASE_OUT) diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm index 79a43fc6052..08859e81bfa 100644 --- a/code/modules/fishing/fishing_equipment.dm +++ b/code/modules/fishing/fishing_equipment.dm @@ -118,10 +118,10 @@ else destination = user throw_callback = CALLBACK(src, PROC_REF(clear_hitby_signal), movable_target) - RegisterSignal(movable_target, COMSIG_ATOM_PREHITBY, PROC_REF(catch_it_chucklenut)) + RegisterSignal(movable_target, COMSIG_MOVABLE_PRE_IMPACT, PROC_REF(catch_it_chucklenut)) if(!movable_target.safe_throw_at(destination, source.cast_range, 2, callback = throw_callback, gentle = please_be_gentle)) - UnregisterSignal(movable_target, COMSIG_ATOM_PREHITBY) + UnregisterSignal(movable_target, COMSIG_MOVABLE_PRE_IMPACT) else playsound(src, 'sound/items/weapons/batonextend.ogg', 50, TRUE) @@ -129,12 +129,13 @@ SIGNAL_HANDLER var/mob/living/user = throwingdatum.initial_target.resolve() if(QDELETED(user) || hit_atom != user) - return - if(user.try_catch_item(source, skip_throw_mode_check = TRUE, try_offhand = TRUE)) - return COMSIG_HIT_PREVENTED + return NONE + if(!user.try_catch_item(source, skip_throw_mode_check = TRUE, try_offhand = TRUE)) + return NONE + return COMPONENT_MOVABLE_IMPACT_NEVERMIND /obj/item/fishing_line/auto_reel/proc/clear_hitby_signal(obj/item/item) - UnregisterSignal(item, COMSIG_ATOM_PREHITBY) + UnregisterSignal(item, COMSIG_MOVABLE_PRE_IMPACT) // Hooks diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm index 998c5347889..0447acc9138 100644 --- a/code/modules/fishing/fishing_minigame.dm +++ b/code/modules/fishing/fishing_minigame.dm @@ -506,6 +506,8 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user) else mover = new /datum/fish_movement(src) + SEND_SIGNAL(src, COMSIG_FISHING_CHALLENGE_MOVER_INITIALIZED, mover) + if(auto_reel) completion *= 1.3 else diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 8b24e34b9e5..4bd045616b3 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -122,7 +122,7 @@ if(hook) equipped_stuff += "[icon2html(hook, user)] [hook.name]" if(bait) - equipped_stuff += "[icon2html(bait, user)] [bait] as bait." + equipped_stuff += "[icon2html(bait, user)] [bait]" if(length(equipped_stuff)) . += span_notice("It has \a [english_list(equipped_stuff)] equipped.") if(!bait) diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm index 2ad6a2bc5bb..bfc90d6e05f 100644 --- a/code/modules/fishing/sources/_fish_source.dm +++ b/code/modules/fishing/sources/_fish_source.dm @@ -311,8 +311,12 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons()) return reward /// Returns the fish table, with with the unavailable items from fish_counts removed. -/datum/fish_source/proc/get_fish_table() +/datum/fish_source/proc/get_fish_table(from_explosion = FALSE) var/list/table = fish_table.Copy() + //message bottles cannot spawn from explosions. They're meant to be one-time messages (rarely) and photos from past rounds + //and it would suck if the pool of bottle messages were constantly being emptied by explosive fishing. + if(from_explosion) + table -= /obj/effect/spawner/message_in_a_bottle for(var/result in table) if(!isnull(fish_counts[result]) && fish_counts[result] <= 0) table -= result @@ -467,7 +471,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons()) /datum/fish_source/proc/spawn_reward_from_explosion(atom/location, severity) if(!(fish_source_flags & FISH_SOURCE_FLAG_EXPLOSIVE_MALUS)) - explosive_spawn(location, severity) + explosive_spawn(isturf(location) ? location : location.drop_location(), severity) return if(isnull(exploded_turfs)) exploded_turfs = list() @@ -486,7 +490,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons()) for(var/i in 1 to (severity + 2)) if(!prob((100 + 100 * severity)/i * multiplier)) continue - var/reward_loot = pick_weight(get_fish_table()) + var/reward_loot = pick_weight(get_fish_table(from_explosion = TRUE)) var/atom/movable/reward = simple_dispense_reward(reward_loot, location, location) if(isnull(reward)) continue diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm index a21f3f008e8..9b7c0d0bbf1 100644 --- a/code/modules/fishing/sources/source_types.dm +++ b/code/modules/fishing/sources/source_types.dm @@ -271,7 +271,7 @@ ///In the spirit of randomness, we skew a few values here and there /datum/fish_source/portal/random/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) - challenge.bait_bounce_mult = clamp(challenge.bait_bounce_mult + (rand(-3, 3) * 0.1), 0.1, 1) + challenge.bait_bounce_mult = max(challenge.bait_bounce_mult + rand(-3, 3) * 0.1, 0.1) challenge.completion_loss = max(challenge.completion_loss + rand(-2, 2), 0) challenge.completion_gain = max(challenge.completion_gain + rand(-1, 1), 2) challenge.mover.short_jump_velocity_limit += rand(-100, 100) @@ -280,6 +280,12 @@ for(var/effect in active_effects) if(prob(30)) challenge.special_effects |= effect + RegisterSignal(challenge, COMSIG_FISHING_CHALLENGE_MOVER_INITIALIZED, PROC_REF(randomize_mover_velocity)) + +/datum/fish_source/portal/random/proc/randomize_mover_velocity(datum/source, datum/fish_movement/mover) + SIGNAL_HANDLER + mover.short_jump_velocity_limit += rand(-100, 100) + mover.long_jump_velocity_limit += rand(-100, 100) ///Cherry on top, fish caught from the randomizer portal also have (almost completely) random traits /datum/fish_source/portal/random/spawn_reward(reward_path, atom/movable/spawn_location, turf/fishing_spot) @@ -295,7 +301,7 @@ var/obj/item/fish/caught_fish = new reward_path(spawn_location, FALSE) var/list/new_traits = list() - for(var/iteration in rand(1, 4)) + for(var/iteration in 1 to rand(1, 4)) new_traits |= pick_weight(weighted_traits) caught_fish.inherit_traits(new_traits) caught_fish.randomize_size_and_weight(deviation = 0.3) diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index 417ac543612..82607e4049c 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -237,6 +237,7 @@ if(!user.can_perform_action(src)) return balloon_alert(user, "writing box tag...") + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) boxtag_set = TRUE update_appearance() return diff --git a/code/modules/forensics/_forensics.dm b/code/modules/forensics/_forensics.dm index 5c43b9da099..8058a32e7fa 100644 --- a/code/modules/forensics/_forensics.dm +++ b/code/modules/forensics/_forensics.dm @@ -109,10 +109,10 @@ /// Adds a single fingerprint /datum/forensics/proc/add_fingerprint(mob/living/suspect, ignoregloves = FALSE) if(!isliving(suspect)) - if(!iscameramob(suspect)) + if(!iseyemob(suspect)) return if(isaicamera(suspect)) - var/mob/camera/ai_eye/ai_camera = suspect + var/mob/eye/ai_eye/ai_camera = suspect if(!ai_camera.ai) return suspect = ai_camera.ai @@ -190,10 +190,10 @@ /// Adds a single hiddenprint /datum/forensics/proc/add_hiddenprint(mob/suspect) if(!isliving(suspect)) - if(!iscameramob(suspect)) + if(!iseyemob(suspect)) return if(isaicamera(suspect)) - var/mob/camera/ai_eye/ai_camera = suspect + var/mob/eye/ai_eye/ai_camera = suspect if(!ai_camera.ai) return suspect = ai_camera.ai diff --git a/code/modules/hallucination/fake_death.dm b/code/modules/hallucination/fake_death.dm index c80c54959ee..126e9dd3a2b 100644 --- a/code/modules/hallucination/fake_death.dm +++ b/code/modules/hallucination/fake_death.dm @@ -101,41 +101,55 @@ return ..() /datum/hallucination/death/dust/start() - - if(!ishuman(hallucinator)) - return FALSE - - var/mob/living/carbon/human/hallucinating_human = hallucinator - var/dust_icon_state = hallucinating_human.dna?.species?.dust_anim - if(!dust_icon_state) - return FALSE - . = ..() if(!.) return - created_images = list() - var/turf/below_hallucinating = get_turf(hallucinator) - - // Apply a blank / empty image to make them look invisible to themselves + LAZYINITLIST(created_images) + // Makes hallucinator invisible, we create a clone image to animate on var/image/make_them_invisible = image(loc = hallucinator) make_them_invisible.override = TRUE created_images += make_them_invisible - - // Grab the typepath of the dust animation visual so we can steal its icon (for consistency and futureproofing) - var/obj/effect/temp_visual/dust_animation/dust_source = /obj/effect/temp_visual/dust_animation - var/image/fake_dust_animation = image(initial(dust_source.icon), below_hallucinating, dust_icon_state, layer = ABOVE_MOB_LAYER) - created_images += fake_dust_animation - - // Grab the typepath of remains so we can steal its icon and state (futureproofing) - var/obj/effect/decal/remains/human/remains_source = /obj/effect/decal/remains/human - var/image/fake_remains_image = image(initial(remains_source.icon), below_hallucinating, initial(remains_source.icon_state)) - created_images += fake_remains_image - - // Grab the typepath of an observer so we can steal its icon and state (futureproofing) - var/mob/dead/observer/observer_source = /mob/dead/observer - var/image/fake_ghost = image(initial(observer_source.icon), below_hallucinating, initial(observer_source.icon_state)) + // Makes remains, only visible if on a turf + if(isturf(hallucinator.loc)) + created_images += image(/obj/effect/decal/remains/human, hallucinator.loc) + // Makes a ghost + var/image/fake_ghost = image(/mob/dead/observer, get_turf(hallucinator)) DO_FLOATING_ANIM(fake_ghost) created_images += fake_ghost hallucinator.client?.images |= created_images + + // Does the actual animation here + if(isturf(hallucinator.loc)) + new /obj/effect/temp_visual/dust_hallucination(hallucinator.loc, hallucinator) + +/obj/effect/temp_visual/dust_hallucination + // duration doesn't really matter - it just needs to be longer than the dust animation + // for all non-hallucinating mobs, we're invisible + // for the hallucinating mob, we animate into invisibility + duration = 10 SECONDS + randomdir = FALSE + +/obj/effect/temp_visual/dust_hallucination/Initialize(mapload, mob/hallucinator) + . = ..() + if(isnull(hallucinator)) + return INITIALIZE_HINT_QDEL + + dir = hallucinator.dir + appearance = hallucinator.appearance + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + + // make it invisible to everyone else + var/image/invisible = image(loc = src) + invisible.override = TRUE + add_alt_appearance( + /* type = *//datum/atom_hud/alternate_appearance/basic/one_person/reversed, + /* key = */"[REF(src)]", + /* image = */invisible, + /* options = */null, + /* non-seer = */hallucinator, + ) + + // do the dust animation, only the hallucinator can see it now + dust_animation() diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 6edbfd382f9..b5527782011 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -139,10 +139,7 @@ reagents.add_reagent(/datum/reagent/consumable/ethanol/fruit_wine, reagent.volume, data, added_purity = reagent_purity) reagents.del_reagent(reagent.type) -/obj/item/food/grown/grind(datum/reagents/target_holder, mob/user) - if(on_grind() == -1) - return FALSE - +/obj/item/food/grown/grind_atom(datum/reagents/target_holder, mob/user) var/grind_results_num = LAZYLEN(grind_results) if(grind_results_num) var/average_purity = reagents.get_average_purity() @@ -152,9 +149,7 @@ for(var/reagent in grind_results) reagents.add_reagent(reagent, single_reagent_amount, added_purity = average_purity) - if(reagents && target_holder) - reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user) - return TRUE + return reagents?.trans_to(target_holder, reagents.total_volume, transferred_by = user) #undef BITE_SIZE_POTENCY_MULTIPLIER #undef BITE_SIZE_VOLUME_MULTIPLIER diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm index 7d4ece1d208..069b36482ea 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm @@ -300,6 +300,7 @@ righthand_file = 'icons/mob/inhands/items/touchspell_righthand.dmi' slot_flags = null item_flags = ABSTRACT | DROPDEL + resistance_flags = FIRE_PROOF|ACID_PROOF w_class = WEIGHT_CLASS_HUGE hitsound = 'sound/items/weapons/sear.ogg' damtype = BURN @@ -399,6 +400,7 @@ w_class = WEIGHT_CLASS_HUGE slot_flags = null item_flags = ABSTRACT + resistance_flags = FIRE_PROOF|ACID_PROOF sharpness = SHARP_EDGED attack_verb_continuous = list("saws", "tears", "lacerates", "cuts", "chops", "dices") attack_verb_simple = list("saw", "tear", "lacerate", "cut", "chop", "dice") @@ -522,6 +524,7 @@ righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' slot_flags = null item_flags = ABSTRACT + resistance_flags = FIRE_PROOF|ACID_PROOF w_class = WEIGHT_CLASS_HUGE sharpness = SHARP_EDGED wound_bonus = -20 @@ -572,7 +575,7 @@ /obj/item/nullrod/bostaff name = "monk's staff" desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts, it is now used to harass the clown." - force = 14 + force = 10 block_chance = 40 block_sound = 'sound/items/weapons/genhit.ogg' slot_flags = ITEM_SLOT_BACK @@ -600,6 +603,10 @@ icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]" return ..() +/obj/item/nullrod/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == PROJECTILE_ATTACK) + final_block_chance = 0 //Don't bring a sword to a gunfight + return ..() // Arrhythmic Knife - Lets your walk without rhythm by varying your walk speed. Can't be put away. diff --git a/code/modules/library/book.dm b/code/modules/library/book.dm index 7f5f010563a..0a190b94662 100644 --- a/code/modules/library/book.dm +++ b/code/modules/library/book.dm @@ -131,6 +131,7 @@ to_chat(user, span_warning("That title is invalid.")) return name = newtitle + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) book_data.set_title(html_decode(newtitle)) //Don't want to double encode here if("Contents") var/content = tgui_input_text(user, "Write your book's contents (HTML NOT allowed)", "Book Contents", max_length = MAX_PAPER_LENGTH, multiline = TRUE) @@ -140,6 +141,7 @@ to_chat(user, span_warning("The content is invalid.")) return book_data.set_content(html_decode(content)) + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) if("Author") var/author = tgui_input_text(user, "Write the author's name", "Author Name", max_length = MAX_NAME_LEN) if(!user.can_perform_action(src) || !user.can_write(attacking_item)) @@ -148,6 +150,7 @@ to_chat(user, span_warning("The name is invalid.")) return book_data.set_author(html_decode(author)) //Setting this encodes, don't want to double up + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) else if(istype(attacking_item, /obj/item/barcodescanner)) var/obj/item/barcodescanner/scanner = attacking_item diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index d7102fe9600..c3adc298b63 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -441,10 +441,12 @@ GLOBAL_VAR_INIT(library_table_modified, 0) var/id = params["book_id"] inventory -= id inventory_update() + update_static_data_for_all_viewers() return TRUE if("switch_inventory_page") inventory_page = sanitize_page_input(params["page"], inventory_page, inventory_page_count) inventory_update() + update_static_data_for_all_viewers() return TRUE if("checkout") var/list/available = list() diff --git a/code/modules/manufactorio/_manufacturing.dm b/code/modules/manufactorio/_manufacturing.dm index 5c44d1e8615..02cc47999d5 100644 --- a/code/modules/manufactorio/_manufacturing.dm +++ b/code/modules/manufactorio/_manufacturing.dm @@ -106,7 +106,7 @@ if(!manufactury.anchored) return MANUFACTURING_FAIL return manufactury.receive_resource(sending, src, isturf(what_or_dir) ? get_dir(src, what_or_dir) : what_or_dir) - if(next_turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = sending)) + if(next_turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = sending) && !ischasm(next_turf)) return MANUFACTURING_FAIL if(length(next_turf.contents) >= MANUFACTURING_TURF_LAG_LIMIT) return MANUFACTURING_FAIL_FULL diff --git a/code/modules/manufactorio/machines/crafter.dm b/code/modules/manufactorio/machines/crafter.dm index 4b3f2dba1c4..d164976b81a 100644 --- a/code/modules/manufactorio/machines/crafter.dm +++ b/code/modules/manufactorio/machines/crafter.dm @@ -22,6 +22,7 @@ craftsman = AddComponent(/datum/component/personal_crafting/machine) if(ispath(recipe)) recipe = locate(recipe) in (cooking ? GLOB.cooking_recipes : GLOB.crafting_recipes) + START_PROCESSING(SSmanufacturing, src) /obj/machinery/power/manufacturing/crafter/examine(mob/user) . = ..() @@ -45,8 +46,7 @@ var/turf/machine_turf = get_turf(src) if(length(machine_turf.contents) >= MANUFACTURING_TURF_LAG_LIMIT) return MANUFACTURING_FAIL_FULL - receiving.Move(machine_turf, receive_dir) - START_PROCESSING(SSmanufacturing, src) + receiving.forceMove(machine_turf) return MANUFACTURING_SUCCESS /obj/machinery/power/manufacturing/crafter/multitool_act(mob/living/user, obj/item/tool) diff --git a/code/modules/manufactorio/machines/lathe.dm b/code/modules/manufactorio/machines/lathe.dm index 431d7af1c11..351e5c25030 100644 --- a/code/modules/manufactorio/machines/lathe.dm +++ b/code/modules/manufactorio/machines/lathe.dm @@ -125,7 +125,7 @@ return var/craft_time = (design.construction_time * design.lathe_time_factor) ** 0.8 - flick_overlay_view(mutable_appearance(icon, "crafter_printing"), craft_time) + flick_overlay_view(mutable_appearance(icon, "lathe_printing"), craft_time) print_sound.start() add_load(power_cost) busy = addtimer(CALLBACK(src, PROC_REF(do_make_item), design, materials_needed), craft_time, TIMER_UNIQUE | TIMER_STOPPABLE | TIMER_DELETE_ME) diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index c2dffd37ee5..216275a2390 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -109,6 +109,7 @@ icon_state = "goliath_cloak" desc = "A staunch, practical cape made out of numerous monster materials, it is coveted amongst exiles & hermits." body_parts_covered = CHEST|GROIN|LEGS|ARMS + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON cold_protection = CHEST|GROIN|LEGS|ARMS min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT heat_protection = CHEST|GROIN|LEGS|ARMS diff --git a/code/modules/mining/equipment/monster_organs/brimdust_sac.dm b/code/modules/mining/equipment/monster_organs/brimdust_sac.dm index a77e526a9d1..62a3acdb447 100644 --- a/code/modules/mining/equipment/monster_organs/brimdust_sac.dm +++ b/code/modules/mining/equipment/monster_organs/brimdust_sac.dm @@ -71,7 +71,7 @@ id = "brimdust_coating" stacks = 0 max_stacks = 3 - tick_interval = -1 + tick_interval = STATUS_EFFECT_NO_TICK consumed_on_threshold = FALSE alert_type = /atom/movable/screen/alert/status_effect/brimdust_coating status_type = STATUS_EFFECT_REFRESH // Allows us to add one stack at a time by just applying the effect diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index 6ffcfa7bc67..fa9b63a4658 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -103,7 +103,7 @@ light_on = FALSE wibbles = FALSE -/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M) +/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M, force = FALSE) . = ..() if(.) // KERPLUNK diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 3d80ad066ff..bbe1de54243 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -761,8 +761,10 @@ berserk_value *= PROJECTILE_HIT_MULTIPLIER berserk_charge = clamp(round(berserk_charge + berserk_value), 0, MAX_BERSERK_CHARGE) if(berserk_charge >= MAX_BERSERK_CHARGE) + var/datum/action/item_action/berserk_mode/ragemode = locate() in actions to_chat(owner, span_notice("Berserk mode is fully charged.")) balloon_alert(owner, "berserk charged") + ragemode?.build_all_button_icons(UPDATE_BUTTON_STATUS) /obj/item/clothing/head/hooded/berserker/IsReflect() if(berserk_active) @@ -770,6 +772,7 @@ /// Starts berserk, reducing incoming brute by 50%, doubled attacking speed, NOGUNS trait, adding a color and giving them the berserk movespeed modifier /obj/item/clothing/head/hooded/berserker/proc/berserk_mode(mob/living/carbon/human/user) + var/datum/action/item_action/berserk_mode/ragemode = locate() in actions to_chat(user, span_warning("You enter berserk mode.")) playsound(user, 'sound/effects/magic/staff_healing.ogg', 50) user.add_movespeed_modifier(/datum/movespeed_modifier/berserk) @@ -780,6 +783,7 @@ ADD_TRAIT(src, TRAIT_NODROP, BERSERK_TRAIT) berserk_active = TRUE START_PROCESSING(SSobj, src) + ragemode?.build_all_button_icons(UPDATE_BUTTON_STATUS) /// Ends berserk, reverting the changes from the proc [berserk_mode] /obj/item/clothing/head/hooded/berserker/proc/end_berserk(mob/living/carbon/human/user) @@ -788,6 +792,8 @@ berserk_active = FALSE if(QDELETED(user)) return + var/datum/action/item_action/berserk_mode/ragemode = locate() in actions + ragemode?.build_all_button_icons(UPDATE_BUTTON_STATUS) to_chat(user, span_warning("You exit berserk mode.")) playsound(user, 'sound/effects/magic/summonitems_generic.ogg', 50) user.remove_movespeed_modifier(/datum/movespeed_modifier/berserk) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 312acb66720..24e0f53a87a 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -229,21 +229,27 @@ for(var/datum/material/material as anything in mat_container.materials) var/amount = mat_container.materials[material] var/sheet_amount = amount / SHEET_MATERIAL_AMOUNT + var/obj/sheet_type = material.sheet_type data["materials"] += list(list( "name" = material.name, "id" = REF(material), "amount" = sheet_amount, "category" = "material", "value" = ore_values[material.type], + "icon" = sheet_type::icon, + "icon_state" = sheet_type::icon_state, )) for(var/research in stored_research.researched_designs) var/datum/design/alloy = SSresearch.techweb_design_by_id(research) + var/obj/alloy_type = alloy.build_path data["materials"] += list(list( "name" = alloy.name, "id" = alloy.id, "category" = "alloy", "amount" = can_smelt_alloy(alloy), + "icon" = alloy_type::icon, + "icon_state" = alloy_type::icon_state, )) data["disconnected"] = null @@ -274,29 +280,6 @@ ) return data -/obj/machinery/mineral/ore_redemption/ui_static_data(mob/user) - var/list/data = list() - - var/datum/component/material_container/mat_container = materials.mat_container - if (mat_container) - for(var/datum/material/material as anything in mat_container.materials) - var/obj/material_display = initial(material.sheet_type) - data["material_icons"] += list(list( - "id" = REF(material), - "product_icon" = icon2base64(getFlatIcon(image(icon = initial(material_display.icon), icon_state = initial(material_display.icon_state)), no_anim=TRUE)), - )) - - for(var/research in stored_research.researched_designs) - var/datum/design/alloy = SSresearch.techweb_design_by_id(research) - var/obj/alloy_display = initial(alloy.build_path) - data["material_icons"] += list(list( - "id" = alloy.id, - "product_icon" = icon2base64(getFlatIcon(image(icon = initial(alloy_display.icon), icon_state = initial(alloy_display.icon_state)), no_anim=TRUE)), - )) - - return data - - /obj/machinery/mineral/ore_redemption/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f880c50dd08..c532769a1d9 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -328,7 +328,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp ghostize(FALSE) // FALSE parameter is so we can never re-enter our body. U ded. return TRUE -/mob/camera/verb/ghost() +/mob/eye/verb/ghost() set category = "OOC" set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." @@ -718,7 +718,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //this is called when a ghost is drag clicked to something. /mob/dead/observer/mouse_drop_dragged(atom/over, mob/user) - if (isobserver(user) && user.client.holder && (isliving(over) || iscameramob(over))) + if (isobserver(user) && user.client.holder && (isliving(over) || iseyemob(over))) user.client.holder.cmd_ghost_drag(src, over) /mob/dead/observer/Topic(href, href_list) diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index bdb0b7ce37e..d2823eae2b5 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -285,7 +285,7 @@ GLOBAL_DATUM_INIT(orbit_menu, /datum/orbit_menu, new) * Helper POI validation function passed as a callback to various SSpoints_of_interest procs. * * Provides extended validation above and beyond standard, limiting mob POIs without minds or ckeys - * unless they're mobs, camera mobs or megafauna. Also allows exceptions for mobs that are deadchat controlled. + * unless they're mobs, eye mobs or megafauna. Also allows exceptions for mobs that are deadchat controlled. * * If they satisfy that requirement, falls back to default validation for the POI. */ @@ -294,7 +294,7 @@ GLOBAL_DATUM_INIT(orbit_menu, /datum/orbit_menu, new) if(!potential_mob_poi.mind && !potential_mob_poi.ckey) if(!mob_allowed_typecache) mob_allowed_typecache = typecacheof(list( - /mob/camera, + /mob/eye, /mob/living/basic/regal_rat, /mob/living/simple_animal/bot, /mob/living/simple_animal/hostile/megafauna, diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 5d5df4e9b89..94feaefb873 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -48,7 +48,7 @@ /datum/emote/help key = "help" - mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/camera/imaginary_friend) + mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/eye/imaginary_friend) /datum/emote/help/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -80,8 +80,8 @@ key = "flip" key_third_person = "flips" hands_use_check = TRUE - mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/camera/imaginary_friend) - mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/camera/imaginary_friend) + mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/eye/imaginary_friend) + mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/eye/imaginary_friend) /datum/emote/flip/run_emote(mob/user, params , type_override, intentional) . = ..() @@ -117,8 +117,8 @@ key = "spin" key_third_person = "spins" hands_use_check = TRUE - mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/camera/imaginary_friend) - mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/camera/imaginary_friend) + mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/eye/imaginary_friend) + mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/eye/imaginary_friend) /datum/emote/spin/run_emote(mob/user, params, type_override, intentional) . = ..() diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/eye/eye.dm similarity index 71% rename from code/modules/mob/camera/camera.dm rename to code/modules/mob/eye/eye.dm index eb0d787f64b..ca58e2969c5 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/eye/eye.dm @@ -1,6 +1,6 @@ -// Camera mob, used by AI camera and blob. -/mob/camera - name = "camera mob" +// Eye mob, used by cameras and overminds such as blobs. +/mob/eye + name = "eye mob" density = FALSE move_force = INFINITY move_resist = INFINITY @@ -13,42 +13,42 @@ /// Toggles if the camera can use emotes var/has_emotes = FALSE -/mob/camera/Initialize(mapload) +/mob/eye/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_GODMODE, INNATE_TRAIT) SSpoints_of_interest.make_point_of_interest(src) if(!move_on_shuttle) ADD_TRAIT(src, TRAIT_BLOCK_SHUTTLE_MOVEMENT, INNATE_TRAIT) -/mob/camera/experience_pressure_difference() +/mob/eye/experience_pressure_difference() return -/mob/camera/canUseStorage() +/mob/eye/canUseStorage() return FALSE -/mob/camera/up() +/mob/eye/up() set name = "Move Upwards" set category = "IC" if(zMove(UP, z_move_flags = ZMOVE_FEEDBACK)) to_chat(src, span_notice("You move upwards.")) -/mob/camera/down() +/mob/eye/down() set name = "Move Down" set category = "IC" if(zMove(DOWN, z_move_flags = ZMOVE_FEEDBACK)) to_chat(src, span_notice("You move down.")) -/mob/camera/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) +/mob/eye/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) z_move_flags |= ZMOVE_IGNORE_OBSTACLES //cameras do not respect these FLOORS you speak so much of return ..() -/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE, force_silence = FALSE) +/mob/eye/emote(act, m_type=1, message = null, intentional = FALSE, force_silence = FALSE) if(has_emotes) return ..() return FALSE -/mob/camera/update_sight() +/mob/eye/update_sight() lighting_color_cutoffs = list(lighting_cutoff_red, lighting_cutoff_green, lighting_cutoff_blue) return ..() diff --git a/code/modules/mob/living/basic/blob_minions/blob_mob.dm b/code/modules/mob/living/basic/blob_minions/blob_mob.dm index 6c30bdfe16d..1ebd53bb592 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_mob.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_mob.dm @@ -25,7 +25,7 @@ AddComponent(/datum/component/blob_minion, on_strain_changed = CALLBACK(src, PROC_REF(on_strain_updated))) /// Called when our blob overmind changes their variant, update some of our mob properties -/mob/living/basic/blob_minion/proc/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/mob/living/basic/blob_minion/proc/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain) return /// Associates this mob with a specific blob factory node diff --git a/code/modules/mob/living/basic/blob_minions/blob_spore.dm b/code/modules/mob/living/basic/blob_minions/blob_spore.dm index 9c7b8001e06..6a61e8a56a2 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_spore.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_spore.dm @@ -88,7 +88,7 @@ z_turf = get_turf(factory) /// If the blob changes to distributed neurons then you can control the spores -/mob/living/basic/blob_minion/spore/minion/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/mob/living/basic/blob_minion/spore/minion/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain) if (isnull(overmind)) REMOVE_TRAIT(src, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) else diff --git a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm index 13146c3b5c5..a548a30be6a 100644 --- a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm +++ b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm @@ -92,7 +92,7 @@ to_chat(src, span_infoplain("The [blobstrain.name] reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]")) /// Set our attack damage based on blob's properties -/mob/living/basic/blob_minion/blobbernaut/minion/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/mob/living/basic/blob_minion/blobbernaut/minion/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain) if (isnull(overmind)) melee_damage_lower = initial(melee_damage_lower) melee_damage_upper = initial(melee_damage_upper) diff --git a/code/modules/mob/living/basic/heretic/flesh_worm.dm b/code/modules/mob/living/basic/heretic/flesh_worm.dm index cddd34ba441..13372c72688 100644 --- a/code/modules/mob/living/basic/heretic/flesh_worm.dm +++ b/code/modules/mob/living/basic/heretic/flesh_worm.dm @@ -56,7 +56,7 @@ /mob/living/basic/heretic_summon/armsy/has_gravity(turf/gravity_turf) return TRUE -/mob/living/basic/heretic_summon/armsy/can_be_pulled() +/mob/living/basic/heretic_summon/armsy/can_be_pulled(user, force) return FALSE // The component does this but not on the head. We don't want the head to be pulled either. /mob/living/basic/heretic_summon/armsy/proc/build_tail(worm_length) diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm b/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm index 440cfc2861b..ee93a9c1236 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm @@ -37,6 +37,7 @@ hunt_range = 7 /datum/ai_behavior/find_and_set/treatable_hydro + action_cooldown = 5 SECONDS /datum/ai_behavior/find_and_set/treatable_hydro/search_tactic(datum/ai_controller/controller, locate_path, search_range) var/list/possible_trays = list() @@ -97,6 +98,9 @@ return FALSE set_movement_target(controller, target) +/datum/ai_behavior/find_and_set/beamable_hydroplants + action_cooldown = 15 SECONDS + /datum/ai_behavior/find_and_set/beamable_hydroplants/search_tactic(datum/ai_controller/controller, locate_path, search_range) var/list/possible_trays = list() @@ -136,7 +140,8 @@ return can_see(source, water_source, radius) /datum/ai_behavior/hunt_target/interact_with_target/water_source - behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH + always_reset_target = TRUE hunt_cooldown = 5 SECONDS /datum/ai_controller/basic_controller/seedling/meanie diff --git a/code/modules/mob/living/basic/pets/orbie/orbie.dm b/code/modules/mob/living/basic/pets/orbie/orbie.dm index 85d82e92515..b4099a8c634 100644 --- a/code/modules/mob/living/basic/pets/orbie/orbie.dm +++ b/code/modules/mob/living/basic/pets/orbie/orbie.dm @@ -77,7 +77,7 @@ happy_state = !happy_state update_appearance() -/mob/living/basic/orbie/can_be_pulled(user, grab_state, force) +/mob/living/basic/orbie/can_be_pulled(user, force) return FALSE /mob/living/basic/orbie/proc/on_level_up(datum/source, new_level) diff --git a/code/modules/mob/living/basic/ruin_defender/flesh.dm b/code/modules/mob/living/basic/ruin_defender/flesh.dm index c5ff2fb90e7..550484a75c5 100644 --- a/code/modules/mob/living/basic/ruin_defender/flesh.dm +++ b/code/modules/mob/living/basic/ruin_defender/flesh.dm @@ -1,4 +1,10 @@ +/// Chance per second to print a warning text +#define LIVING_FLESH_WARN_CHANCE 3 +/// Chance per second to perform an unwanted interaction +#define LIVING_FLESH_INTERFERENCE_CHANCE 1.5 +/// Chance to caress instead of grab something nearby without combat mode #define LIVING_FLESH_TOUCH_CHANCE 30 +/// Chance to punch instead of grab something nearby in combat mode #define LIVING_FLESH_COMBAT_TOUCH_CHANCE 70 /datum/ai_controller/basic_controller/living_limb_flesh @@ -59,47 +65,47 @@ if(isnull(current_bodypart) || isnull(current_bodypart.owner)) return var/mob/living/carbon/human/victim = current_bodypart.owner - if(SPT_PROB(3, SSMOBS_DT)) - to_chat(victim, span_warning("The thing posing as your limb makes you feel funny...")) //warn em - //firstly as a sideeffect we drain nutrition from our host + if(SPT_PROB(LIVING_FLESH_WARN_CHANCE, SSMOBS_DT)) + to_chat(victim, span_warning("The skin on your [current_bodypart.plaintext_zone] crawls.")) + victim.adjust_nutrition(-1.5) - if(!SPT_PROB(1.5, SSMOBS_DT)) + if(!SPT_PROB(LIVING_FLESH_INTERFERENCE_CHANCE, SSMOBS_DT)) return - if(istype(current_bodypart, /obj/item/bodypart/arm)) - var/list/candidates = list() - for(var/atom/movable/movable in orange(victim, 1)) - if(movable == victim) - continue - if(!victim.CanReach(movable) || victim.invisibility) - continue - candidates += movable - if(!length(candidates)) - return - var/atom/movable/candidate = pick(candidates) - if(isnull(candidate)) - return - - victim.visible_message(span_warning("[victim]'s [current_bodypart.name] instinctively starts feeling [candidate]!")) - if (!victim.anchored && !prob(victim.combat_mode ? LIVING_FLESH_COMBAT_TOUCH_CHANCE : LIVING_FLESH_TOUCH_CHANCE)) - INVOKE_ASYNC(victim, TYPE_PROC_REF(/atom/movable, start_pulling), candidate, supress_message = TRUE) + if(istype(current_bodypart, /obj/item/bodypart/leg)) + if(HAS_TRAIT(victim, TRAIT_IMMOBILIZED)) return + step(victim, pick(GLOB.cardinals)) + to_chat(victim, span_warning("Your [current_bodypart.plaintext_zone] moves on its own!")) + return - var/active_hand = victim.active_hand_index - var/new_index = (current_bodypart.body_zone == BODY_ZONE_L_ARM) ? LEFT_HANDS : RIGHT_HANDS - if (active_hand != new_index) - victim.swap_hand(new_index, TRUE) - victim.resolve_unarmed_attack(candidate) - if (active_hand != victim.active_hand_index) // Different check in case we failed to swap hands previously due to holding a bulky item - victim.swap_hand(active_hand, TRUE) + var/list/candidates = list() + for(var/atom/movable/movable in orange(victim, 1)) + if(movable == victim) + continue + if(!victim.CanReach(movable) || movable.invisibility > victim.see_invisible) + continue + candidates += movable + if(!length(candidates)) + return + var/atom/movable/candidate = pick(candidates) + if(isnull(candidate)) return - if(HAS_TRAIT(victim, TRAIT_IMMOBILIZED)) + if (!prob(victim.combat_mode ? LIVING_FLESH_COMBAT_TOUCH_CHANCE : LIVING_FLESH_TOUCH_CHANCE) && candidate.can_be_pulled(user = victim, force = victim.pull_force)) + victim.visible_message(span_warning("[victim]'s [current_bodypart.plaintext_zone] suddenly fastens around [candidate]!")) + INVOKE_ASYNC(victim, TYPE_PROC_REF(/atom/movable, start_pulling), candidate, supress_message = TRUE) return - step(victim, pick(GLOB.cardinals)) - to_chat(victim, span_warning("Your [current_bodypart] moves on its own!")) + victim.visible_message(span_warning("[victim]'s [current_bodypart.plaintext_zone] suddenly spasms towards [candidate]!")) + var/active_hand = victim.active_hand_index + var/new_index = (current_bodypart.body_zone == BODY_ZONE_L_ARM) ? LEFT_HANDS : RIGHT_HANDS + if (active_hand != new_index) + victim.swap_hand(new_index, TRUE) + victim.resolve_unarmed_attack(candidate) + if (active_hand != victim.active_hand_index) // Different check in case we failed to swap hands previously due to holding a bulky item + victim.swap_hand(active_hand, TRUE) /mob/living/basic/living_limb_flesh/melee_attack(mob/living/carbon/human/target, list/modifiers, ignore_cooldown) . = ..() @@ -157,7 +163,7 @@ if(!detach_self()) return var/turf/our_location = get_turf(src) - our_location.visible_message(span_warning("[part_owner][part_owner.p_s()] [current_bodypart] begins to convulse wildly!")) + our_location.visible_message(span_warning("[part_owner][part_owner.p_s()] [current_bodypart.plaintext_zone] begins to convulse wildly!")) /mob/living/basic/living_limb_flesh/proc/owner_died(datum/source, gibbed) SIGNAL_HANDLER @@ -200,3 +206,5 @@ #undef LIVING_FLESH_TOUCH_CHANCE #undef LIVING_FLESH_COMBAT_TOUCH_CHANCE +#undef LIVING_FLESH_WARN_CHANCE +#undef LIVING_FLESH_INTERFERENCE_CHANCE diff --git a/code/modules/mob/living/basic/slime/ai/behaviours.dm b/code/modules/mob/living/basic/slime/ai/behaviours.dm index fe8102eee11..934404d88dd 100644 --- a/code/modules/mob/living/basic/slime/ai/behaviours.dm +++ b/code/modules/mob/living/basic/slime/ai/behaviours.dm @@ -25,6 +25,7 @@ return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_hunt_target/find_slime_food + action_cooldown = 7.5 SECONDS // Check if the slime can drain the target /datum/ai_behavior/find_hunt_target/find_slime_food/valid_dinner(mob/living/basic/slime/hunter, mob/living/dinner, radius, datum/ai_controller/controller, seconds_per_tick) diff --git a/code/modules/mob/living/basic/slime/ai/controller.dm b/code/modules/mob/living/basic/slime/ai/controller.dm index 41466b29734..1d5f00e6c43 100644 --- a/code/modules/mob/living/basic/slime/ai/controller.dm +++ b/code/modules/mob/living/basic/slime/ai/controller.dm @@ -4,7 +4,6 @@ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_SLIME_RABID = FALSE, BB_SLIME_HUNGER_DISABLED = FALSE, - BB_CURRENT_HUNTING_TARGET = null, // people whose energy we want to drain ) ai_movement = /datum/ai_movement/basic_avoidance @@ -13,13 +12,12 @@ /datum/ai_planning_subtree/change_slime_face, /datum/ai_planning_subtree/use_mob_ability/evolve, /datum/ai_planning_subtree/use_mob_ability/reproduce, - /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/find_and_hunt_target/find_slime_food, /datum/ai_planning_subtree/basic_melee_attack_subtree/slime, /datum/ai_planning_subtree/random_speech/slime, ) - can_idle = FALSE /datum/ai_controller/basic_controller/slime/CancelActions() ..() diff --git a/code/modules/mob/living/basic/slime/ai/pet_command.dm b/code/modules/mob/living/basic/slime/ai/pet_command.dm index 33484e360fb..211d7aa552c 100644 --- a/code/modules/mob/living/basic/slime/ai/pet_command.dm +++ b/code/modules/mob/living/basic/slime/ai/pet_command.dm @@ -10,7 +10,7 @@ var/mob/living/basic/slime/slime_pawn = controller.pawn if(isslime(slime_pawn) && slime_pawn.can_feed_on(controller.blackboard[BB_CURRENT_PET_TARGET], check_friendship = TRUE)) - controller.queue_behavior(hunting_behavior, BB_CURRENT_PET_TARGET, BB_HUNTING_COOLDOWN) + controller.queue_behavior(hunting_behavior, BB_CURRENT_PET_TARGET) return SUBTREE_RETURN_FINISH_PLANNING return ..() diff --git a/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm b/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm index c162ecf2c21..366cb1c5065 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm @@ -111,7 +111,7 @@ return FALSE var/datum/beam/draining_beam = Beam(target, icon_state = "drain_life") - if(!do_after(src, 4.6 SECONDS, target, timed_action_flags = (IGNORE_HELD_ITEM | IGNORE_INCAPACITATED))) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining. + if(!do_after(src, 4.6 SECONDS, target, timed_action_flags = (IGNORE_HELD_ITEM | IGNORE_INCAPACITATED))) //As one cannot prove the existence of ghosts, ghosts cannot prove the existence of the target they were draining. to_chat(src, span_revenwarning("[target ? "[target]'s soul has" : "[target_They_have]"] been drawn out of your grasp. The link has been broken.")) if(target) target.visible_message( diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 2ce1e94fb63..e5da7a47665 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -133,7 +133,7 @@ Des: Removes all infected images from the alien. ) new_xeno.setDir(dir) - new_xeno.change_name(name, real_name, numba) + new_xeno.change_name(name, real_name, identifier) if(mind) mind.name = new_xeno.real_name @@ -147,7 +147,7 @@ Des: Removes all infected images from the alien. qdel(src) /// Changes the name of the xeno we are evolving into in order to keep the same numerical identifier the old xeno had. -/mob/living/carbon/alien/proc/change_name(old_name, old_real_name, old_number) +/mob/living/carbon/alien/proc/change_name(old_name, old_real_name, old_identifier) if(!alien_name_regex.Find(old_name)) // check to make sure there's no admins doing funny stuff with naming these aliens name = old_name real_name = old_real_name @@ -156,8 +156,8 @@ Des: Removes all infected images from the alien. if(!unique_name) return - if(old_number != 0) - numba = old_number + if(old_identifier != 0) + identifier = old_identifier name = initial(name) // prevent chicanery like two different numerical identifiers tied to the same mob set_name() diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm index f5a0b7ace1b..8671a66c98a 100644 --- a/code/modules/mob/living/carbon/alien/death.dm +++ b/code/modules/mob/living/carbon/alien/death.dm @@ -7,8 +7,10 @@ /mob/living/carbon/alien/gib_animation() new /obj/effect/temp_visual/gib_animation(loc, "gibbed-a") -/mob/living/carbon/alien/spawn_dust() - new /obj/effect/decal/remains/xeno(loc) +/mob/living/carbon/alien/spawn_dust(just_ash) + if(just_ash) + return ..() -/mob/living/carbon/alien/dust_animation() - new /obj/effect/temp_visual/dust_animation(loc, "dust-a") + var/obj/effect/decal/remains/xeno/bones = new(loc) + bones.pixel_z = -6 + bones.pixel_w = rand(-1, 1) diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index 4b7f9f93218..3c4500518de 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -15,8 +15,10 @@ /mob/living/carbon/alien/larva/gib_animation() new /obj/effect/temp_visual/gib_animation(loc, "gibbed-l") -/mob/living/carbon/alien/larva/spawn_dust() - new /obj/effect/decal/remains/xeno(loc) +/mob/living/carbon/alien/larva/spawn_dust(just_ash) + if(just_ash) + return ..() -/mob/living/carbon/alien/larva/dust_animation() - new /obj/effect/temp_visual/dust_animation(loc, "dust-l") + var/obj/effect/decal/remains/xeno/bones = new(loc) + bones.pixel_z = -6 + bones.pixel_w = rand(-1, 1) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 4c362728d0e..76cb1e25dcc 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -147,8 +147,6 @@ GLOBAL_LIST_EMPTY(features_by_species) ///What gas does this species breathe? Used by suffocation screen alerts, most of actual gas breathing is handled by mutantlungs. See [life.dm][code/modules/mob/living/carbon/human/life.dm] var/breathid = GAS_O2 - ///What anim to use for dusting - var/dust_anim = "dust-h" ///What anim to use for gibbing var/gib_anim = "gibbed-h" diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 1cefc7d0c73..220570faa80 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -2,9 +2,6 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) /mob/living/carbon/human/gib_animation() new /obj/effect/temp_visual/gib_animation(loc, dna.species.gib_anim) -/mob/living/carbon/human/dust_animation() - new /obj/effect/temp_visual/dust_animation(loc, dna.species.dust_anim) - /mob/living/carbon/human/spawn_gibs(drop_bitflags=NONE) if(flags_1 & HOLOGRAM_1) return @@ -13,11 +10,17 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) else new /obj/effect/gibspawner/human/bodypartless(drop_location(), src, get_static_viruses()) -/mob/living/carbon/human/spawn_dust(just_ash = FALSE) +/mob/living/carbon/human/spawn_dust(just_ash) if(just_ash) - new /obj/effect/decal/cleanable/ash(loc) - else - new /obj/effect/decal/remains/human(loc) + return ..() + + var/bone_type = /obj/effect/decal/remains/human + if(isplasmaman(src)) + bone_type = /obj/effect/decal/remains/plasma + + var/obj/effect/decal/remains/human/bones = new bone_type(loc) + bones.pixel_z = -6 + bones.pixel_w = rand(-1, 1) /mob/living/carbon/human/death(gibbed) if(stat == DEAD) 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 1ca2979d3d6..0d332c78c58 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -35,7 +35,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/monkey, ) fire_overlay = "monkey" - dust_anim = "dust-m" gib_anim = "gibbed-m" payday_modifier = 1.5 diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 758dab37960..f6d247b95b1 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -69,6 +69,9 @@ /mob/living/proc/spread_bodyparts(drop_bitflags=NONE) return +/// Length of the animation in dust_animation.dmi +#define DUST_ANIMATION_TIME 1.3 SECONDS + /** * This is the proc for turning a mob into ash. * Dusting robots does not eject the MMI, so it's a bit more powerful than gib() @@ -91,15 +94,55 @@ buckled.unbuckle_mob(src, force = TRUE) dust_animation() - spawn_dust(just_ash) + addtimer(CALLBACK(src, PROC_REF(spawn_dust), just_ash), DUST_ANIMATION_TIME - 0.3 SECONDS) ghostize() - QDEL_IN(src,5) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes. + QDEL_IN(src, DUST_ANIMATION_TIME) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes. -/mob/living/proc/dust_animation() - return +/// Animates turning into dust. +/// Does not delete src afterwards, BUT it will become invisible (and grey), so ensure you handle that yourself +/atom/movable/proc/dust_animation(atom/anim_loc = src.loc) + if(isnull(anim_loc)) // the effect breaks if we have a null loc + return + var/obj/effect/temp_visual/dust_animation_filter/dustfx = new(anim_loc, REF(src)) + add_filter("dust_animation", 1, displacement_map_filter(render_source = dustfx.render_target, size = 256)) + add_filter("dust_color", 1, color_matrix_filter()) + transition_filter("dust_color", color_matrix_filter(COLOR_MATRIX_GRAYSCALE), DUST_ANIMATION_TIME - 0.3 SECONDS) + animate(src, alpha = 0, time = DUST_ANIMATION_TIME - 0.1 SECONDS, easing = SINE_EASING | EASE_IN) + +/// Holds the dust animation filter effect, so we can animate it +/obj/effect/temp_visual/dust_animation_filter + icon = 'icons/mob/dust_animation.dmi' + icon_state = "dust.1" + duration = DUST_ANIMATION_TIME + randomdir = FALSE + +/obj/effect/temp_visual/dust_animation_filter/Initialize(mapload, anim_id = "random_default_anti_collision_text") + . = ..() + // we manually animate this, rather than just using an animated icon state or flick, to work around byond animated state memes + // (normally, all animated icon states are synced to the same time, which would bad here) + for(var/i in 2 to duration) + if(PERFORM_ALL_TESTS(focus_only/runtime_icon_states) && !icon_exists(icon, "dust.[i]")) + stack_trace("Missing dust animation icon state: dust.[i]") + animate(src, time = 1, icon_state = "dust.[i]", flags = ANIMATION_CONTINUE) + if(PERFORM_ALL_TESTS(focus_only/runtime_icon_states) && icon_exists(icon, "dust.[duration + 1]")) + stack_trace("Extra dust animation icon state: dust.[duration + 1]") + render_target = "*dust-[anim_id]" + +#undef DUST_ANIMATION_TIME +/** + * Spawns dust / ash or remains where the mob was + * + * just_ash: If TRUE, just ash will spawn where the mob was, as opposed to remains + */ /mob/living/proc/spawn_dust(just_ash = FALSE) - new /obj/effect/decal/cleanable/ash(loc) + var/ash_type = /obj/effect/decal/cleanable/ash + if(mob_size >= MOB_SIZE_LARGE) + ash_type = /obj/effect/decal/cleanable/ash/large + + var/obj/effect/decal/cleanable/ash/ash = new ash_type(loc) + ash.pixel_z = -5 + ash.pixel_w = rand(-1, 1) /* * Called when the mob dies. Can also be called manually to kill a mob. diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index fda1be21a12..1fa2e11ac64 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -394,7 +394,7 @@ /mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE) if(!AM || !src) return FALSE - if(!(AM.can_be_pulled(src, state, force))) + if(!(AM.can_be_pulled(src, force))) return FALSE if(throwing || !(mobility_flags & MOBILITY_PULL)) return FALSE @@ -1971,7 +1971,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) "[C] leaps out of [src]'s way!"))) C.Paralyze(40) -/mob/living/can_be_pulled() +/mob/living/can_be_pulled(user, force) return ..() && !(buckled?.buckle_prevents_pull) @@ -2045,9 +2045,9 @@ GLOBAL_LIST_EMPTY(fire_appearances) user.put_in_hands(holder) /mob/living/proc/set_name() - if(numba == 0) - numba = rand(1, 1000) - name = "[name] ([numba])" + if(identifier == 0) + identifier = rand(1, 999) + name = "[name] ([identifier])" real_name = name /mob/living/proc/mob_try_pickup(mob/living/user, instant=FALSE) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index a12fde03107..6b04e84af12 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -148,7 +148,7 @@ ///if a mob's name should be appended with an id when created e.g. Mob (666) var/unique_name = FALSE ///the id a mob gets when it's created - var/numba = 0 + var/identifier = 0 ///these will be yielded from butchering with a probability chance equal to the butcher item's effectiveness var/list/butcher_results = null diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index a7e766f12bd..110c502ba45 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -62,7 +62,7 @@ var/nuking = FALSE var/obj/machinery/doomsday_device/doomsday_device - var/mob/camera/ai_eye/eyeobj + var/mob/eye/ai_eye/eyeobj var/sprint = 10 var/last_moved = 0 var/acceleration = TRUE @@ -120,7 +120,7 @@ create_eye() - if(target_ai.mind && target_ai.mind.active) + if((target_ai.mind && target_ai.mind.active) || SSticker.current_state == GAME_STATE_SETTING_UP) target_ai.mind.transfer_to(src) if(mind.special_role) to_chat(src, span_userdanger("You have been installed as an AI! ")) @@ -241,7 +241,7 @@ /// Removes all malfunction-related abilities from the AI /mob/living/silicon/ai/proc/remove_malf_abilities() QDEL_NULL(modules_action) - for(var/datum/ai_module/AM in current_modules) + for(var/datum/ai_module/malf/AM in current_modules) for(var/datum/action/A in actions) if(istype(A, initial(AM.power_type))) qdel(A) @@ -1140,7 +1140,7 @@ target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct . = ..() -/mob/living/silicon/ai/proc/camera_visibility(mob/camera/ai_eye/moved_eye) +/mob/living/silicon/ai/proc/camera_visibility(mob/eye/ai_eye/moved_eye) GLOB.cameranet.visibility(moved_eye, client, all_eyes, TRUE) /mob/living/silicon/ai/forceMove(atom/destination) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 2c5e809e5d9..b8bd1f443ea 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -65,7 +65,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) else other_eyes = list() - for(var/mob/camera/ai_eye/eye as anything in moved_eyes) + for(var/mob/eye/ai_eye/eye as anything in moved_eyes) var/list/visibleChunks = list() //Get the eye's turf in case its located in an object like a mecha var/turf/eye_turf = get_turf(eye) diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index c21f08e2d6b..7b2c57abc3c 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -16,7 +16,7 @@ ///list of all turfs, associative with that turf's static image ///turf -> /image var/list/turfs = list() - ///camera mobs that can see turfs in our grid + ///eye mobs that can see turfs in our grid var/list/seenby = list() ///images currently in use on obscured turfs. var/list/active_static_images = list() @@ -28,7 +28,7 @@ var/upper_z /// Add an AI eye to the chunk, then update if changed. -/datum/camerachunk/proc/add(mob/camera/ai_eye/eye) +/datum/camerachunk/proc/add(mob/eye/ai_eye/eye) eye.visibleCameraChunks += src seenby += eye if(changed) @@ -39,7 +39,7 @@ client.images += active_static_images /// Remove an AI eye from the chunk -/datum/camerachunk/proc/remove(mob/camera/ai_eye/eye, remove_static_with_last_chunk = TRUE) +/datum/camerachunk/proc/remove(mob/eye/ai_eye/eye, remove_static_with_last_chunk = TRUE) eye.visibleCameraChunks -= src seenby -= eye @@ -89,7 +89,7 @@ ///turfs that we could see last update but cant see now var/list/newly_obscured_turfs = visibleTurfs - updated_visible_turfs - for(var/mob/camera/ai_eye/client_eye as anything in seenby) + for(var/mob/eye/ai_eye/client_eye as anything in seenby) var/client/client = client_eye.ai?.client || client_eye.client if(!client) continue @@ -119,7 +119,7 @@ changed = FALSE - for(var/mob/camera/ai_eye/client_eye as anything in seenby) + for(var/mob/eye/ai_eye/client_eye as anything in seenby) var/client/client = client_eye.ai?.client || client_eye.client if(!client) continue diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 4570f93e0e9..c93054d6d26 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -2,11 +2,11 @@ // // An invisible (no icon) mob that the AI controls to look around the station with. // It streams chunks as it moves around, which will show it what the AI can and cannot see. -/mob/camera/ai_eye +/mob/eye/ai_eye name = "Inactive AI Eye" icon_state = "ai_camera" - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' invisibility = INVISIBILITY_MAXIMUM hud_possible = list(ANTAG_HUD, AI_DETECT_HUD = HUD_LIST_LIST) var/list/visibleCameraChunks = list() @@ -18,26 +18,26 @@ var/ai_detector_color = COLOR_RED interaction_range = INFINITY -/mob/camera/ai_eye/Initialize(mapload) +/mob/eye/ai_eye/Initialize(mapload) . = ..() GLOB.aiEyes += src update_ai_detect_hud() setLoc(loc, TRUE) -/mob/camera/ai_eye/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) +/mob/eye/ai_eye/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) . = ..() if(same_z_layer) return update_ai_detect_hud() -/mob/camera/ai_eye/examine(mob/user) //Displays a silicon's laws to ghosts +/mob/eye/ai_eye/examine(mob/user) //Displays a silicon's laws to ghosts . = ..() if(istype(ai) && ai.laws && isobserver(user)) . += "[ai] has the following laws:" for(var/law in ai.laws.get_law_list(include_zeroth = TRUE)) . += law -/mob/camera/ai_eye/proc/update_ai_detect_hud() +/mob/eye/ai_eye/proc/update_ai_detect_hud() var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT] var/list/old_images = hud_list[AI_DETECT_HUD] if(!ai_detector_visible) @@ -75,7 +75,7 @@ active_hud_list[AI_DETECT_HUD] = new_images hud.add_atom_to_hud(src) -/mob/camera/ai_eye/proc/get_visible_turfs() +/mob/eye/ai_eye/proc/get_visible_turfs() if(!isturf(loc)) return list() var/client/C = GetViewerClient() @@ -85,7 +85,7 @@ return block(lowerleft, upperright) /// Used in cases when the eye is located in a movable object (i.e. mecha) -/mob/camera/ai_eye/proc/update_visibility() +/mob/eye/ai_eye/proc/update_visibility() SIGNAL_HANDLER if(use_static) ai.camera_visibility(src) @@ -93,7 +93,7 @@ // Use this when setting the aiEye's location. // It will also stream the chunk that the new loc is in. -/mob/camera/ai_eye/proc/setLoc(destination, force_update = FALSE) +/mob/eye/ai_eye/proc/setLoc(destination, force_update = FALSE) if(!ai) return if(!isturf(ai.loc)) @@ -122,20 +122,20 @@ if(ai.master_multicam) ai.master_multicam.refresh_view() -/mob/camera/ai_eye/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs) +/mob/eye/ai_eye/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs) . = ..() if(.) setLoc(loc, force_update = TRUE) -/mob/camera/ai_eye/Move() +/mob/eye/ai_eye/Move() return -/mob/camera/ai_eye/proc/GetViewerClient() +/mob/eye/ai_eye/proc/GetViewerClient() if(ai) return ai.client return null -/mob/camera/ai_eye/Destroy() +/mob/eye/ai_eye/Destroy() if(ai) ai.all_eyes -= src ai = null @@ -215,7 +215,7 @@ /mob/living/silicon/ai/proc/create_eye() if(eyeobj) return - eyeobj = new /mob/camera/ai_eye() + eyeobj = new /mob/eye/ai_eye() all_eyes += eyeobj eyeobj.ai = src eyeobj.setLoc(loc) @@ -241,7 +241,7 @@ acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") -/mob/camera/ai_eye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) +/mob/eye/ai_eye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) . = ..() if(relay_speech && speaker && ai && !radio_freq && speaker != ai && GLOB.cameranet.checkCameraVis(speaker)) ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index 4ef437a5303..12ee1ce3b53 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -4,11 +4,11 @@ var/mob/living/silicon/ai/ai var/mutable_appearance/highlighted_background var/highlighted = FALSE - var/mob/camera/ai_eye/pic_in_pic/aiEye + var/mob/eye/ai_eye/pic_in_pic/aiEye /atom/movable/screen/movable/pic_in_pic/ai/Initialize(mapload, datum/hud/hud_owner) . = ..() - aiEye = new /mob/camera/ai_eye/pic_in_pic() + aiEye = new /mob/eye/ai_eye/pic_in_pic() aiEye.screen = src /atom/movable/screen/movable/pic_in_pic/ai/Destroy() @@ -126,7 +126,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) //Dummy camera eyes -/mob/camera/ai_eye/pic_in_pic +/mob/eye/ai_eye/pic_in_pic name = "Secondary AI Eye" invisibility = INVISIBILITY_OBSERVER mouse_opacity = MOUSE_OPACITY_ICON @@ -137,11 +137,11 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) var/telegraph_range = 7 ai_detector_color = COLOR_ORANGE -/mob/camera/ai_eye/pic_in_pic/GetViewerClient() +/mob/eye/ai_eye/pic_in_pic/GetViewerClient() if(screen?.ai) return screen.ai.client -/mob/camera/ai_eye/pic_in_pic/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/pic_in_pic/setLoc(turf/destination, force_update = FALSE) if (destination) abstract_move(destination) else @@ -153,10 +153,10 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) update_camera_telegraphing() update_ai_detect_hud() -/mob/camera/ai_eye/pic_in_pic/get_visible_turfs() +/mob/eye/ai_eye/pic_in_pic/get_visible_turfs() return screen ? screen.get_visible_turfs() : list() -/mob/camera/ai_eye/pic_in_pic/proc/update_camera_telegraphing() +/mob/eye/ai_eye/pic_in_pic/proc/update_camera_telegraphing() if(!telegraph_cameras) return var/list/obj/machinery/camera/add = list() @@ -185,7 +185,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) C.in_use_lights++ C.update_appearance() -/mob/camera/ai_eye/pic_in_pic/proc/disable_camera_telegraphing() +/mob/eye/ai_eye/pic_in_pic/proc/disable_camera_telegraphing() telegraph_cameras = FALSE for (var/obj/machinery/camera/C as anything in cameras_telegraphed) if(QDELETED(C)) @@ -194,7 +194,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) C.update_appearance() cameras_telegraphed.Cut() -/mob/camera/ai_eye/pic_in_pic/Destroy() +/mob/eye/ai_eye/pic_in_pic/Destroy() disable_camera_telegraphing() return ..() diff --git a/code/modules/mob/living/silicon/death.dm b/code/modules/mob/living/silicon/death.dm index 229ad70bb84..ba7fbea8ade 100644 --- a/code/modules/mob/living/silicon/death.dm +++ b/code/modules/mob/living/silicon/death.dm @@ -1,8 +1,13 @@ /mob/living/silicon/spawn_gibs() new /obj/effect/gibspawner/robot(drop_location(), src) -/mob/living/silicon/spawn_dust() - new /obj/effect/decal/remains/robot(loc) +/mob/living/silicon/spawn_dust(just_ash) + if(just_ash) + return ..() + + var/obj/effect/decal/remains/robot/robones = new(loc) + robones.pixel_z = -6 + robones.pixel_w = rand(-1, 1) /mob/living/silicon/death(gibbed) diag_hud_set_status() diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index 5c4384302b8..99c5686aa53 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -7,12 +7,6 @@ QDEL_NULL(mmi) return ..() -/mob/living/silicon/robot/spawn_dust() - new /obj/effect/decal/remains/robot(loc) - -/mob/living/silicon/robot/dust_animation() - new /obj/effect/temp_visual/dust_animation(loc, "dust-r") - /mob/living/silicon/robot/death(gibbed) if(stat == DEAD) return diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index fe6a7076f0f..ac9ca46d9b9 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -28,8 +28,6 @@ inv2 = new /atom/movable/screen/robot/module2() inv3 = new /atom/movable/screen/robot/module3() - ident = rand(1, 999) - previous_health = health if(ispath(cell)) @@ -192,6 +190,9 @@ model.transform_to(GLOB.cyborg_model_list[input_model]) +/mob/living/silicon/robot/set_name() //we have our name-making proc to call after we make our mmi, just set identifier here + if(identifier == 0) + identifier = rand(1, 999) /// Used to setup the a basic and (somewhat) unique name for the robot. /mob/living/silicon/robot/proc/setup_default_name() @@ -227,7 +228,7 @@ /mob/living/silicon/robot/proc/get_standard_name() - return "[(designation ? "[designation] " : "")][mmi.braintype]-[ident]" + return "[(designation ? "[designation] " : "")][mmi.braintype]-[identifier]" /mob/living/silicon/robot/proc/ionpulse() if(!ionpulse_on) @@ -859,7 +860,7 @@ shell = TRUE braintype = "AI Shell" - name = "Empty AI Shell-[ident]" + name = "Empty AI Shell-[identifier]" real_name = name GLOB.available_ai_shells |= src if(!QDELETED(builtInCamera)) @@ -878,7 +879,7 @@ qdel(boris) shell = FALSE GLOB.available_ai_shells -= src - name = "Unformatted Cyborg-[ident]" + name = "Unformatted Cyborg-[identifier]" real_name = name if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name @@ -891,7 +892,7 @@ * * AI - AI unit that initiated the deployment into the AI shell */ /mob/living/silicon/robot/proc/deploy_init(mob/living/silicon/ai/AI) - real_name = "[AI.real_name] [designation] Shell-[ident]" + real_name = "[AI.real_name] [designation] Shell-[identifier]" name = real_name if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name //update the camera name too diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index 7c6db79f7bd..7e9ab287ecf 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -15,6 +15,7 @@ designation = "Default" //used for displaying the prefix & getting the current model of cyborg has_limbs = TRUE hud_type = /datum/hud/robot + unique_name = TRUE ///Represents the cyborg's model (engineering, medical, etc.) var/obj/item/robot_model/model = null @@ -110,8 +111,6 @@ var/ai_lockdown = FALSE ///Timer that allows the borg to self-unlock after a set amount of time var/lockdown_timer = null - ///Random serial number generated for each cyborg upon its initialization - var/ident = 0 var/locked = TRUE req_one_access = list(ACCESS_ROBOTICS) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index dd3303f3523..5e9018384be 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -379,7 +379,7 @@ if(!isliving(user)) return - if(!istype(AM) || isdead(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) + if(!istype(AM) || isdead(AM) || iseyemob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) return load(AM) @@ -809,7 +809,7 @@ if(user.incapacitated || (istype(L) && L.body_position == LYING_DOWN)) return - if(!istype(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) //allows ghosts! + if(!istype(AM) || iseyemob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) //allows ghosts! return load(AM) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index e89522b6360..4efc847805f 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -668,7 +668,7 @@ return 0 // Infinite duration status effects technically are not "timed status effects" // by name or nature, but support is included just in case. - if(existing.duration == -1) + if(existing.duration == STATUS_EFFECT_PERMANENT) return INFINITY return existing.duration - world.time diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 601a707af9f..153f91f2494 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -277,7 +277,7 @@ hearers -= ignored_mobs //NOVA EDIT ADDITION BEGIN - AI QoL - for(var/mob/camera/ai_eye/ai_eye in hearers) + for(var/mob/eye/ai_eye/ai_eye in hearers) if(ai_eye.ai?.client && !(ai_eye.ai.stat == DEAD)) hearers -= ai_eye hearers |= ai_eye.ai @@ -361,7 +361,7 @@ var/list/hearers = get_hearers_in_view(hearing_distance, src) //NOVA EDIT ADDITION BEGIN - AI QoL - for(var/mob/camera/ai_eye/ai_eye in hearers) + for(var/mob/eye/ai_eye/ai_eye in hearers) if(ai_eye.ai?.client && !(ai_eye.ai.stat == DEAD)) hearers -= ai_eye hearers |= ai_eye.ai diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index bb3397cfec9..0d232ef3b66 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -172,6 +172,12 @@ var/min_x = -(strength*ICON_SIZE_X) var/min_y = -(strength*ICON_SIZE_Y) + if(C.prefs?.read_preference(/datum/preference/toggle/screen_shake_darken)) + var/type = /atom/movable/screen/fullscreen/flash/black + + M.overlay_fullscreen("flash", type) + addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, clear_fullscreen), "flash", 3 SECONDS), 3 SECONDS) + //How much time to allot for each pixel moved var/time_scalar = (1 / ICON_SIZE_ALL) * TILES_PER_SECOND var/last_x = oldx diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index a90a3fedc24..df33c71305e 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -261,7 +261,7 @@ return new_slime /mob/proc/become_overmind(starting_points = OVERMIND_STARTING_POINTS) - var/mob/camera/blob/B = new /mob/camera/blob(get_turf(src), starting_points) + var/mob/eye/blob/B = new /mob/eye/blob(get_turf(src), starting_points) B.key = key . = B qdel(src) diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index 7b09a00c853..2403528236f 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -423,7 +423,7 @@ /obj/item/mod/module/anomaly_locked name = "MOD anomaly locked module" desc = "A form of a module, locked behind an anomalous core to function." - incompatible_modules = list(/obj/item/mod/module/anomaly_locked) + incompatible_modules = list() /// The core item the module runs off. var/obj/item/assembly/signaler/anomaly/core /// Accepted types of anomaly cores. diff --git a/code/modules/mod/modules/module_kinesis.dm b/code/modules/mod/modules/module_kinesis.dm index 3c9ae3310b7..733e5ab40d9 100644 --- a/code/modules/mod/modules/module_kinesis.dm +++ b/code/modules/mod/modules/module_kinesis.dm @@ -17,7 +17,7 @@ accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/grav) required_slots = list(ITEM_SLOT_GLOVES) /// Range of the knesis grab. - var/grab_range = 5 + var/grab_range = 8 /// Time between us hitting objects with kinesis. var/hit_cooldown_time = 1 SECONDS /// Stat required for us to grab a mob. diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 14fc328aed7..42e4c56f55e 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -985,7 +985,7 @@ return gloves.AddComponent(/datum/component/adjust_fishing_difficulty, 5) if(equipped) - gloves.AddComponent(/datum/component/profound_fisher, equipped) + gloves.AddComponent(/datum/component/profound_fisher, equipped, delete_rod_when_deleted = FALSE) /obj/item/mod/module/fishing_glove/on_part_deactivation(deleting = FALSE) var/obj/item/gloves = mod.get_part_from_slot(ITEM_SLOT_GLOVES) diff --git a/code/modules/mod/modules/modules_science.dm b/code/modules/mod/modules/modules_science.dm index 409b4423366..ea9f1d01e43 100644 --- a/code/modules/mod/modules/modules_science.dm +++ b/code/modules/mod/modules/modules_science.dm @@ -55,9 +55,9 @@ desc = "A module that uses a gravitational core to make the user completely weightless." icon_state = "antigrav" module_type = MODULE_TOGGLE - complexity = 3 + complexity = 2 active_power_cost = DEFAULT_CHARGE_DRAIN * 0.7 - incompatible_modules = list(/obj/item/mod/module/anomaly_locked, /obj/item/mod/module/atrocinator) + incompatible_modules = list(/obj/item/mod/module/atrocinator, /obj/item/mod/module/anomaly_locked/antigrav) accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/grav) required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT) @@ -88,21 +88,34 @@ icon_state = "teleporter" module_type = MODULE_ACTIVE complexity = 3 - use_energy_cost = DEFAULT_CHARGE_DRAIN * 5 - cooldown_time = 5 SECONDS + use_energy_cost = DEFAULT_CHARGE_DRAIN * 25 + cooldown_time = 4 SECONDS + incompatible_modules = list(/obj/item/mod/module/anomaly_locked/teleporter) accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/bluespace) required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT) /// Time it takes to teleport - var/teleport_time = 3 SECONDS + var/teleport_time = 1 SECONDS + /// Maximum turf range + var/max_range = 9 /obj/item/mod/module/anomaly_locked/teleporter/on_select_use(atom/target) . = ..() if(!.) return var/turf/open/target_turf = get_turf(target) - if(!istype(target_turf) || target_turf.is_blocked_turf_ignore_climbable() || !(target_turf in view(mod.wearer))) + if(get_dist(target_turf, mod.wearer) > max_range) + balloon_alert(mod.wearer, "too far!") + return + if(!istype(target_turf)) balloon_alert(mod.wearer, "invalid target!") return + if(target_turf.is_blocked_turf_ignore_climbable() || !los_check(mod.wearer, target, pass_args = PASSTABLE|PASSGLASS|PASSGRILLE|PASSMOB|PASSMACHINE|PASSSTRUCTURE|PASSFLAPS|PASSWINDOW)) + balloon_alert(mod.wearer, "blocked destination!") + return + // check early so we don't go through the whole loops + if(!check_teleport_valid(mod.wearer, target_turf, channel = TELEPORT_CHANNEL_BLUESPACE, original_destination = target_turf)) + balloon_alert(mod.wearer, "something holds you back!") + return balloon_alert(mod.wearer, "teleporting...") var/matrix/pre_matrix = matrix() pre_matrix.Scale(4, 0.25) diff --git a/code/modules/modular_computers/file_system/programs/maintenance/camera.dm b/code/modules/modular_computers/file_system/programs/maintenance/camera.dm index f851dada495..e62aa35a608 100644 --- a/code/modules/modular_computers/file_system/programs/maintenance/camera.dm +++ b/code/modules/modular_computers/file_system/programs/maintenance/camera.dm @@ -11,12 +11,18 @@ circuit_comp_type = /obj/item/circuit_component/mod_program/camera /// Camera built-into the tablet. - var/obj/item/camera/internal_camera + var/obj/item/camera/app/internal_camera /// Latest picture taken by the app. var/datum/picture/internal_picture /// How many pictures were taken already, used for the camera's TGUI photo display var/picture_number = 1 +// Special type of camera for this exact usecase to prevent harddels +/obj/item/camera/app + name = "internal camera" + desc = "Specialized internal camera protected from the hellish depths of SSWardrobe. \ + Yell at coders if you somehow manage to see this" + /datum/computer_file/program/maintenance/camera/on_install() . = ..() internal_camera = new(computer) diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index 50c833ca89f..036584ec2b1 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -49,6 +49,7 @@ if(user.can_perform_action(src)) name = "folder[(inputvalue ? " - '[inputvalue]'" : null)]" + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) /obj/item/folder/proc/remove_item(obj/item/Item, mob/user) if(istype(Item)) diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index 1ae6a85edc0..2c5cc6fa5b9 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -116,6 +116,13 @@ labels_left = initial(labels_left) //Yes, it's capped at its initial value return ITEM_INTERACT_SUCCESS +/obj/item/hand_labeler/examine() + . = ..() + if(labels_left > 0) + . += span_notice("It looks like it could label [labels_left] more thing\s.") + else + . += span_notice("It's out of labels.") + /obj/item/hand_labeler/borg name = "cyborg-hand labeler" diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index eb7b2991852..525cb8aac23 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -683,6 +683,8 @@ // Safe to assume there are writing implement details as user.can_write(...) fails with an invalid writing implement. var/writing_implement_data = holding.get_writing_implement_details() + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) + add_raw_text(paper_input, writing_implement_data["font"], writing_implement_data["color"], writing_implement_data["use_bold"], check_rights_for(user?.client, R_FUN)) log_paper("[key_name(user)] wrote to [name]: \"[paper_input]\"") diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm index e240e94292d..3cac28663ff 100644 --- a/code/modules/photography/photos/photo.dm +++ b/code/modules/photography/photos/photo.dm @@ -82,6 +82,7 @@ return var/txt = tgui_input_text(user, "What would you like to write on the back?", "Photo Writing", max_length = 128) if(txt && user.can_perform_action(src)) + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) scribble = txt else return ..() diff --git a/code/modules/plumbing/plumbers/grinder_chemical.dm b/code/modules/plumbing/plumbers/grinder_chemical.dm index bd0a69e6d5e..c631e26def6 100644 --- a/code/modules/plumbing/plumbers/grinder_chemical.dm +++ b/code/modules/plumbing/plumbers/grinder_chemical.dm @@ -74,7 +74,7 @@ to_chat(user, span_notice("You dump items from [tool] into the grinder.")) for(var/obj/item/obj_item in tool.contents) - grind(obj_item) + blend(obj_item) return ITEM_INTERACT_SUCCESS else if(!tool.tool_behaviour) var/action = "[grinding ? "grind" : "juice"]" @@ -83,7 +83,7 @@ return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You attempt to [action] [tool].")) - grind(tool) + blend(tool) return ITEM_INTERACT_SUCCESS /obj/machinery/plumbing/grinder_chemical/CanAllowThrough(atom/movable/mover, border_dir) @@ -97,33 +97,45 @@ /obj/machinery/plumbing/grinder_chemical/proc/on_entered(datum/source, atom/movable/AM) SIGNAL_HANDLER - INVOKE_ASYNC(src, PROC_REF(grind), AM) + if(!isitem(AM)) + return + + INVOKE_ASYNC(src, PROC_REF(blend), AM) + + +/obj/machinery/plumbing/grinder_chemical/blended(obj/item/blended_item, grinded) + //don't delete slime extracts + if(istype(blended_item, /obj/item/slime_extract)) + //so you can't regrind them for extra stuff + blended_item.grind_results = null + + blended_item.forceMove(drop_location()) + + return TRUE + + return ..() /** * Grinds/Juices the atom * Arguments * * [AM][atom] - the atom to grind or juice */ -/obj/machinery/plumbing/grinder_chemical/proc/grind(atom/AM) +/obj/machinery/plumbing/grinder_chemical/proc/blend(obj/item/I) PRIVATE_PROC(TRUE) if(!is_operational || !anchored) return if(reagents.holder_full()) return - if(!isitem(AM)) - return - var/obj/item/I = AM if((I.item_flags & ABSTRACT) || (I.flags_1 & HOLOGRAM_1)) return + if(!I.blend_requirements(src)) + return - var/result if(!grinding) - result = I.juice(reagents, usr) + I.juice(reagents, usr, src) else if(length(I.grind_results) || I.reagents?.total_volume) - result = I.grind(reagents, usr) + I.grind(reagents, usr, src) use_energy(active_power_usage) - if(result) - qdel(I) diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 6e0555f937c..fd4bf689c90 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -777,7 +777,7 @@ plane = FLOOR_PLANE light_type = /obj/item/light/bulb fitting = "bulb" - nightshift_brightness = 3 + nightshift_brightness = 4 fire_brightness = 4.5 /obj/machinery/light/floor/get_light_offset() diff --git a/code/modules/power/singularity/reality_tear.dm b/code/modules/power/singularity/reality_tear.dm index 5ee3351cf68..692128e9d91 100644 --- a/code/modules/power/singularity/reality_tear.dm +++ b/code/modules/power/singularity/reality_tear.dm @@ -58,9 +58,7 @@ return var/mob/living/jedi = user to_chat(jedi, span_userdanger("You don't feel like you are real anymore.")) - jedi.dust_animation() - jedi.spawn_dust() - addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, attack_hand), jedi), 0.5 SECONDS) + jedi.dust(just_ash = TRUE) return COMPONENT_CANCEL_ATTACK_CHAIN //The temporary tears in reality. Collapses into nothing, and has a significantly lower gravity pull range, but consumes more widely. diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 182bd36a8bc..eb5ad47a88c 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -243,7 +243,7 @@ //This also means we have no need to track distance, as the doview() proc does it all for us. //Darkness fucks oview up hard. I've tried dview() but it doesn't seem to work - //I hate existance + //I hate existence for(var/atom/A as anything in typecache_filter_list(oview(zap_range+2, source), things_to_shock)) if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(shocked_targets, A)) continue diff --git a/code/modules/projectiles/guns/special/medbeam.dm b/code/modules/projectiles/guns/special/medbeam.dm index 0ad5caf2fec..95da571baf5 100644 --- a/code/modules/projectiles/guns/special/medbeam.dm +++ b/code/modules/projectiles/guns/special/medbeam.dm @@ -83,56 +83,26 @@ last_check = world.time - if(!los_check(loc, current_target)) + if(!los_check(loc, current_target, mid_check = CALLBACK(src, PROC_REF(mid_los_check)))) QDEL_NULL(current_beam)//this will give the target lost message return if(current_target) on_beam_tick(current_target) -/obj/item/gun/medbeam/proc/los_check(atom/movable/user, mob/target) - var/turf/user_turf = user.loc - if(mounted) - user_turf = get_turf(user) - else if(!istype(user_turf)) - return FALSE - var/obj/dummy = new(user_turf) - dummy.pass_flags |= PASSTABLE|PASSGLASS|PASSGRILLE //Grille/Glass so it can be used through common windows - var/turf/previous_step = user_turf - var/first_step = TRUE - for(var/turf/next_step as anything in (get_line(user_turf, target) - user_turf)) - if(first_step) - for(var/obj/blocker in user_turf) - if(!blocker.density || !(blocker.flags_1 & ON_BORDER_1)) - continue - if(blocker.CanPass(dummy, get_dir(user_turf, next_step))) - continue - return FALSE // Could not leave the first turf. - first_step = FALSE - if(mounted && next_step == user_turf) - - continue //Mechs are dense and thus fail the check - if(next_step.density) +/obj/item/gun/medbeam/proc/mid_los_check(atom/movable/user, mob/target, pass_args = PASSTABLE|PASSGLASS|PASSGRILLE, turf/next_step, obj/dummy) + for(var/obj/effect/ebeam/medical/B in next_step)// Don't cross the str-beams! + if(QDELETED(current_beam)) + break //We shouldn't be processing anymore. + if(QDELETED(B)) + continue + if(!B.owner) + stack_trace("beam without an owner! [B]") + continue + if(B.owner.origin != current_beam.origin) + explosion(B.loc, heavy_impact_range = 3, light_impact_range = 5, flash_range = 8, explosion_cause = src) qdel(dummy) return FALSE - for(var/atom/movable/movable as anything in next_step) - if(!movable.CanPass(dummy, get_dir(next_step, previous_step))) - qdel(dummy) - return FALSE - for(var/obj/effect/ebeam/medical/B in next_step)// Don't cross the str-beams! - if(QDELETED(current_beam)) - break //We shouldn't be processing anymore. - if(QDELETED(B)) - continue - if(!B.owner) - stack_trace("beam without an owner! [B]") - continue - if(B.owner.origin != current_beam.origin) - explosion(B.loc, heavy_impact_range = 3, light_impact_range = 5, flash_range = 8, explosion_cause = src) - qdel(dummy) - return FALSE - previous_step = next_step - qdel(dummy) return TRUE /obj/item/gun/medbeam/proc/on_beam_hit(mob/living/target) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 0eebe0e03bc..e1137411ef5 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -456,11 +456,11 @@ target = select_target(target_turf, target) continue - if (SEND_SIGNAL(target, COMSIG_PROJECTILE_PREHIT, args, src) & PROJECTILE_INTERRUPT_HIT) + if (SEND_SIGNAL(target, COMSIG_PROJECTILE_PREHIT, src) & PROJECTILE_INTERRUPT_HIT) qdel(src) return - if (SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_PREHIT, args) & PROJECTILE_INTERRUPT_HIT) + if (SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_PREHIT, target) & PROJECTILE_INTERRUPT_HIT) qdel(src) return diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 977bb2bcae1..588f6b7793c 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -279,9 +279,11 @@ var/datum/reagent/temp = GLOB.chemical_reagents_list[re] if(temp) var/chemname = temp.name + var/chemcolor = temp.color if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals += list(list("title" = chemname, "id" = temp.name, "pH" = temp.ph, "pHCol" = convert_ph_to_readable_color(temp.ph))) + chemcolor = random_colour() + chemicals += list(list("title" = chemname, "id" = temp.name, "pH" = temp.ph, "color" = chemcolor, "pHCol" = convert_ph_to_readable_color(temp.ph))) .["chemicals"] = chemicals .["recipes"] = saved_recipes diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 7aa53290184..1fdced9f41d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -395,7 +395,6 @@ . = TRUE if(. && !QDELETED(src)) //transferring volatile reagents can cause a explosion & destory us update_appearance(UPDATE_OVERLAYS) - return . /obj/machinery/chem_master/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() @@ -449,9 +448,27 @@ if("selectContainer") var/obj/item/reagent_containers/target = locate(params["ref"]) + + //is this even a valid type path if(!ispath(target)) return FALSE + //are we printing a valid container + var/container_found = FALSE + for(var/category in printable_containers) + //container found in previous iteration + if(container_found) + break + + //find for matching typepath + for(var/obj/item/reagent_containers/container as anything in printable_containers[category]) + if(target == container) + container_found = TRUE + break + if(!container_found) + return FALSE + + //set the container selected_container = target return TRUE diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 141fb7c4e6f..7716784e4b4 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -434,43 +434,33 @@ playsound(src, 'sound/machines/juicer.ogg', 20, TRUE) var/total_weight - for(var/obj/item/weapon in src) - if((weapon in component_parts) || weapon == beaker) - continue + var/item_weight + for(var/obj/item/ingredient in contents) if(beaker.reagents.holder_full()) break + if((ingredient in component_parts) || ingredient == beaker) + continue + + //record item weight before & after blending + item_weight = ingredient.w_class - //recursively process everything inside this atom - var/item_processed = FALSE - var/item_weight = weapon.w_class - for(var/obj/item/ingredient as anything in weapon.get_all_contents_type(/obj/item)) - if(beaker.reagents.holder_full()) - break - - if(juicing) - if(!ingredient.juice(beaker.reagents, user)) - to_chat(user, span_danger("[src] shorts out as it tries to juice up [ingredient], and transfers it back to storage.")) - continue - item_processed = TRUE - else if(length(ingredient.grind_results) || ingredient.reagents?.total_volume) - if(!ingredient.grind(beaker.reagents, user)) - if(isstack(ingredient)) - to_chat(user, span_notice("[src] attempts to grind as many pieces of [ingredient] as possible.")) - else - to_chat(user, span_danger("[src] shorts out as it tries to grind up [ingredient], and transfers it back to storage.")) - continue - item_processed = TRUE + if(juicing) + if(!ingredient.juice(beaker.reagents, user)) + to_chat(user, span_danger("[src] shorts out as it tries to juice up [ingredient], and transfers it back to storage.")) + continue + else if(!ingredient.grind(beaker.reagents, user)) + if(isstack(ingredient)) + to_chat(user, span_notice("[src] attempts to grind as many pieces of [ingredient] as possible.")) + else + to_chat(user, span_danger("[src] shorts out as it tries to grind up [ingredient], and transfers it back to storage.")) + continue //happens only for stacks where some of the sheets were grinded so we roughly compute the weight grinded - if(item_weight != weapon.w_class) - total_weight += item_weight - weapon.w_class + if(item_weight != ingredient.w_class) + total_weight += item_weight - ingredient.w_class else total_weight += item_weight - //delete only if operation was successfull for atleast 1 item(also delete atoms for whom only some of its contents were processed as they are non functional now) - if(item_processed) - qdel(weapon) - //use power according to the total weight of items grinded use_energy((active_power_usage * (duration / 1 SECONDS)) * (total_weight / maximum_weight)) diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 132d9ef7888..138df76c5b6 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -109,7 +109,7 @@ /datum/reagent/consumable/ethanol/beer name = "Beer" description = "An alcoholic beverage brewed since ancient times on Old Earth. Still popular today." - color = "#664300" // rgb: 102, 67, 0 + color = "#D7BC31" // rgb: 215, 188, 49 nutriment_factor = 1 boozepwr = 25 taste_description = "mild carbonated malt" @@ -1531,7 +1531,7 @@ /datum/reagent/consumable/ethanol/eggnog name = "Eggnog" description = "For enjoying the most wonderful time of the year." - color = "#fcfdc6" // rgb: 252, 253, 198 + color = "#ffe2ad" // rgb: 255, 226, 173 nutriment_factor = 2 boozepwr = 1 quality = DRINK_VERYGOOD @@ -1541,7 +1541,7 @@ /datum/reagent/consumable/ethanol/dreadnog name = "Dreadnog" description = "For suffering during a period of joy." - color = "#abb862" // rgb: 252, 253, 198 + color = "#f7ffad" // rgb: 247, 255, 173 nutriment_factor = 3 * REAGENTS_METABOLISM boozepwr = 1 quality = DRINK_REVOLTING @@ -1573,7 +1573,7 @@ /datum/reagent/consumable/ethanol/creme_de_menthe name = "Creme de Menthe" description = "A minty liqueur excellent for refreshing, cool drinks." - color = "#00cc00" + color = "#467446" //rgb: 70, 116, 70 boozepwr = 20 taste_description = "a minty, cool, and invigorating splash of cold streamwater" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1581,7 +1581,7 @@ /datum/reagent/consumable/ethanol/creme_de_cacao name = "Creme de Cacao" description = "A chocolatey liqueur excellent for adding dessert notes to beverages and bribing sororities." - color = "#996633" + color = "#350900" // rgb: 53, 9, 0 boozepwr = 20 taste_description = "a slick and aromatic hint of chocolates swirling in a bite of alcohol" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index da86dd07987..81af315a119 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -30,7 +30,7 @@ /datum/reagent/consumable/limejuice name = "Lime Juice" description = "The sweet-sour juice of limes." - color = "#365E30" // rgb: 54, 94, 48 + color = "#a6f19a" // rgb: 166, 241, 154 taste_description = "unbearable sourness" ph = 2.2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -73,14 +73,14 @@ /datum/reagent/consumable/applejuice name = "Apple Juice" description = "The sweet juice of an apple, fit for all ages." - color = "#ECFF56" // rgb: 236, 255, 86 + color = "#fff06b" // rgb: 255, 240, 107 taste_description = "apples" ph = 3.2 // ~ 2.7 -> 3.7 /datum/reagent/consumable/poisonberryjuice name = "Poison Berry Juice" description = "A tasty juice blended from various kinds of very deadly and toxic berries." - color = "#863353" // rgb: 134, 51, 83 + color = "#792b49" // rgb: 121, 43, 73 taste_description = "berries" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -92,14 +92,14 @@ /datum/reagent/consumable/watermelonjuice name = "Watermelon Juice" description = "Delicious juice made from watermelon." - color = "#863333" // rgb: 134, 51, 51 + color = "#af5e5e" // rgb: 175, 94, 94 taste_description = "juicy watermelon" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/lemonjuice name = "Lemon Juice" description = "This juice is VERY sour." - color = "#863333" // rgb: 175, 175, 0 + color = "#ebeb9e" // rgb: 235, 235, 158 taste_description = "sourness" ph = 2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -107,7 +107,7 @@ /datum/reagent/consumable/banana name = "Banana Juice" description = "The raw essence of a banana. HONK" - color = "#863333" // rgb: 175, 175, 0 + color = "#FFFCB9" // rgb: 255, 252, 185 taste_description = "banana" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -167,7 +167,7 @@ name = "Potato Juice" description = "Juice of the potato. Bleh." nutriment_factor = 2 - color = "#302000" // rgb: 48, 32, 0 + color = "#E8A856" // rgb: 234, 157, 58 taste_description = "irish sadness" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -175,7 +175,7 @@ name = "Pickle Juice" description = "More accurately, this is the brine the pickle was floating in" nutriment_factor = 2 - color = "#302000" // rgb: 48, 32, 0 + color = "#cde65e" // rgb: 205, 230, 94 taste_description = "vinegar brine" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -362,7 +362,7 @@ /datum/reagent/consumable/icecoffee name = "Iced Coffee" description = "Coffee and ice, refreshing and cool." - color = "#102838" // rgb: 16, 40, 56 + color = "#462b15" // rgb: 70, 43, 21 nutriment_factor = 0 overdose_threshold = 80 taste_description = "bitter coldness" @@ -383,7 +383,7 @@ /datum/reagent/consumable/hot_ice_coffee name = "Hot Ice Coffee" description = "Coffee with pulsing ice shards" - color = "#102838" // rgb: 16, 40, 56 + color = "#462b15" // rgb: 70, 43, 21 nutriment_factor = 0 overdose_threshold = 80 taste_description = "bitter coldness and a hint of smoke" @@ -950,7 +950,7 @@ name = "Hot Coco" description = "Made with love! And coco beans." nutriment_factor = 4 - color = "#403010" // rgb: 64, 48, 16 + color = "#3b240e" // rgb: 59, 36, 14 taste_description = "creamy chocolate" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1095,7 +1095,7 @@ /datum/reagent/consumable/aloejuice name = "Aloe Juice" - color = "#A3C48B" + color = "#b3c5a7" // rgb: 179, 197, 167 description = "A healthy and refreshing juice." taste_description = "vegetable" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1139,7 +1139,7 @@ /datum/reagent/consumable/toechtauese_juice name = "Töchtaüse Juice" description = "An unpleasant juice made from töchtaüse berries. Best made into a syrup, unless you enjoy pain." - color = "#554862" + color = "#554862" // rgb: 85, 72, 98 nutriment_factor = 0 taste_description = "fiery itchy pain" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1147,7 +1147,7 @@ /datum/reagent/consumable/toechtauese_syrup name = "Töchtaüse Syrup" description = "A harsh spicy and bitter syrup, made from töchtaüse berries. Useful as an ingredient, both for food and cocktails." - color = "#554862" + color = "#554862" // rgb: 85, 72, 98 nutriment_factor = 0 taste_description = "sugar, spice, and nothing nice" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1203,14 +1203,14 @@ /datum/reagent/consumable/cucumberjuice name = "Cucumber Juice" description = "Ordinary cucumber juice, nothing from the fantasy world." - color = "#6cd87a" + color = "#B1D861" // rgb: 177, 216, 97 taste_description = "light cucumber" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/cucumberlemonade name = "Cucumber Lemonade" description = "Cucumber juice, sugar, and soda; what else do I need?" - color = "#6cd87a" + color = "#cbe248" // rgb: 203, 226, 72 quality = DRINK_GOOD taste_description = "citrus soda with cucumber" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm index 5811f49da8f..564f081601d 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm @@ -95,6 +95,7 @@ name = "glass of amaretto" desc = "A sweet and syrupy looking drink." icon_state = "amarettoglass" + /datum/glass_style/drinking_glass/cognac required_drink_type = /datum/reagent/consumable/ethanol/cognac name = "glass of cognac" @@ -155,7 +156,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/pruno name = "glass of pruno" desc = "Fermented prison wine made from fruit, sugar, and despair. Security loves to confiscate this, which is the only kind thing Security has ever done." - icon_state = "glass_orange" /datum/glass_style/drinking_glass/navy_rum required_drink_type = /datum/reagent/consumable/ethanol/navy_rum @@ -187,7 +187,6 @@ name = "glass of yūyake" desc = "It's the saccharine essence of the 70s in a glass... the 1970s, that is!" icon = 'icons/obj/drinks/drinks.dmi' - icon_state = "glass_red" /datum/glass_style/drinking_glass/shochu required_drink_type = /datum/reagent/consumable/ethanol/shochu @@ -255,7 +254,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/hooch name = "Hooch" desc = "You've really hit rock bottom now... your liver packed its bags and left last night." - icon_state = "glass_brown2" /datum/glass_style/shot_glass/goldschlager required_drink_type = /datum/reagent/consumable/ethanol/goldschlager diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm index 36a8877b820..938a3753dd3 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm @@ -4,7 +4,6 @@ required_drink_type = /datum/reagent/consumable/coffee name = "glass of coffee" desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/tea required_drink_type = /datum/reagent/consumable/tea @@ -58,7 +57,6 @@ required_drink_type = /datum/reagent/consumable/hot_coco name = "glass of hot coco" desc = "A favorite winter drink to warm you up." - icon_state = "chocolateglass" drink_type = SUGAR | DAIRY /datum/glass_style/drinking_glass/italian_coco diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm index e788a589ad1..139f8a85929 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm @@ -4,7 +4,6 @@ required_drink_type = /datum/reagent/consumable/milk name = "glass of milk" desc = "White and nutritious goodness!" - icon_state = "glass_white" drink_type = DAIRY | BREAKFAST /datum/glass_style/has_foodtype/juicebox/milk @@ -25,17 +24,14 @@ required_drink_type = /datum/reagent/consumable/soymilk name = "glass of soy milk" desc = "White and nutritious soy goodness!" - icon_state = "glass_white" /datum/glass_style/drinking_glass/cream required_drink_type = /datum/reagent/consumable/cream name = "glass of cream" desc = "Ewwww..." - icon_state = "glass_white" /datum/glass_style/drinking_glass/coconut_milk required_drink_type = /datum/reagent/consumable/coconut_milk name = "glass of coconut milk" desc = "The essence of the tropics, contained safely within a glass." icon = 'icons/obj/drinks/drinks.dmi' - icon_state = "glass_white" diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm index 6f837d8f515..e7ecfa331fa 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm @@ -4,7 +4,6 @@ required_drink_type = /datum/reagent/consumable/orangejuice name = "glass of orange juice" desc = "Vitamins! Yay!" - icon_state = "glass_orange" drink_type = FRUIT | BREAKFAST /datum/glass_style/has_foodtype/juicebox/orangejuice @@ -62,13 +61,11 @@ required_drink_type = /datum/reagent/consumable/tomatojuice name = "glass of tomato juice" desc = "Are you sure this is tomato juice?" - icon_state = "glass_red" /datum/glass_style/drinking_glass/limejuice required_drink_type = /datum/reagent/consumable/limejuice name = "glass of lime juice" desc = "A glass of sweet-sour lime juice." - icon_state = "glass_green" /datum/glass_style/drinking_glass/carrotjuice required_drink_type = /datum/reagent/consumable/carrotjuice @@ -80,19 +77,16 @@ required_drink_type = /datum/reagent/consumable/berryjuice name = "glass of berry juice" desc = "Berry juice. Or maybe it's jam. Who cares?" - icon_state = "berryjuice" /datum/glass_style/drinking_glass/poisonberryjuice required_drink_type = /datum/reagent/consumable/poisonberryjuice name = "glass of berry juice" desc = "Berry juice. Or maybe it's poison. Who cares?" - icon_state = "poisonberryjuice" /datum/glass_style/drinking_glass/watermelonjuice required_drink_type = /datum/reagent/consumable/watermelonjuice name = "glass of watermelon juice" desc = "A glass of watermelon juice." - icon_state = "glass_red" /datum/glass_style/drinking_glass/lemonjuice required_drink_type = /datum/reagent/consumable/lemonjuice @@ -116,43 +110,36 @@ required_drink_type = /datum/reagent/consumable/potato_juice name = "glass of potato juice" desc = "Bleh..." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/bungojuice required_drink_type = /datum/reagent/consumable/bungojuice name = "glass of bungo juice" desc = "Exotic! You feel like you are on vacation already." - icon_state = "glass_yellow" /datum/glass_style/drinking_glass/prunomix required_drink_type = /datum/reagent/consumable/prunomix name = "glass of pruno mixture" desc = "Fruit, sugar, yeast, and water pulped together into a pungent slurry." - icon_state = "glass_orange" /datum/glass_style/drinking_glass/aloejuice required_drink_type = /datum/reagent/consumable/aloejuice name = "glass of aloe juice" desc = "A healthy and refreshing juice." - icon_state = "glass_yellow" /datum/glass_style/drinking_glass/toechtauese_juice required_drink_type = /datum/reagent/consumable/toechtauese_juice name = "glass of töchtaüse juice" desc = "Raw, unadulterated töchtaüse juice. One swig will fill you with regrets." - icon_state = "toechtauese_syrup" /datum/glass_style/drinking_glass/toechtauese_syrup required_drink_type = /datum/reagent/consumable/toechtauese_syrup name = "glass of töchtaüse syrup" desc = "Not for drinking on its own." - icon_state = "toechtauese_syrup" /datum/glass_style/drinking_glass/cucumberjuice required_drink_type = /datum/reagent/consumable/cucumberjuice name = "glass of cucumber juice" desc = "A glass of cucumber juice." - icon_state = "glass_cucumber" // Effectively misc @@ -161,7 +148,6 @@ required_drink_type = /datum/reagent/consumable/menthol name = "glass of menthol" desc = "Tastes naturally minty, and imparts a very mild numbing sensation." - icon_state = "glass_green" /datum/glass_style/drinking_glass/grenadine required_drink_type = /datum/reagent/consumable/grenadine diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm index 67802b9af20..ee741191771 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm @@ -2,7 +2,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/bilk name = "glass of bilk" desc = "A brew of milk and beer. For those alcoholics who fear osteoporosis." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/threemileisland required_drink_type = /datum/reagent/consumable/ethanol/threemileisland @@ -400,7 +399,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/bacchus_blessing name = "Bacchus' Blessing" desc = "You didn't think it was possible for a liquid to be so utterly revolting. Are you sure about this...?" - icon_state = "glass_brown2" /datum/glass_style/drinking_glass/atomicbomb required_drink_type = /datum/reagent/consumable/ethanol/atomicbomb @@ -434,7 +432,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/eggnog name = "eggnog" desc = "For enjoying the most wonderful time of the year." - icon_state = "glass_yellow" drink_type = FRUIT /datum/glass_style/has_foodtype/juicebox/eggnog @@ -461,25 +458,21 @@ required_drink_type = /datum/reagent/consumable/ethanol/triple_sec name = "Triple Sec" desc = "A glass of straight Triple Sec." - icon_state = "glass_orange" /datum/glass_style/drinking_glass/creme_de_menthe required_drink_type = /datum/reagent/consumable/ethanol/creme_de_menthe name = "Creme de Menthe" desc = "You can almost feel the first breath of spring just looking at it." - icon_state = "glass_green" /datum/glass_style/drinking_glass/creme_de_cacao required_drink_type = /datum/reagent/consumable/ethanol/creme_de_cacao name = "Creme de Cacao" desc = "A million hazing lawsuits and alcohol poisonings have started with this humble ingredient." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/creme_de_coconut required_drink_type = /datum/reagent/consumable/ethanol/creme_de_coconut name = "Creme de Coconut" desc = "An unintimidating glass of coconut liqueur." - icon_state = "glass_white" /datum/glass_style/drinking_glass/quadruple_sec required_drink_type = /datum/reagent/consumable/ethanol/quadruple_sec @@ -787,7 +780,6 @@ /datum/glass_style/drinking_glass/mushi_kombucha required_drink_type = /datum/reagent/consumable/ethanol/mushi_kombucha name = "glass of mushi kombucha" - icon_state = "glass_orange" /datum/glass_style/drinking_glass/triumphal_arch required_drink_type = /datum/reagent/consumable/ethanol/triumphal_arch diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm index 893466f9a8c..1bf91cc898d 100644 --- a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm @@ -480,6 +480,7 @@ Basically, we fill the time between now and 2s from now with hands based off the overdose_threshold = 20 self_consuming = TRUE //No pesky liver shenanigans chemical_flags = REAGENT_DONOTSPLIT | REAGENT_DEAD_PROCESS + affected_organ_flags = NONE ///If we brought someone back from the dead var/back_from_the_dead = FALSE /// List of trait buffs to give to the affected mob, and remove as needed. diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index d11e608ccb6..8347c62629c 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -17,7 +17,6 @@ required_drink_type = /datum/reagent/blood name = "glass of tomato juice" desc = "Are you sure this is tomato juice?" - icon_state = "glass_red" // FEED ME /datum/reagent/blood/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user) diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 4670aebdd6e..9e6c9da53a0 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -248,7 +248,7 @@ for(var/atom/movable/X in orange(range, T)) if(X.anchored) continue - if(iseffect(X) || iscameramob(X) || isdead(X)) + if(iseffect(X) || iseyemob(X) || isdead(X)) continue var/distance = get_dist(X, T) var/moving_power = max(range - distance, 1) @@ -413,7 +413,7 @@ live.apply_damage(damage)//Since this can be called multiple times if(movey.anchored) continue - if(iseffect(movey) || iscameramob(movey) || isdead(movey)) + if(iseffect(movey) || iseyemob(movey) || isdead(movey)) continue if(implosion) var/distance = get_dist(movey, this_turf) diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index c7d8c59e439..847ae8b3997 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -571,7 +571,7 @@ /datum/chemical_reaction/corgium/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) var/location = get_turf(holder.my_atom) - for(var/i in rand(1, created_volume) to created_volume) // More lulz. + for(var/i in 1 to rand(1, created_volume)) // More lulz. new /mob/living/basic/pet/dog/corgi(location) ..() @@ -627,7 +627,7 @@ /datum/chemical_reaction/butterflium/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) var/location = get_turf(holder.my_atom) - for(var/i in rand(1, created_volume) to created_volume) + for(var/i in 1 to rand(1, created_volume)) new /mob/living/basic/butterfly(location) ..() //scream powder @@ -976,7 +976,7 @@ /datum/chemical_reaction/ant_slurry/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) var/location = get_turf(holder.my_atom) - for(var/i in rand(1, created_volume) to created_volume) + for(var/i in 1 to rand(1, created_volume)) new /mob/living/basic/ant(location) ..() diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index 21d076e949f..41622550f8f 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -384,7 +384,7 @@ /datum/chemical_reaction/slime/slimeoil - results = list(/datum/reagent/consumable/nutriment/fat/oil = 10) + results = list(/datum/reagent/consumable/nutriment/fat/oil/corn = 10) required_reagents = list(/datum/reagent/blood = 1) required_container = /obj/item/slime_extract/oil diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 15c79e4c150..cdc8c3a4639 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -111,6 +111,7 @@ if(custom_label) labelled = TRUE name = "blood pack - [custom_label]" + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) balloon_alert(user, "new label set") else labelled = FALSE diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm index 5d5cbce1254..4c61f7af269 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -530,11 +530,17 @@ if(grinded) to_chat(user, span_warning("There is something inside already!")) return - if(I.juice_typepath || I.grind_results) + if(!I.blend_requirements(src)) + to_chat(user, span_warning("Cannot grind this!")) + return + if(length(I.grind_results) || I.reagents?.total_volume) I.forceMove(src) grinded = I - return - to_chat(user, span_warning("You can't grind this!")) + +/obj/item/reagent_containers/cup/mortar/blended(obj/item/blended_item, grinded) + src.grinded = null + + return ..() /obj/item/reagent_containers/cup/mortar/proc/grind_item(obj/item/item, mob/living/carbon/human/user) if(item.flags_1 & HOLOGRAM_1) @@ -544,13 +550,12 @@ if(!item.grind(reagents, user)) if(isstack(item)) - to_chat(usr, span_notice("[src] attempts to grind as many pieces of [item] as possible.")) + to_chat(user, span_notice("[src] attempts to grind as many pieces of [item] as possible.")) else to_chat(user, span_danger("You fail to grind [item].")) return + to_chat(user, span_notice("You grind [item] into a nice powder.")) - grinded = null - QDEL_NULL(item) /obj/item/reagent_containers/cup/mortar/proc/juice_item(obj/item/item, mob/living/carbon/human/user) if(item.flags_1 & HOLOGRAM_1) @@ -561,9 +566,8 @@ if(!item.juice(reagents, user)) to_chat(user, span_notice("You fail to juice [item].")) return + to_chat(user, span_notice("You juice [item] into a fine liquid.")) - grinded = null - QDEL_NULL(item) //Coffeepots: for reference, a standard cup is 30u, to allow 20u for sugar/sweetener/milk/creamer /obj/item/reagent_containers/cup/coffeepot diff --git a/code/modules/reagents/reagent_containers/cups/bottle.dm b/code/modules/reagents/reagent_containers/cups/bottle.dm index 2259cda34d7..f733a4dac88 100644 --- a/code/modules/reagents/reagent_containers/cups/bottle.dm +++ b/code/modules/reagents/reagent_containers/cups/bottle.dm @@ -544,6 +544,7 @@ return if(user.can_perform_action(src)) + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) name = "[(inputvalue ? "[inputvalue]" : null)] bottle" //types of syrups diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index be774198dd2..04ff332a9ea 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -401,6 +401,8 @@ current_range = 2 spray_range = 2 spray_sound = 'sound/effects/snap.ogg' + possible_transfer_amounts = list(5) + reagent_container_liquid_sound = null /obj/item/reagent_containers/spray/chemsprayer/party/spray(atom/A, mob/user) . = ..() diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 3d36ef1ecea..6039191918d 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -122,6 +122,7 @@ if(!str || !length(str)) to_chat(user, span_warning("Invalid text!")) return + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) user.visible_message(span_notice("[user] labels [src] as [str].")) name = "[name] ([str])" diff --git a/code/modules/religion/religion_structures.dm b/code/modules/religion/religion_structures.dm index 1b30d021268..8c8783f16eb 100644 --- a/code/modules/religion/religion_structures.dm +++ b/code/modules/religion/religion_structures.dm @@ -109,7 +109,7 @@ new /obj/effect/decal/cleanable/ash(drop_location()) qdel(src) -/obj/item/ritual_totem/can_be_pulled(user, grab_state, force) +/obj/item/ritual_totem/can_be_pulled(user, force) . = ..() return FALSE //no diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 0e6dd68c3e0..c68410caa04 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -39,6 +39,8 @@ . += span_notice("An item can be loaded inside via [EXAMINE_HINT("Left-Click")].") /obj/machinery/rnd/destructive_analyzer/base_item_interaction(mob/living/user, obj/item/weapon, list/modifiers) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + return ..() if(user.combat_mode) return ..() if(!is_insertion_ready(user)) diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm index dce09ae2809..3ed1a8f5b37 100644 --- a/code/modules/research/stock_parts.dm +++ b/code/modules/research/stock_parts.dm @@ -18,13 +18,6 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good . = ..() create_storage(storage_type = /datum/storage/rped) -/obj/item/storage/part_replacer/pre_attack(obj/attacked_object, mob/living/user, params) - . = ..() - if(.) - return . - - return part_replace_action(attacked_object, user) - /obj/item/storage/part_replacer/proc/part_replace_action(obj/attacked_object, mob/living/user) if(!ismachinery(attacked_object) || istype(attacked_object, /obj/machinery/computer)) return FALSE diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 227f1be5165..9376ca9441f 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -59,8 +59,8 @@ /datum/status_effect/slimerecall id = "slime_recall" - duration = -1 //Will be removed by the extract. - tick_interval = -1 + duration = STATUS_EFFECT_PERMANENT //Will be removed by the extract. + tick_interval = STATUS_EFFECT_NO_TICK alert_type = null var/interrupted = FALSE var/mob/target @@ -96,7 +96,7 @@ /datum/status_effect/frozenstasis id = "slime_frozen" status_type = STATUS_EFFECT_UNIQUE - duration = -1 //Will remove self when block breaks. + duration = STATUS_EFFECT_PERMANENT //Will remove self when block breaks. alert_type = /atom/movable/screen/alert/status_effect/freon/stasis var/obj/structure/ice_stasis/cube @@ -125,7 +125,7 @@ /datum/status_effect/slime_clone id = "slime_cloned" status_type = STATUS_EFFECT_UNIQUE - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null var/mob/living/clone var/datum/mind/originalmind //For when the clone gibs. @@ -169,7 +169,7 @@ /datum/status_effect/slime_clone_decay id = "slime_clonedecay" status_type = STATUS_EFFECT_UNIQUE - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = /atom/movable/screen/alert/status_effect/clone_decay /datum/status_effect/slime_clone_decay/tick(seconds_between_ticks) @@ -230,7 +230,7 @@ /datum/status_effect/rebreathing id = "rebreathing" - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null /datum/status_effect/rebreathing/tick(seconds_between_ticks) @@ -440,7 +440,7 @@ /datum/status_effect/stabilized //The base stabilized extract effect, has no effect of its' own. id = "stabilizedbase" - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null /// Item which provides this buff var/obj/item/slimecross/stabilized/linked_extract @@ -836,7 +836,7 @@ /datum/status_effect/pinkdamagetracker id = "pinkdamagetracker" - duration = -1 + duration = STATUS_EFFECT_PERMANENT alert_type = null var/damage = 0 var/lasthealth diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 68ffe5e9248..fc6d236f96a 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -1,22 +1,22 @@ //Xenobio control console -/mob/camera/ai_eye/remote/xenobio +/mob/eye/ai_eye/remote/xenobio visible_icon = TRUE - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' icon_state = "generic_camera" var/allowed_area = null -/mob/camera/ai_eye/remote/xenobio/Initialize(mapload) +/mob/eye/ai_eye/remote/xenobio/Initialize(mapload) var/area/our_area = get_area(loc) allowed_area = our_area.name . = ..() -/mob/camera/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE) var/area/new_area = get_area(destination) if(new_area && new_area.name == allowed_area || new_area && (new_area.area_flags & XENOBIOLOGY_COMPATIBLE)) return ..() -/mob/camera/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) +/mob/eye/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) . = ..() if(!.) return @@ -84,10 +84,10 @@ stored_slimes -= gone /obj/machinery/computer/camera_advanced/xenobio/CreateEye() - eyeobj = new /mob/camera/ai_eye/remote/xenobio(get_turf(src)) + eyeobj = new /mob/eye/ai_eye/remote/xenobio(get_turf(src)) eyeobj.origin = src eyeobj.visible_icon = TRUE - eyeobj.icon = 'icons/mob/silicon/cameramob.dmi' + eyeobj.icon = 'icons/mob/eyemob.dmi' eyeobj.icon_state = "generic_camera" /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user) @@ -151,7 +151,7 @@ Boilerplate check for a valid area to perform a camera action in. Checks if the AI eye is on a valid turf and then checks if the target turf is xenobiology compatible Due to keyboard shortcuts, the second one is not necessarily the remote eye's location. */ -/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/camera/ai_eye/remote/xenobio/remote_eye, turf/open/target_turf) +/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/eye/ai_eye/remote/xenobio/remote_eye, turf/open/target_turf) if(!GLOB.cameranet.checkTurfVis(remote_eye.loc)) to_chat(user, span_warning("Target is not near a camera. Cannot proceed.")) return FALSE @@ -169,6 +169,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo stored_slime.forceMove(target_turf) stored_slime.visible_message(span_notice("[stored_slime] warps in!")) stored_slimes -= stored_slime + REMOVE_TRAIT(stored_slime, TRAIT_STASIS, XENOBIO_CONSOLE_TRAIT) ///Places every slime not controlled by a player into the internal storage, respecting its limits ///Returns TRUE to signal it hitting the limit, in case its being called from a loop and we want it to stop @@ -184,6 +185,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo target_slime.visible_message(span_notice("[target_slime] vanishes in a flash of light!")) target_slime.forceMove(src) stored_slimes += target_slime + ADD_TRAIT(target_slime, TRAIT_STASIS, XENOBIO_CONSOLE_TRAIT) return FALSE @@ -226,7 +228,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -243,7 +245,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -262,7 +264,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/living_owner = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = living_owner.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = living_owner.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -280,7 +282,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target var/obj/machinery/monkey_recycler/recycler = xeno_console.connected_recycler @@ -303,7 +305,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -322,7 +324,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -373,7 +375,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!isslime(target_slime)) return - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_slime.loc)) @@ -389,7 +391,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo /obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/basic/slime/target_slime) SIGNAL_HANDLER - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_slime.loc)) @@ -402,7 +404,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo SIGNAL_HANDLER var/mob/living/user_mob = user - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_turf)) @@ -428,7 +430,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo return var/cleanup = FALSE - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_turf)) @@ -447,7 +449,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!ismonkey(target_mob)) return - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.connected_recycler) @@ -464,7 +466,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!isslime(target_slime)) return - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_slime.loc)) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index 3eec11d0b40..fbe528b8703 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -107,8 +107,8 @@ shuttle_port = null return - eyeobj = new /mob/camera/ai_eye/remote/shuttle_docker(null, src) - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + eyeobj = new /mob/eye/ai_eye/remote/shuttle_docker(null, src) + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj the_eye.setDir(shuttle_port.dir) var/turf/origin = locate(shuttle_port.x + x_offset, shuttle_port.y + y_offset, shuttle_port.z) for(var/area/shuttle_area as anything in shuttle_port.shuttle_areas) @@ -128,7 +128,7 @@ /obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user) ..() if(!QDELETED(user) && user.client) - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/list/to_add = list() to_add += the_eye.placement_images to_add += the_eye.placed_images @@ -141,7 +141,7 @@ /obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user) ..() if(!QDELETED(user) && user.client) - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/list/to_remove = list() to_remove += the_eye.placement_images to_remove += the_eye.placed_images @@ -155,7 +155,7 @@ if(designating_target_loc || !current_user) return - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/landing_clear = checkLandingSpot() if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED)) to_chat(current_user, span_warning("Targeting transit location, please wait [DisplayTimeText(designate_time)]...")) @@ -223,7 +223,7 @@ return TRUE /obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot() - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/list/image_cache = the_eye.placement_images the_eye.setDir(turn(the_eye.dir, -90)) for(var/i in 1 to image_cache.len) @@ -239,7 +239,7 @@ checkLandingSpot() /obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot() - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/turf/eyeturf = get_turf(the_eye) if(!eyeturf) return SHUTTLE_DOCKER_BLOCKED @@ -316,22 +316,22 @@ add_jumpable_port(dock.shuttle_id) return TRUE -/mob/camera/ai_eye/remote/shuttle_docker +/mob/eye/ai_eye/remote/shuttle_docker visible_icon = FALSE use_static = FALSE var/list/image/placement_images = list() var/list/image/placed_images = list() -/mob/camera/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin) +/mob/eye/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin) src.origin = origin return ..() -/mob/camera/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE) . = ..() var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin console.checkLandingSpot() -/mob/camera/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user) +/mob/eye/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user) user.set_sight(BLIND|SEE_TURFS) // Pale blue, should look nice I think user.lighting_color_cutoffs = list(30, 40, 50) @@ -346,7 +346,7 @@ /datum/action/innate/shuttledocker_rotate/Activate() if(QDELETED(owner) || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin origin.rotateLandingSpot() @@ -358,7 +358,7 @@ /datum/action/innate/shuttledocker_place/Activate() if(QDELETED(owner) || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin origin.placeLandingSpot(owner) @@ -369,7 +369,7 @@ /datum/action/innate/camera_jump/shuttle_docker/Activate() if(QDELETED(owner) || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin playsound(console, 'sound/machines/terminal/terminal_prompt_deny.ogg', 25, FALSE) diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index f49d67c2aff..debf7236d91 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -288,7 +288,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) for(var/turf/shuttle_turf as anything in zlevel_turfs) for(var/atom/movable/exporting_atom in shuttle_turf) - if(iscameramob(exporting_atom)) + if(iseyemob(exporting_atom)) continue if(exporting_atom.anchored) continue diff --git a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm index 2795efc2b20..8c9c6809a06 100644 --- a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm +++ b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm @@ -5,7 +5,7 @@ */ /datum/action/cooldown/spell/jaunt/bloodcrawl name = "Blood Crawl" - desc = "Allows you to phase in and out of existance via pools of blood." + desc = "Allows you to phase in and out of existence via pools of blood." background_icon_state = "bg_demon" overlay_icon_state = "bg_demon_border" @@ -158,7 +158,7 @@ */ /datum/action/cooldown/spell/jaunt/bloodcrawl/slaughter_demon name = "Voracious Blood Crawl" - desc = "Allows you to phase in and out of existance via pools of blood. If you are dragging someone in critical or dead, \ + desc = "Allows you to phase in and out of existence via pools of blood. If you are dragging someone in critical or dead, \ they will be consumed by you, fully healing you." /// The sound played when someone's consumed. var/consume_sound = 'sound/effects/magic/demon_consume.ogg' @@ -285,7 +285,7 @@ */ /datum/action/cooldown/spell/jaunt/bloodcrawl/slaughter_demon/funny name = "Friendly Blood Crawl" - desc = "Allows you to phase in and out of existance via pools of blood. If you are dragging someone in critical or dead - I mean, \ + desc = "Allows you to phase in and out of existence via pools of blood. If you are dragging someone in critical or dead - I mean, \ sleeping, when entering a blood pool, they will be invited to a party and fully heal you!" consume_sound = 'sound/misc/scary_horn.ogg' diff --git a/code/modules/spells/spell_types/shapeshift/_shape_status.dm b/code/modules/spells/spell_types/shapeshift/_shape_status.dm index 2f8d53eeac2..f8f44817a59 100644 --- a/code/modules/spells/spell_types/shapeshift/_shape_status.dm +++ b/code/modules/spells/spell_types/shapeshift/_shape_status.dm @@ -194,7 +194,7 @@ if(owner?.contents) // Prevent round removal and consuming stuff when losing shapeshift for(var/atom/movable/thing as anything in owner.contents) - if(thing == caster_mob) + if(thing == caster_mob || HAS_TRAIT(thing, TRAIT_NOT_BARFABLE)) continue thing.forceMove(get_turf(owner)) diff --git a/code/modules/spells/spell_types/tower_of_babel.dm b/code/modules/spells/spell_types/tower_of_babel.dm index 618711a8d95..6c7374b4420 100644 --- a/code/modules/spells/spell_types/tower_of_babel.dm +++ b/code/modules/spells/spell_types/tower_of_babel.dm @@ -53,7 +53,7 @@ GLOBAL_DATUM(tower_of_babel, /datum/tower_of_babel) to_chat(to_curse, span_notice("You have a strange feeling for a moment, but then it passes.")) return - to_curse.apply_status_effect(/datum/status_effect/tower_of_babel/magical, INFINITE) + to_curse.apply_status_effect(/datum/status_effect/tower_of_babel/magical, INFINITY) return TRUE /// Mainly so admin triggered tower of babel can be undone diff --git a/code/modules/surgery/organs/autosurgeon.dm b/code/modules/surgery/organs/autosurgeon.dm index 59107666bfd..b4a939e9a95 100644 --- a/code/modules/surgery/organs/autosurgeon.dm +++ b/code/modules/surgery/organs/autosurgeon.dm @@ -8,7 +8,7 @@ w_class = WEIGHT_CLASS_SMALL /// How many times you can use the autosurgeon before it becomes useless - var/uses = INFINITE + var/uses = INFINITY /// What organ will the autosurgeon sub-type will start with. ie, CMO autosurgeon start with a medi-hud. var/starting_organ /// The organ currently loaded in the autosurgeon, ready to be implanted. @@ -40,7 +40,7 @@ to_chat(user, span_alert("[src] already has an implant stored.")) return - if(uses == 0) + if(uses <= 0) to_chat(user, span_alert("[src] is used up and cannot be loaded with more implants.")) return @@ -69,7 +69,7 @@ to_chat(user, span_alert("[src] currently has no implant stored.")) return - if(!uses) + if(uses <= 0) to_chat(user, span_alert("[src] has already been used. The tools are dull and won't reactivate.")) return @@ -96,9 +96,8 @@ playsound(target.loc, 'sound/items/weapons/circsawhit.ogg', 50, vary = TRUE) update_appearance() - if(uses) - uses-- - if(uses == 0) + uses-- + if(uses <= 0) desc = "[initial(desc)] Looks like it's been used up." /obj/item/autosurgeon/attack_self(mob/user)//when the object it used... @@ -129,9 +128,8 @@ stored_organ = null screwtool.play_tool_sound(src) - if (uses) - uses-- - if(!uses) + uses-- + if(uses <= 0) desc = "[initial(desc)] Looks like it's been used up." update_appearance(UPDATE_ICON) return TRUE diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 9a516a8a11d..c90dcd8c8a8 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -145,7 +145,7 @@ if (get_dir(source, backup) == movement_dir || source.loc == backup.loc) return - if (!can_fly(source) || !source.client.intended_direction) + if (!can_fly(source) || !source.client.intended_direction || (source.client.intended_direction & get_dir(source, backup))) return return COMPONENT_PREVENT_SPACEMOVE_HALT diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index ff81209c3e9..4d7074ddefa 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -82,7 +82,7 @@ if (get_dir(source, backup) == movement_dir || source.loc == backup.loc) return - if (!allow_flight() || !source.client.intended_direction) + if (!allow_flight() || !source.client.intended_direction || (source.client.intended_direction & get_dir(source, backup))) return return COMPONENT_PREVENT_SPACEMOVE_HALT diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index 3ff6c5daf65..b4a0ac79d33 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -241,7 +241,7 @@ /obj/item/organ/internal/ears/cybernetic/xray name = "wall-penetrating cybernetic ears" icon_state = "ears-c-u" - desc = "Throguh the power of modern engineering, allows the user to hear speech through walls. The user becomes extra vulnerable to loud noises, however" + desc = "Through the power of modern engineering, allows the user to hear speech through walls. The user becomes extra vulnerable to loud noises, however" // Same sensitivity as felinid ears damage_multiplier = 2 diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm index 1168b6c619a..f9e05f9e95a 100644 --- a/code/modules/tgui/external.dm +++ b/code/modules/tgui/external.dm @@ -42,7 +42,7 @@ * * required user mob The mob interacting with the UI. * - * return list Statuic Data to be sent to the UI. + * return list Static Data to be sent to the UI. */ /datum/proc/ui_static_data(mob/user) return list() diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 3e4a5be979f..b0497ed3b2e 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -136,7 +136,7 @@ /obj/structure/transport/linear/proc/add_item_on_transport(datum/source, atom/movable/new_transport_contents) SIGNAL_HANDLER - var/static/list/blacklisted_types = typecacheof(list(/obj/structure/fluff/tram_rail, /obj/effect/decal/cleanable, /obj/structure/transport/linear, /mob/camera)) + var/static/list/blacklisted_types = typecacheof(list(/obj/structure/fluff/tram_rail, /obj/effect/decal/cleanable, /obj/structure/transport/linear, /mob/eye)) if(is_type_in_typecache(new_transport_contents, blacklisted_types) || new_transport_contents.invisibility == INVISIBILITY_ABSTRACT || HAS_TRAIT(new_transport_contents, TRAIT_UNDERFLOOR)) //prevents the tram from stealing things like landmarks return FALSE if(new_transport_contents in transport_contents) diff --git a/code/modules/unit_tests/README.md b/code/modules/unit_tests/README.md index 9fe97b8b16d..d53a6eb9586 100644 --- a/code/modules/unit_tests/README.md +++ b/code/modules/unit_tests/README.md @@ -39,7 +39,14 @@ Open `code/_compile_options.dm` and uncomment the following line. //#define UNIT_TESTS //If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between ``` -Then, run tgstation.dmb in Dream Daemon. Don't bother trying to connect, you won't need to. You'll be able to see the outputs of all the tests. You'll get to see which tests failed and for what reason. If they all pass, you're set! +There are 3 ways to run unit tests + +- Run tgstation.dmb in Dream Daemon. Don't bother trying to connect, you won't need to. You'll be able to see the outputs of all the tests. You'll get to see which tests failed and for what reason. If they all pass, you're set! + +- Launch game from VS Code. Launch the game as normal & you will see the output of your unit tests in your fancy chat window. This is preferred as you can use the debugger to step through each line of your unit test & can use the games inbuilt debugging tools to further aid in testing + +- Use VS Code Tgstation Test Explorer Extension. This allows you to run tests without launching the game & can also run focused tests(either a single or a selected group) + ## How to think about tests diff --git a/code/modules/unit_tests/focus_only_tests.dm b/code/modules/unit_tests/focus_only_tests.dm index c9bfea88e5e..5530d7418a7 100644 --- a/code/modules/unit_tests/focus_only_tests.dm +++ b/code/modules/unit_tests/focus_only_tests.dm @@ -53,3 +53,6 @@ /// Catches any invalid footstep types set for humans /datum/unit_test/focus_only/humanstep_validity + +/// Checks icon states generated at runtime are valid +/datum/unit_test/focus_only/runtime_icon_states diff --git a/code/modules/unit_tests/heretic_knowledge.dm b/code/modules/unit_tests/heretic_knowledge.dm index f75fff24cee..4154e50285e 100644 --- a/code/modules/unit_tests/heretic_knowledge.dm +++ b/code/modules/unit_tests/heretic_knowledge.dm @@ -1,3 +1,4 @@ + /* * This test checks all heretic knowledge nodes and validates they are setup correctly. * We check that all knowledge is reachable by players (through the research tree) @@ -6,13 +7,13 @@ /datum/unit_test/heretic_knowledge /datum/unit_test/heretic_knowledge/Run() - + if(!GLOB.heretic_research_tree) + GLOB.heretic_research_tree = generate_heretic_research_tree() // First, we get a list of all knowledge types - // EXCLUDING types which have route unset / set to null. - // (Types without a route set are assumed to be abstract or purposefully unreachable) + // EXCLUDING all abstract types var/list/all_possible_knowledge = typesof(/datum/heretic_knowledge) for(var/datum/heretic_knowledge/knowledge_type as anything in all_possible_knowledge) - if(isnull(initial(knowledge_type.route))) + if(initial(knowledge_type.abstract_parent_type) == knowledge_type) all_possible_knowledge -= knowledge_type // Now, let's build a list of all researchable knowledge @@ -22,12 +23,11 @@ var/list/list_to_check = GLOB.heretic_start_knowledge.Copy() var/i = 0 while(i < length(list_to_check)) - var/datum/heretic_knowledge/path_to_create = list_to_check[++i] - if(!ispath(path_to_create)) - TEST_FAIL("Heretic Knowledge: Got a non-heretic knowledge datum (Got: [path_to_create]) in the list knowledges!") - var/datum/heretic_knowledge/instantiated_knowledge = new path_to_create() + var/datum/heretic_knowledge/knowledge = list_to_check[++i] + if(!ispath(knowledge)) + TEST_FAIL("Heretic Knowledge: Got a non-heretic knowledge datum (Got: [knowledge]) in the list knowledges!") // Next knowledge is a list of typepaths. - for(var/datum/heretic_knowledge/next_knowledge as anything in instantiated_knowledge.next_knowledge) + for(var/datum/heretic_knowledge/next_knowledge as anything in GLOB.heretic_research_tree[knowledge][HKT_NEXT]) if(!ispath(next_knowledge)) TEST_FAIL("Heretic Knowledge: [next_knowledge.type] has a [isnull(next_knowledge) ? "null":"invalid path"] in its next_knowledge list!") continue @@ -35,7 +35,6 @@ continue list_to_check += next_knowledge - qdel(instantiated_knowledge) // We now have a list that SHOULD contain all knowledges with a path set (list_to_check). // Let's compare it to our original list (all_possible_knowledge). If they're not identical, @@ -45,48 +44,3 @@ var/list/unreachables = all_possible_knowledge - list_to_check for(var/datum/heretic_knowledge/lost_knowledge as anything in unreachables) TEST_FAIL("Heretic Knowledge: [lost_knowledge] is unreachable by players! Add it to another knowledge's 'next_knowledge' list. If it is purposeful, set its route to 'null'.") - - -/* - * This test checks that all main heretic paths are of the same length. - * - * If any two main paths are not equal length, the test will fail and quit, reporting - * which two paths did not match. Then, whichever is erroneous can be determined manually. - */ -/datum/unit_test/heretic_main_paths - -/datum/unit_test/heretic_main_paths/Run() - // A list of path strings we don't need to check. - var/list/paths_we_dont_check = list(PATH_SIDE, PATH_START) - // An assoc list of [path string] to [number of nodes we found of that path]. - var/list/paths = list() - // The starting knowledge node, we use this to deduce what main paths we have. - var/datum/heretic_knowledge/spell/basic/starter_node = new() - - // Go through and determine what paths exist from our base node. - for(var/datum/heretic_knowledge/possible_path as anything in starter_node.next_knowledge) - paths[initial(possible_path.route)] = 0 - - qdel(starter_node) // Get rid of that starter node, we don't need it anymore. - - // Now go through all the knowledges and record how many of each main path exist. - for(var/datum/heretic_knowledge/knowledge as anything in subtypesof(/datum/heretic_knowledge)) - var/knowledge_route = initial(knowledge.route) - // null (abstract), side paths, and start paths we can skip - if(isnull(knowledge_route) || (knowledge_route in paths_we_dont_check)) - continue - - if(isnull(paths[knowledge_route])) - TEST_FAIL("Heretic Knowledge: An invalid knowledge route ([knowledge_route]) was found on [knowledge].") - continue - - paths[knowledge_route]++ - - // Now all entries in the paths list should have an equal value. - // If any two entries do not match, then one of them is incorrect, and the test fails. - for(var/main_path in paths) - for(var/other_main_path in (paths - main_path)) - TEST_ASSERT(paths[main_path] == paths[other_main_path], \ - "Heretic Knowledge: [main_path] had [paths[main_path]] knowledges, \ - which was not equal to [other_main_path]'s [paths[other_main_path]] knowledges. \ - All main paths should have the same number of knowledges!") diff --git a/code/modules/unit_tests/mob_faction.dm b/code/modules/unit_tests/mob_faction.dm index 554a1adda9d..f5d64918038 100644 --- a/code/modules/unit_tests/mob_faction.dm +++ b/code/modules/unit_tests/mob_faction.dm @@ -8,10 +8,10 @@ /mob/dview, /mob/oranges_ear ) - ignored += typesof(/mob/camera/imaginary_friend) + ignored += typesof(/mob/eye/imaginary_friend) ignored += typesof(/mob/living/silicon/robot/model) - ignored += typesof(/mob/camera/ai_eye/remote/base_construction) - ignored += typesof(/mob/camera/ai_eye/remote/shuttle_docker) + ignored += typesof(/mob/eye/ai_eye/remote/base_construction) + ignored += typesof(/mob/eye/ai_eye/remote/shuttle_docker) for (var/mob_type in typesof(/mob) - ignored) var/mob/mob_instance = allocate(mob_type) if(!islist(mob_instance.faction)) diff --git a/code/modules/unit_tests/status_effect_ticks.dm b/code/modules/unit_tests/status_effect_ticks.dm index 6f3c43c7ada..d60ba187abc 100644 --- a/code/modules/unit_tests/status_effect_ticks.dm +++ b/code/modules/unit_tests/status_effect_ticks.dm @@ -3,21 +3,21 @@ /datum/unit_test/status_effect_ticks/Run() for(var/datum/status_effect/checking as anything in subtypesof(/datum/status_effect)) - var/checking_tick = initial(checking.tick_interval) - if(checking_tick == -1) + var/tick_speed = initial(checking.tick_interval) + if(tick_speed == STATUS_EFFECT_NO_TICK) continue - if(checking_tick == INFINITY) - TEST_FAIL("Status effect [checking] has tick_interval set to INFINITY, this is not how you prevent ticks - use tick_interval = -1 instead.") + if(tick_speed == INFINITY) + TEST_FAIL("Status effect [checking] has tick_interval set to INFINITY, this is not how you prevent ticks - use tick_interval = STATUS_EFFECT_NO_TICK instead.") continue - if(checking_tick == 0) - TEST_FAIL("Status effect [checking] has tick_interval set to 0, this is not how you prevent ticks - use tick_interval = -1 instead.") + if(tick_speed == 0) + TEST_FAIL("Status effect [checking] has tick_interval set to 0, this is not how you prevent ticks - use tick_interval = STATUS_EFFECT_NO_TICK instead.") continue switch(initial(checking.processing_speed)) if(STATUS_EFFECT_FAST_PROCESS) - if(checking_tick < SSfastprocess.wait) - TEST_FAIL("Status effect [checking] has tick_interval set to [checking_tick], which is faster than SSfastprocess can tick ([SSfastprocess.wait]).") + if(tick_speed < SSfastprocess.wait) + TEST_FAIL("Status effect [checking] has tick_interval set to [tick_speed], which is faster than SSfastprocess can tick ([SSfastprocess.wait]).") if(STATUS_EFFECT_NORMAL_PROCESS) - if(checking_tick < SSprocessing.wait) - TEST_FAIL("Status effect [checking] has tick_interval set to [checking_tick], which is faster than SSprocessing can tick ([SSprocessing.wait]).") + if(tick_speed < SSprocessing.wait) + TEST_FAIL("Status effect [checking] has tick_interval set to [tick_speed], which is faster than SSprocessing can tick ([SSprocessing.wait]).") else TEST_FAIL("Invalid processing speed for status effect [checking] : [initial(checking.processing_speed)]") diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 24c51b4a34c..eca29e8d008 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -286,13 +286,13 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) //We have a baseturf limit of 10, adding more than 10 baseturf helpers will kill CI, so here's a future edge case to fix. returnable_list += typesof(/obj/effect/baseturf_helper) //No tauma to pass in - returnable_list += typesof(/mob/camera/imaginary_friend) + returnable_list += typesof(/mob/eye/imaginary_friend) //No heart to give returnable_list += typesof(/obj/structure/ethereal_crystal) //No linked console - returnable_list += typesof(/mob/camera/ai_eye/remote/base_construction) + returnable_list += typesof(/mob/eye/ai_eye/remote/base_construction) //See above - returnable_list += typesof(/mob/camera/ai_eye/remote/shuttle_docker) + returnable_list += typesof(/mob/eye/ai_eye/remote/shuttle_docker) //Hangs a ref post invoke async, which we don't support. Could put a qdeleted check but it feels hacky returnable_list += typesof(/obj/effect/anomaly/grav/high) //See above diff --git a/code/modules/uplink/uplink_items/dangerous.dm b/code/modules/uplink/uplink_items/dangerous.dm index 3feb8dc30ca..0c86d8731e0 100644 --- a/code/modules/uplink/uplink_items/dangerous.dm +++ b/code/modules/uplink/uplink_items/dangerous.dm @@ -37,7 +37,7 @@ pocketed when inactive. Activating it produces a loud, distinctive noise." progression_minimum = 20 MINUTES item = /obj/item/melee/energy/sword/saber - cost = 8 + cost = 6 purchasable_from = ~UPLINK_CLOWN_OPS /datum/uplink_item/dangerous/powerfist diff --git a/code/modules/uplink/uplink_items/device_tools.dm b/code/modules/uplink/uplink_items/device_tools.dm index 36fcc7d1e5f..3fb6b84b750 100644 --- a/code/modules/uplink/uplink_items/device_tools.dm +++ b/code/modules/uplink/uplink_items/device_tools.dm @@ -246,9 +246,9 @@ active gravitational singularities or tesla balls towards it. This will not work when the engine is still \ in containment. Because of its size, it cannot be carried. Ordering this \ sends you a small beacon that will teleport the larger beacon to your location upon activation." - progression_minimum = 30 MINUTES + progression_minimum = 20 MINUTES item = /obj/item/sbeacondrop - cost = 10 + cost = 4 surplus = 0 // not while there isnt one on any station purchasable_from = ~UPLINK_ALL_SYNDIE_OPS diff --git a/code/modules/vehicles/mecha/combat/durand.dm b/code/modules/vehicles/mecha/combat/durand.dm index 0e1ab1302db..da1f7122dd1 100644 --- a/code/modules/vehicles/mecha/combat/durand.dm +++ b/code/modules/vehicles/mecha/combat/durand.dm @@ -35,8 +35,6 @@ . = ..() shield = new /obj/durand_shield(loc, src, plane, layer, dir) RegisterSignal(src, COMSIG_MECHA_ACTION_TRIGGER, PROC_REF(relay)) - RegisterSignal(src, COMSIG_PROJECTILE_PREHIT, PROC_REF(prehit)) - /obj/vehicle/sealed/mecha/durand/Destroy() if(shield) @@ -84,10 +82,12 @@ shield.setDir(dir) //Redirects projectiles to the shield if defense_check decides they should be blocked and returns true. -/obj/vehicle/sealed/mecha/durand/proc/prehit(obj/projectile/source, list/signal_args) - SIGNAL_HANDLER +/obj/vehicle/sealed/mecha/durand/bullet_act(obj/projectile/source, def_zone, mode) if(defense_check(source.loc) && shield) - signal_args[2] = shield + return shield.bullet_act(source, def_zone, mode) + return ..() + + /**Checks if defense mode is enabled, and if the attacker is standing in an area covered by the shield. Expects a turf. Returns true if the attack should be blocked, false if not.*/ diff --git a/code/modules/vehicles/mecha/mecha_ai_interaction.dm b/code/modules/vehicles/mecha/mecha_ai_interaction.dm index 4259dff5c34..6dc1e2307dc 100644 --- a/code/modules/vehicles/mecha/mecha_ai_interaction.dm +++ b/code/modules/vehicles/mecha/mecha_ai_interaction.dm @@ -99,7 +99,7 @@ mecha_flags |= SILICON_PILOT moved_inside(AI) AI.eyeobj?.forceMove(src) - AI.eyeobj?.RegisterSignal(src, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/camera/ai_eye, update_visibility)) + AI.eyeobj?.RegisterSignal(src, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/eye/ai_eye, update_visibility)) AI.controlled_equipment = src AI.remote_control = src add_occupant(AI) diff --git a/code/modules/vehicles/mecha/mecha_movement.dm b/code/modules/vehicles/mecha/mecha_movement.dm index a4b21190a1e..130e0e807b4 100644 --- a/code/modules/vehicles/mecha/mecha_movement.dm +++ b/code/modules/vehicles/mecha/mecha_movement.dm @@ -139,6 +139,8 @@ // if we're not strafing or if we are forced to rotate or if we are holding down the key if(dir != direction && (!strafe || forcerotate || keyheld)) setDir(direction) + if(!(mecha_flags & QUIET_TURNS)) + playsound(src, turnsound, 40, TRUE) if(keyheld || !pivot_step) //If we pivot step, we don't return here so we don't just come to a stop return TRUE @@ -146,10 +148,6 @@ //Otherwise just walk normally . = try_step_multiz(direction) - //dir and olddir are the current direction of the sprite and the old direction of the sprite respectively - if (dir != olddir && !(mecha_flags & QUIET_TURNS)) - playsound(src, turnsound, 40, TRUE) - if(phasing) use_energy(phasing_energy_drain) if(strafe) diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm index cb51a0e8ab7..4f0c72148a1 100644 --- a/code/modules/wiremod/core/component_printer.dm +++ b/code/modules/wiremod/core/component_printer.dm @@ -22,7 +22,7 @@ /obj/machinery/component_printer/Initialize(mapload) . = ..() - materials = AddComponent(/datum/component/remote_materials, mapload, whitelist_typecache = typecacheof(/obj/item/circuit_component)) + materials = AddComponent(/datum/component/remote_materials, mapload) /obj/machinery/component_printer/post_machine_initialize() . = ..() @@ -66,6 +66,19 @@ return current_unlocked_designs -= added_design.build_path +/obj/machinery/component_printer/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + //to allow quick recycling of circuits + if(istype(tool, /obj/item/circuit_component)) + var/amount_inserted = materials.insert_item(tool) + + if(amount_inserted) + to_chat(user, span_notice("[tool] worth [amount_inserted / SHEET_MATERIAL_AMOUNT] sheets of material was consumed by [src]")) + else + to_chat(user, span_warning("[tool] was rejected by [src]")) + + return amount_inserted > 0 ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_FAILURE + + return ..() /obj/machinery/component_printer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/modules/wiremod/core/integrated_circuit.dm b/code/modules/wiremod/core/integrated_circuit.dm index 8afc963b5a3..f3d52653baf 100644 --- a/code/modules/wiremod/core/integrated_circuit.dm +++ b/code/modules/wiremod/core/integrated_circuit.dm @@ -501,11 +501,13 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) return component.disconnect() remove_component(component) + + var/mob/user = ui.user if(component.loc == src) - usr.put_in_hands(component) + user.put_in_hands(component) var/obj/machinery/component_printer/printer = linked_component_printer?.resolve() if (!isnull(printer)) - printer.attackby(component, usr) + printer.base_item_interaction(user, component) . = TRUE if("set_component_coordinates") var/component_id = text2num(params["component_id"]) diff --git a/config/config.txt b/config/config.txt index 75a8a6e7404..637b3006b44 100644 --- a/config/config.txt +++ b/config/config.txt @@ -9,6 +9,7 @@ $include nova/config_nova.txt $include interviews.txt $include lua.txt $include auxtools.txt +$include map_vote.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game # Example usage: diff --git a/html/changelogs/AutoChangeLog-pr-87432.yml b/html/changelogs/AutoChangeLog-pr-87432.yml new file mode 100644 index 00000000000..bf189b82cc3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87432.yml @@ -0,0 +1,4 @@ +author: "Djiq" +delete-after: True +changes: + - refactor: "Refactors heretic tree coode" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87435.yml b/html/changelogs/AutoChangeLog-pr-87435.yml new file mode 100644 index 00000000000..88c4cdbfb57 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87435.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - image: "The animation for being dusted now takes into account your sprite, rather than being a normal nude spaceman" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87489.yml b/html/changelogs/AutoChangeLog-pr-87489.yml new file mode 100644 index 00000000000..8ad3a9a7489 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87489.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "only insulated,nitrile, enhanced retrieval, latex, boxing, improvised gripper gloves have an equip sound" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87533.yml b/html/changelogs/AutoChangeLog-pr-87533.yml new file mode 100644 index 00000000000..1a74f21dd85 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87533.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - qol: "security helmet straps can be loosened to show hair" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87549.yml b/html/changelogs/AutoChangeLog-pr-87549.yml new file mode 100644 index 00000000000..6ec0454b4e5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87549.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - qol: "you can now mitigate motion sickness from screen shake by enabling \"darken screen shake\" in preferences" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87576.yml b/html/changelogs/AutoChangeLog-pr-87576.yml new file mode 100644 index 00000000000..42d0f724720 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87576.yml @@ -0,0 +1,4 @@ +author: "MTandi" +delete-after: True +changes: + - qol: "chem dispenser droplets in UI colored as their reagent" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87634.yml b/html/changelogs/AutoChangeLog-pr-87634.yml new file mode 100644 index 00000000000..8d8e95fdf1f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87634.yml @@ -0,0 +1,4 @@ +author: "carlarctg" +delete-after: True +changes: + - bugfix: "you now snip cuffs with right click to prevent accidental cuts" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87684.yml b/html/changelogs/AutoChangeLog-pr-87684.yml new file mode 100644 index 00000000000..e13ae3fcc6c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87684.yml @@ -0,0 +1,4 @@ +author: "tontyGH" +delete-after: True +changes: + - server: "mob/camera has been renamed to mob/eye, which may break downstreams" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87706.yml b/html/changelogs/AutoChangeLog-pr-87706.yml new file mode 100644 index 00000000000..0265c8918a5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87706.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed fishing rod duping with poly belts and shapeshift spells." + - spellcheck: "Fixed a small typo when examining fishing rods." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87725.yml b/html/changelogs/AutoChangeLog-pr-87725.yml new file mode 100644 index 00000000000..51ddeffd50f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87725.yml @@ -0,0 +1,5 @@ +author: "tontyGH" +delete-after: True +changes: + - bugfix: "Teleporting while buckled to something now works as expected" + - bugfix: "You can buckle to anything if you share the same tile (cause at that point it doesn't matter if there's a wall, right?)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87730.yml b/html/changelogs/AutoChangeLog-pr-87730.yml new file mode 100644 index 00000000000..2450028e1e1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87730.yml @@ -0,0 +1,4 @@ +author: "thegrb93" +delete-after: True +changes: + - bugfix: "Fixes oil slimes making vegetable oil instead of corn oil" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87733.yml b/html/changelogs/AutoChangeLog-pr-87733.yml new file mode 100644 index 00000000000..e558858df26 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87733.yml @@ -0,0 +1,4 @@ +author: "Majkl-J" +delete-after: True +changes: + - bugfix: "Cigarettes can be injected again and have the right amount of nicotine" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87735.yml b/html/changelogs/AutoChangeLog-pr-87735.yml new file mode 100644 index 00000000000..b304247196c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87735.yml @@ -0,0 +1,6 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "mortar pedestal now grinds & juices items that previously could not be processed" + - bugfix: "plumbing grinder won't destroy slime extracts after grinding" + - refactor: "grinding & juicing code has been refactored overall. Please report bugs on github" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87736.yml b/html/changelogs/AutoChangeLog-pr-87736.yml new file mode 100644 index 00000000000..f5aa63c75db --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87736.yml @@ -0,0 +1,5 @@ +author: "Jacquerel" +delete-after: True +changes: + - bugfix: "Living Limbs no longer try to grab things that are under the floor." + - spellcheck: "Living Limb feedback messages now don't redundantly specify that they are flesh arms." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87737.yml b/html/changelogs/AutoChangeLog-pr-87737.yml new file mode 100644 index 00000000000..63f172548d7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87737.yml @@ -0,0 +1,4 @@ +author: "Fikou" +delete-after: True +changes: + - bugfix: "fixes borgs linking to ais in mechs cards and modsuits" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87738.yml b/html/changelogs/AutoChangeLog-pr-87738.yml new file mode 100644 index 00000000000..ded7e062680 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87738.yml @@ -0,0 +1,4 @@ +author: "EnterTheJake" +delete-after: True +changes: + - balance: "The Uplink cost of the energy sword has been lowered from 8 to 6 TC." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87741.yml b/html/changelogs/AutoChangeLog-pr-87741.yml new file mode 100644 index 00000000000..e27aee03b3b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87741.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed wings and jetpacks sometimes preventing you from opening doors" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87743.yml b/html/changelogs/AutoChangeLog-pr-87743.yml new file mode 100644 index 00000000000..f485fa99217 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87743.yml @@ -0,0 +1,11 @@ +author: "carlarctg" +delete-after: True +changes: + - balance: "Significantly buffed the anomalock modules." + - balance: "Anomalock modules can be used with eachother." + - balance: "Antigravity module costs 2 complexity." + - balance: "Teleporter module is thrice as fast at teleporting with a slightly reduced cooldown, but has a much larger power cost." + - code_imp: "Changed how teleporter tracks maximum range to be less painful to the end user." + - refactor: "Refactored LoS checks to be a proc on atom, los_check" + - balance: "Kinesis module's default range has been extended to 8." + - balance: "Kinesis module can drag around people in critical condition or worse." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87744.yml b/html/changelogs/AutoChangeLog-pr-87744.yml new file mode 100644 index 00000000000..c3ac14a47e8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87744.yml @@ -0,0 +1,4 @@ +author: "Xander3359" +delete-after: True +changes: + - bugfix: "fix blade ascension not giving you the ring of blades" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87749.yml b/html/changelogs/AutoChangeLog-pr-87749.yml new file mode 100644 index 00000000000..bf27ebeb931 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87749.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - admin: "Admins can now add/remove TRAIT_EVIL from mobs." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87756.yml b/html/changelogs/AutoChangeLog-pr-87756.yml new file mode 100644 index 00000000000..a5c9f801d18 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87756.yml @@ -0,0 +1,4 @@ +author: "OrionTheFox" +delete-after: True +changes: + - image: "redid most basic drinking glass sprites, and moved several drinks to use the same color system as beakers. Please bug report any incorrect colored drinks or juices!" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87759.yml b/html/changelogs/AutoChangeLog-pr-87759.yml new file mode 100644 index 00000000000..612020fc7e7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87759.yml @@ -0,0 +1,4 @@ +author: "harryob" +delete-after: True +changes: + - bugfix: "the abductor console now correctly loads images of equipment" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87762.yml b/html/changelogs/AutoChangeLog-pr-87762.yml new file mode 100644 index 00000000000..6b64fb9da55 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87762.yml @@ -0,0 +1,4 @@ +author: "Majkl-J" +delete-after: True +changes: + - bugfix: "Losing malf no longer wipes nonmalf AI abilities" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87767.yml b/html/changelogs/AutoChangeLog-pr-87767.yml new file mode 100644 index 00000000000..124d769aab7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87767.yml @@ -0,0 +1,4 @@ +author: "Rhials" +delete-after: True +changes: + - bugfix: "Blob Overmind/Minion/Blobbernaut speech is now logged. Beware." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87772.yml b/html/changelogs/AutoChangeLog-pr-87772.yml new file mode 100644 index 00000000000..7592120eaf2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87772.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "writing something now produces sound" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87773.yml b/html/changelogs/AutoChangeLog-pr-87773.yml new file mode 100644 index 00000000000..beb2605ec27 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87773.yml @@ -0,0 +1,4 @@ +author: "Holoo-1" +delete-after: True +changes: + - bugfix: "fixed roundstart borgs not being synced to ai" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87775.yml b/html/changelogs/AutoChangeLog-pr-87775.yml new file mode 100644 index 00000000000..f66a13a25b2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87775.yml @@ -0,0 +1,5 @@ +author: "necromanceranne" +delete-after: True +changes: + - bugfix: "Abstract nullrod types can no longer be burned or melted with acid." + - bugfix: "Monk staff now properly does not block projectiles, and uses the correct force before being wielded." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87780.yml b/html/changelogs/AutoChangeLog-pr-87780.yml new file mode 100644 index 00000000000..159c4965873 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87780.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "chem master validates selected container in UI so no more href exploits" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87783.yml b/html/changelogs/AutoChangeLog-pr-87783.yml new file mode 100644 index 00000000000..708d7a0314a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87783.yml @@ -0,0 +1,4 @@ +author: "harryob" +delete-after: True +changes: + - bugfix: "you can no longer send newscaster messages to channels you don't have permissions for" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87784.yml b/html/changelogs/AutoChangeLog-pr-87784.yml new file mode 100644 index 00000000000..bbd6cd52933 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87784.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "Super matter sliver dusts fishing hooks & cannot be picked up by them" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87785.yml b/html/changelogs/AutoChangeLog-pr-87785.yml new file mode 100644 index 00000000000..d7bd7a8c940 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87785.yml @@ -0,0 +1,4 @@ +author: "mc-oofert" +delete-after: True +changes: + - bugfix: "Added dehydrator to birdshot kitchen. Surgery theatre now has a surgery tray and surplus prosthetics. An unwired hallway APC is now wired. 1st SM filter is now set to Nitrogen. Chemistry closet in pharmacy now contains extra chemicals to compensate for not having a chemical storage. Atmos air for distro mixer now mixes correctly" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87787.yml b/html/changelogs/AutoChangeLog-pr-87787.yml new file mode 100644 index 00000000000..10e47ce6efb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87787.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - code_imp: "improves code for recycling circuits in component printer" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87790.yml b/html/changelogs/AutoChangeLog-pr-87790.yml new file mode 100644 index 00000000000..8177de3cecf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87790.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "evidence bags have more sounds now" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87793.yml b/html/changelogs/AutoChangeLog-pr-87793.yml new file mode 100644 index 00000000000..258030b1226 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87793.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "Fixed visual glitches when inserting items from an slot other than the hands into evidence bags & other storages that have quick gather mode enabled" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87794.yml b/html/changelogs/AutoChangeLog-pr-87794.yml new file mode 100644 index 00000000000..9fb7e3cc3de --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87794.yml @@ -0,0 +1,5 @@ +author: "carlarctg, Ghommie" +delete-after: True +changes: + - bugfix: "Fixes the randomizer fishing portal not working as intended. Fish from it should now receive random traits." + - bugfix: "Fish names are no longer partially shown in the aquarium UI if they contain a space character." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87795.yml b/html/changelogs/AutoChangeLog-pr-87795.yml new file mode 100644 index 00000000000..98993142b05 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87795.yml @@ -0,0 +1,4 @@ +author: "carlarctg" +delete-after: True +changes: + - bugfix: "fixed random dm modifiers & some life-like reagent reactions" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87798.yml b/html/changelogs/AutoChangeLog-pr-87798.yml new file mode 100644 index 00000000000..0e94f42326a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87798.yml @@ -0,0 +1,4 @@ +author: "Time-Green" +delete-after: True +changes: + - bugfix: "Nooartrium heart damage can no longer be bypassed with non-organic hearts" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87801.yml b/html/changelogs/AutoChangeLog-pr-87801.yml new file mode 100644 index 00000000000..2bffffca980 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87801.yml @@ -0,0 +1,4 @@ +author: "Dawnseer" +delete-after: True +changes: + - spellcheck: "changed throguh to through in a player facing description" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87803.yml b/html/changelogs/AutoChangeLog-pr-87803.yml new file mode 100644 index 00000000000..e9f054ddbc2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87803.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Many years later, projectiles finally can pass through portals - this time without crashing the server." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87806.yml b/html/changelogs/AutoChangeLog-pr-87806.yml new file mode 100644 index 00000000000..8bcd6dd178a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87806.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - bugfix: "Fix using chairs in holodeck to create infinite metal" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87812.yml b/html/changelogs/AutoChangeLog-pr-87812.yml new file mode 100644 index 00000000000..17d9bbfac7c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87812.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed stingbangs using wrong sprites" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87814.yml b/html/changelogs/AutoChangeLog-pr-87814.yml new file mode 100644 index 00000000000..23e490d2aaf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87814.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed detective action palette being invisible" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87816.yml b/html/changelogs/AutoChangeLog-pr-87816.yml new file mode 100644 index 00000000000..cd829eb2934 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87816.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed scanner gates saying both bypass and detection lines when malfunctioning" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87817.yml b/html/changelogs/AutoChangeLog-pr-87817.yml new file mode 100644 index 00000000000..04ed21be2aa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87817.yml @@ -0,0 +1,4 @@ +author: "Dawnseer" +delete-after: True +changes: + - bugfix: "removes the gas mask check for if the gas mask mouth is covered. Now it only checks for filters and other cigs" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87818.yml b/html/changelogs/AutoChangeLog-pr-87818.yml new file mode 100644 index 00000000000..84037f8dcd9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87818.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed special DNA infusions from squids and pufferfish." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87819.yml b/html/changelogs/AutoChangeLog-pr-87819.yml new file mode 100644 index 00000000000..5e7cfe01c00 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87819.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed bombing non-turfs fishing spots not spawning loot correctly." + - balance: "Explosive bombing no longer spawns bottled messages/photos." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87820.yml b/html/changelogs/AutoChangeLog-pr-87820.yml new file mode 100644 index 00000000000..fafad94cc04 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87820.yml @@ -0,0 +1,4 @@ +author: "xPokee, waterpig" +delete-after: True +changes: + - code_imp: "cleaned up beserk.dm" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87821.yml b/html/changelogs/AutoChangeLog-pr-87821.yml new file mode 100644 index 00000000000..39fecbef86d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87821.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "AI-controlled mobs can now cross open space if they won't fall." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87824.yml b/html/changelogs/AutoChangeLog-pr-87824.yml new file mode 100644 index 00000000000..6e323bb9556 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87824.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "holosign creators interact with storage items correctly" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87825.yml b/html/changelogs/AutoChangeLog-pr-87825.yml new file mode 100644 index 00000000000..15258c679ad --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87825.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed fish not being able to reproduce with other fish of the same type without the crossbreeding trait." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87827.yml b/html/changelogs/AutoChangeLog-pr-87827.yml new file mode 100644 index 00000000000..153c3581b47 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87827.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed fish still being hungry when fed if in aquarium with the 'growth and reproduction' option disabled." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87830.yml b/html/changelogs/AutoChangeLog-pr-87830.yml new file mode 100644 index 00000000000..b55d409d98d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87830.yml @@ -0,0 +1,4 @@ +author: "harryob" +delete-after: True +changes: + - bugfix: "ghosts observing ghosts can no longer click on their screen alerts" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87832.yml b/html/changelogs/AutoChangeLog-pr-87832.yml new file mode 100644 index 00000000000..4ebb0e20d35 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87832.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Xenobio console puts sucked up slimes into stasis so they no longer split up inside" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87834.yml b/html/changelogs/AutoChangeLog-pr-87834.yml new file mode 100644 index 00000000000..8a0ada8f2cd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87834.yml @@ -0,0 +1,4 @@ +author: "harryob" +delete-after: True +changes: + - bugfix: "certain tgui inputs no longer require 2 clicks to open" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87835.yml b/html/changelogs/AutoChangeLog-pr-87835.yml new file mode 100644 index 00000000000..ab2ded648b7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87835.yml @@ -0,0 +1,4 @@ +author: "sqnztb" +delete-after: True +changes: + - map: "tramstation tool storage trash no longer routes to the barber shop" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87836.yml b/html/changelogs/AutoChangeLog-pr-87836.yml new file mode 100644 index 00000000000..dcac7fdd74d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87836.yml @@ -0,0 +1,4 @@ +author: "Goat" +delete-after: True +changes: + - qol: "You can now examine labelers to tell how many more labels it has." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87837.yml b/html/changelogs/AutoChangeLog-pr-87837.yml new file mode 100644 index 00000000000..96a44be2edb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87837.yml @@ -0,0 +1,4 @@ +author: "tmyqlfpir" +delete-after: True +changes: + - bugfix: "Airlock shells are properly assigned circuit cameras modules" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87838.yml b/html/changelogs/AutoChangeLog-pr-87838.yml new file mode 100644 index 00000000000..6e8027cf19a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87838.yml @@ -0,0 +1,5 @@ +author: "Neocloudy" +delete-after: True +changes: + - bugfix: "examine tags now use regex for checking if a tag has \"and\" in it" + - spellcheck: "the tooltip for the morbid examine tag doesn't try to use html anymore" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87839.yml b/html/changelogs/AutoChangeLog-pr-87839.yml new file mode 100644 index 00000000000..43aafa3b236 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87839.yml @@ -0,0 +1,4 @@ +author: "Rhials" +delete-after: True +changes: + - qol: "Makes some minor updates to Runtimestation, including event spawn points and a cargo bounty pad." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87840.yml b/html/changelogs/AutoChangeLog-pr-87840.yml new file mode 100644 index 00000000000..2ce6d8d10d9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87840.yml @@ -0,0 +1,4 @@ +author: "EmptyLullaby" +delete-after: True +changes: + - bugfix: "Goliath cloaks are no longer so hard on the calves that they force digitigrade legs to disable." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87841.yml b/html/changelogs/AutoChangeLog-pr-87841.yml new file mode 100644 index 00000000000..83704f38ee5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87841.yml @@ -0,0 +1,4 @@ +author: "Goat" +delete-after: True +changes: + - qol: "Curator console's inventory screen will now update when you change pages or remove items." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87843.yml b/html/changelogs/AutoChangeLog-pr-87843.yml new file mode 100644 index 00000000000..168494cd29b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87843.yml @@ -0,0 +1,4 @@ +author: "Goat" +delete-after: True +changes: + - map: "The library's scanner on Birdshot is now close enough to connect to the computer and was also given a book binder." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87845.yml b/html/changelogs/AutoChangeLog-pr-87845.yml new file mode 100644 index 00000000000..9a9672e7105 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87845.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - bugfix: "Fix missing screentips plasmaman helmets and MOD suit hat stabilizer helmets." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87846.yml b/html/changelogs/AutoChangeLog-pr-87846.yml new file mode 100644 index 00000000000..3423cb647db --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87846.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - bugfix: "Fix broken link to issue manager guide in Github contributor guide" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87847.yml b/html/changelogs/AutoChangeLog-pr-87847.yml new file mode 100644 index 00000000000..b1290b19944 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87847.yml @@ -0,0 +1,5 @@ +author: "Absolucy" +delete-after: True +changes: + - bugfix: "You can no longer crush random unsuspecting people with vendors by ventcrawling while cursed." + - qol: "AFK players don't count as \"watchers\" for cursed stuff." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87848.yml b/html/changelogs/AutoChangeLog-pr-87848.yml new file mode 100644 index 00000000000..5754465ce3e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87848.yml @@ -0,0 +1,4 @@ +author: "Rhials" +delete-after: True +changes: + - qol: "Crayon bounties are less demanding, and require less crayons for payout." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87849.yml b/html/changelogs/AutoChangeLog-pr-87849.yml new file mode 100644 index 00000000000..394c7b39a0d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87849.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - bugfix: "Fix holymelon armor not inheriting magic resistance" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87850.yml b/html/changelogs/AutoChangeLog-pr-87850.yml new file mode 100644 index 00000000000..b8461884086 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87850.yml @@ -0,0 +1,4 @@ +author: "OrionTheFox" +delete-after: True +changes: + - bugfix: "(DeltaStation) Fixed unwired APCs in the Electronic Marketing Den, Abandoned Garden, Security Maintenance, and Private Investigator's Office" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87851.yml b/html/changelogs/AutoChangeLog-pr-87851.yml new file mode 100644 index 00000000000..e2c0c757c4e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87851.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed hat stabilizer ignoring clothing worn_y_offset" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87852.yml b/html/changelogs/AutoChangeLog-pr-87852.yml new file mode 100644 index 00000000000..50ad199495d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87852.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed basic mob performance impact created by the factorio PR" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87853.yml b/html/changelogs/AutoChangeLog-pr-87853.yml new file mode 100644 index 00000000000..8147066ed62 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87853.yml @@ -0,0 +1,4 @@ +author: "mc-oofert" +delete-after: True +changes: + - bugfix: "meatlovers flatbread no longer tastes raw" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87855.yml b/html/changelogs/AutoChangeLog-pr-87855.yml new file mode 100644 index 00000000000..e31cdb3c8d3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87855.yml @@ -0,0 +1,4 @@ +author: "00-Steven" +delete-after: True +changes: + - bugfix: "Fixed auto-reel fishing line item catching logic." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87856.yml b/html/changelogs/AutoChangeLog-pr-87856.yml new file mode 100644 index 00000000000..df597780aa2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87856.yml @@ -0,0 +1,7 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "flatpacker accepts circuitboards with left click" + - bugfix: "rcd can deconstruct tables" + - bugfix: "you can open panels of destructive analyzers with screwdriver right click. Use right click or combat mode with items for default interactions" + - bugfix: "flatpacker & machines with local storage can be RPED'd again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87858.yml b/html/changelogs/AutoChangeLog-pr-87858.yml new file mode 100644 index 00000000000..073a04f7237 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87858.yml @@ -0,0 +1,7 @@ +author: "Melbert" +delete-after: True +changes: + - image: "Speeds up some frames of the dust animation slightly" + - image: "Dust/remains spawned after being dusted are now aligned towards the bottom of the tile" + - image: "Bigger mobs now produce bigger piles of ash" + - image: "Plasmamen now dust into plasma bones" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87862.yml b/html/changelogs/AutoChangeLog-pr-87862.yml new file mode 100644 index 00000000000..68001ac6100 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87862.yml @@ -0,0 +1,4 @@ +author: "carlarctg" +delete-after: True +changes: + - spellcheck: "spellecheck: existence not existance" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87867.yml b/html/changelogs/AutoChangeLog-pr-87867.yml new file mode 100644 index 00000000000..1f0c1f9eefd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87867.yml @@ -0,0 +1,4 @@ +author: "LT3" +delete-after: True +changes: + - bugfix: "Server config will now read the map vote configuration file" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87868.yml b/html/changelogs/AutoChangeLog-pr-87868.yml new file mode 100644 index 00000000000..6b008e7a6ab --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87868.yml @@ -0,0 +1,4 @@ +author: "MTandi" +delete-after: True +changes: + - qol: "Chem dispenser UI droplets now have a shadow to not blend with the background" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87870.yml b/html/changelogs/AutoChangeLog-pr-87870.yml new file mode 100644 index 00000000000..c72aff1a0ed --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87870.yml @@ -0,0 +1,5 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "silo connection on some machines won't time out when changing FPS settings" + - code_imp: "improved attack chain code for silo connection" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87872.yml b/html/changelogs/AutoChangeLog-pr-87872.yml new file mode 100644 index 00000000000..b2752f40caa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87872.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "party popper no longer makes reagent sloshing sounds" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87875.yml b/html/changelogs/AutoChangeLog-pr-87875.yml new file mode 100644 index 00000000000..125cfb45d5f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87875.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "shoes pickup volume is louder now" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87885.yml b/html/changelogs/AutoChangeLog-pr-87885.yml new file mode 100644 index 00000000000..d6582ff3aab --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87885.yml @@ -0,0 +1,4 @@ +author: "Ben10Omintrix" +delete-after: True +changes: + - bugfix: "fixes seedling ai getting stuck when trying to refill water from emptied water tanks" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87886.yml b/html/changelogs/AutoChangeLog-pr-87886.yml new file mode 100644 index 00000000000..56c04b1ca02 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87886.yml @@ -0,0 +1,4 @@ +author: "Absolucy" +delete-after: True +changes: + - refactor: "The ORM, \"ore container\", and order console UIs (produce, mining, bitrunner vendors) now load icons in a more efficient manner." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87887.yml b/html/changelogs/AutoChangeLog-pr-87887.yml new file mode 100644 index 00000000000..5b0a6f175c0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87887.yml @@ -0,0 +1,4 @@ +author: "Absolucy" +delete-after: True +changes: + - bugfix: "Admin-deleting a mob now ghostizes it beforehand, preventing a runtime error." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87891.yml b/html/changelogs/AutoChangeLog-pr-87891.yml new file mode 100644 index 00000000000..43acec07764 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87891.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - balance: "Lower the telecrystal price of the singularity beacon from 10 to 4 and reduce the timer to 20 minutes before it can be purchased." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87895.yml b/html/changelogs/AutoChangeLog-pr-87895.yml new file mode 100644 index 00000000000..7bf21a61dba --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87895.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - qol: "added feedback for cutting mulebot wires" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87896.yml b/html/changelogs/AutoChangeLog-pr-87896.yml new file mode 100644 index 00000000000..a1308fb4a9f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87896.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "sandstone blocks have the correct sound now" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87901.yml b/html/changelogs/AutoChangeLog-pr-87901.yml new file mode 100644 index 00000000000..af44465c11d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87901.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed tenacity effect printing its messages when it shouldn't be, and not removing its' effects when it should've." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87903.yml b/html/changelogs/AutoChangeLog-pr-87903.yml new file mode 100644 index 00000000000..2a11a63c40a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87903.yml @@ -0,0 +1,4 @@ +author: "Majkl-J" +delete-after: True +changes: + - bugfix: "Fixes SSWardrobe stealing a camera from the camera app when on a dummy, causing a harddel" \ No newline at end of file diff --git a/icons/hud/64x16_actions.dmi b/icons/hud/64x16_actions.dmi index 812d888846e..23865a80f03 100644 Binary files a/icons/hud/64x16_actions.dmi and b/icons/hud/64x16_actions.dmi differ diff --git a/icons/mob/dust_animation.dmi b/icons/mob/dust_animation.dmi new file mode 100644 index 00000000000..10d8418a144 Binary files /dev/null and b/icons/mob/dust_animation.dmi differ diff --git a/icons/mob/silicon/cameramob.dmi b/icons/mob/eyemob.dmi similarity index 100% rename from icons/mob/silicon/cameramob.dmi rename to icons/mob/eyemob.dmi diff --git a/icons/mob/human/hair_masks.dmi b/icons/mob/human/hair_masks.dmi index 45ecb761d9a..5dbd4917a87 100644 Binary files a/icons/mob/human/hair_masks.dmi and b/icons/mob/human/hair_masks.dmi differ diff --git a/icons/mob/simple/mob.dmi b/icons/mob/simple/mob.dmi index 142481e08e9..74b90ffd95b 100644 Binary files a/icons/mob/simple/mob.dmi and b/icons/mob/simple/mob.dmi differ diff --git a/icons/obj/drinks/drinks.dmi b/icons/obj/drinks/drinks.dmi index 4b966cb2db2..5566cb09b2f 100644 Binary files a/icons/obj/drinks/drinks.dmi and b/icons/obj/drinks/drinks.dmi differ diff --git a/icons/obj/machines/manufactorio.dmi b/icons/obj/machines/manufactorio.dmi index 31abf6f6a20..58b08e4ab44 100644 Binary files a/icons/obj/machines/manufactorio.dmi and b/icons/obj/machines/manufactorio.dmi differ diff --git a/icons/obj/medical/reagent_fillings.dmi b/icons/obj/medical/reagent_fillings.dmi index 0da57e714a5..163f41641dd 100644 Binary files a/icons/obj/medical/reagent_fillings.dmi and b/icons/obj/medical/reagent_fillings.dmi differ diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/xeno.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/xeno.dm index 3508f7cba29..ded13972015 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/xeno.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/xeno.dm @@ -38,7 +38,6 @@ skinned_type = /obj/item/stack/sheet/animalhide/xeno death_sound = 'sound/mobs/non-humanoids/hiss/hiss6.ogg' gib_anim = "gibbed-a" - dust_anim = "dust-a" /datum/species/xeno/get_default_mutant_bodyparts() return list( diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_arousal/status_effects/ropebunny.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_arousal/status_effects/ropebunny.dm index d90a8ba1645..3abcd2d7a4b 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_arousal/status_effects/ropebunny.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_arousal/status_effects/ropebunny.dm @@ -1,7 +1,7 @@ /datum/status_effect/ropebunny id = "ropebunny" tick_interval = 1 SECONDS - duration = INFINITE + duration = STATUS_EFFECT_PERMANENT alert_type = null /datum/status_effect/ropebunny/on_apply() diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/breast_milk.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/breast_milk.dm index 4dbc0eb0f7d..8a02f309855 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/breast_milk.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/breast_milk.dm @@ -7,6 +7,5 @@ /datum/glass_style/drinking_glass/breast_milk required_drink_type = /datum/reagent/consumable/breast_milk - icon_state = "glass_white" name = "glass of breast milk" desc = "almost like normal milk." diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm index d531df13ac6..0bdd21242a6 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm @@ -7,7 +7,6 @@ /datum/glass_style/drinking_glass/femcum required_drink_type = /datum/reagent/consumable/femcum - icon_state = "glass_white" name = "glass of girlcum" desc = "A strange white liquid... Ew!" @@ -26,7 +25,6 @@ /datum/glass_style/drinking_glass/cum required_drink_type = /datum/reagent/consumable/cum - icon_state = "glass_white" name = "glass of cum" desc = "O-oh, my...~" diff --git a/modular_nova/modules/moretraitoritems/code/autosurgeon_bodypart.dm b/modular_nova/modules/moretraitoritems/code/autosurgeon_bodypart.dm index 0f015937385..d85f3fc8d9e 100644 --- a/modular_nova/modules/moretraitoritems/code/autosurgeon_bodypart.dm +++ b/modular_nova/modules/moretraitoritems/code/autosurgeon_bodypart.dm @@ -45,7 +45,7 @@ playsound(get_turf(H), 'sound/items/weapons/circsawhit.ogg', 50, TRUE) storedbodypart = null name = initial(name) - if(uses != INFINITE) + if(uses != INFINITY) uses-- if(!uses) desc = "[initial(desc)] Looks like it's been used up." @@ -79,7 +79,7 @@ to_chat(user, span_notice("You remove the [storedbodypart] from [src].")) I.play_tool_sound(src) storedbodypart = null - if(uses != INFINITE) + if(uses != INFINITY) uses-- if(!uses) desc = "[initial(desc)] Looks like it's been used up." diff --git a/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm b/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm index e679ca84bff..3dc1a6dffc2 100644 --- a/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm +++ b/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm @@ -126,12 +126,6 @@ name = "Case of Smuggled Fish" desc = "What makes these fish such hot products? We'd have to kill you if we told you." -/datum/market_item/misc/giant_wrench_parts - name = "Comically-Large Wrench Parts" - desc = "They're searching every broadband transmission for the name of this wrench, alright? You're mad if you assemble this thing. Mad, we tell you." - price_min = PAYCHECK_CREW * 4 - price_max = PAYCHECK_CREW * 8 - // TOOLS /datum/market_item/tool/caravan_wrench price_min = PAYCHECK_CREW * 0.5 @@ -215,3 +209,10 @@ /datum/market_item/weapon/fisher price_min = PAYCHECK_CREW * 4 price_max = PAYCHECK_CREW * 8 + +/datum/market_item/weapon/giant_wrench_parts + name = "Comically-Large Wrench Parts" + desc = "They're searching every broadband transmission for the name of this wrench, alright? You're mad if you assemble this thing. Mad, we tell you." + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 + diff --git a/modular_nova/modules/verbs/code/subtle.dm b/modular_nova/modules/verbs/code/subtle.dm index f6873a6e639..c4234c51c7a 100644 --- a/modular_nova/modules/verbs/code/subtle.dm +++ b/modular_nova/modules/verbs/code/subtle.dm @@ -105,7 +105,7 @@ in_view -= GLOB.dead_mob_list in_view.Remove(user) - for(var/mob/camera/ai_eye/ai_eye in in_view) + for(var/mob/eye/ai_eye/ai_eye in in_view) in_view.Remove(ai_eye) var/list/targets = list(SUBTLE_ONE_TILE_TEXT, SUBTLE_SAME_TILE_TEXT) + in_view diff --git a/sound/effects/writing_pen/attribution.txt b/sound/effects/writing_pen/attribution.txt new file mode 100644 index 00000000000..7af5720c2fc --- /dev/null +++ b/sound/effects/writing_pen/attribution.txt @@ -0,0 +1,2 @@ +writing_pen made by sadboysuss +license: CC-BY-SA 3.0 \ No newline at end of file diff --git a/sound/effects/writing_pen/writing_pen1.ogg b/sound/effects/writing_pen/writing_pen1.ogg new file mode 100644 index 00000000000..1041e026e6b Binary files /dev/null and b/sound/effects/writing_pen/writing_pen1.ogg differ diff --git a/sound/effects/writing_pen/writing_pen2.ogg b/sound/effects/writing_pen/writing_pen2.ogg new file mode 100644 index 00000000000..855cf2c852e Binary files /dev/null and b/sound/effects/writing_pen/writing_pen2.ogg differ diff --git a/sound/effects/writing_pen/writing_pen3.ogg b/sound/effects/writing_pen/writing_pen3.ogg new file mode 100644 index 00000000000..2e9362c99db Binary files /dev/null and b/sound/effects/writing_pen/writing_pen3.ogg differ diff --git a/sound/effects/writing_pen/writing_pen4.ogg b/sound/effects/writing_pen/writing_pen4.ogg new file mode 100644 index 00000000000..cbd095ef3f2 Binary files /dev/null and b/sound/effects/writing_pen/writing_pen4.ogg differ diff --git a/sound/effects/writing_pen/writing_pen5.ogg b/sound/effects/writing_pen/writing_pen5.ogg new file mode 100644 index 00000000000..c3382cb1f59 Binary files /dev/null and b/sound/effects/writing_pen/writing_pen5.ogg differ diff --git a/sound/effects/writing_pen/writing_pen6.ogg b/sound/effects/writing_pen/writing_pen6.ogg new file mode 100644 index 00000000000..cffdc2810be Binary files /dev/null and b/sound/effects/writing_pen/writing_pen6.ogg differ diff --git a/sound/effects/writing_pen/writing_pen7.ogg b/sound/effects/writing_pen/writing_pen7.ogg new file mode 100644 index 00000000000..9f753efff68 Binary files /dev/null and b/sound/effects/writing_pen/writing_pen7.ogg differ diff --git a/sound/items/evidence_bag/attribution.txt b/sound/items/evidence_bag/attribution.txt new file mode 100644 index 00000000000..4cb126eb7cb --- /dev/null +++ b/sound/items/evidence_bag/attribution.txt @@ -0,0 +1,2 @@ +evidence_bag sounds made by sadboysuss +license: CC-BY-SA 3.0 \ No newline at end of file diff --git a/sound/items/evidence_bag/evidence_bag_drop.ogg b/sound/items/evidence_bag/evidence_bag_drop.ogg new file mode 100644 index 00000000000..6752ae5aa94 Binary files /dev/null and b/sound/items/evidence_bag/evidence_bag_drop.ogg differ diff --git a/sound/items/evidence_bag/evidence_bag_pickup.ogg b/sound/items/evidence_bag/evidence_bag_pickup.ogg new file mode 100644 index 00000000000..4027d9d0e8e Binary files /dev/null and b/sound/items/evidence_bag/evidence_bag_pickup.ogg differ diff --git a/sound/items/evidence_bag/evidence_bag_unzip.ogg b/sound/items/evidence_bag/evidence_bag_unzip.ogg new file mode 100644 index 00000000000..f30e9159cdb Binary files /dev/null and b/sound/items/evidence_bag/evidence_bag_unzip.ogg differ diff --git a/sound/items/evidence_bag/evidence_bag_zip.ogg b/sound/items/evidence_bag/evidence_bag_zip.ogg new file mode 100644 index 00000000000..6b6c2caba55 Binary files /dev/null and b/sound/items/evidence_bag/evidence_bag_zip.ogg differ diff --git a/sound/items/handling/shoes/sneakers_pickup1.ogg b/sound/items/handling/shoes/sneakers_pickup1.ogg index 9670ec324e3..7d86eaa562f 100644 Binary files a/sound/items/handling/shoes/sneakers_pickup1.ogg and b/sound/items/handling/shoes/sneakers_pickup1.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 5250d92fa51..a6883376a43 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3298,6 +3298,7 @@ #include "code\modules\antagonists\heretic\items\labyrinth_handbook.dm" #include "code\modules\antagonists\heretic\items\madness_mask.dm" #include "code\modules\antagonists\heretic\items\unfathomable_curio.dm" +#include "code\modules\antagonists\heretic\knowledge\_heretic_paths.dm" #include "code\modules\antagonists\heretic\knowledge\ash_lore.dm" #include "code\modules\antagonists\heretic\knowledge\blade_lore.dm" #include "code\modules\antagonists\heretic\knowledge\cosmic_lore.dm" @@ -3893,6 +3894,7 @@ #include "code\modules\client\preferences_menu.dm" #include "code\modules\client\preferences_savefile.dm" #include "code\modules\client\preferences\_preference.dm" +#include "code\modules\client\preferences\accessibility.dm" #include "code\modules\client\preferences\addict.dm" #include "code\modules\client\preferences\admin.dm" #include "code\modules\client\preferences\age.dm" @@ -3907,7 +3909,6 @@ #include "code\modules\client\preferences\broadcast_login_logout.dm" #include "code\modules\client\preferences\chipped.dm" #include "code\modules\client\preferences\clothing.dm" -#include "code\modules\client\preferences\darkened_flash.dm" #include "code\modules\client\preferences\food_allergy.dm" #include "code\modules\client\preferences\fps.dm" #include "code\modules\client\preferences\gender.dm" @@ -4890,7 +4891,6 @@ #include "code\modules\mob\mob_update_icons.dm" #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" -#include "code\modules\mob\camera\camera.dm" #include "code\modules\mob\dead\dead.dm" #include "code\modules\mob\dead\new_player\latejoin_menu.dm" #include "code\modules\mob\dead\new_player\login.dm" @@ -4905,6 +4905,7 @@ #include "code\modules\mob\dead\observer\observer_movement.dm" #include "code\modules\mob\dead\observer\observer_say.dm" #include "code\modules\mob\dead\observer\orbit.dm" +#include "code\modules\mob\eye\eye.dm" #include "code\modules\mob\living\blood.dm" #include "code\modules\mob\living\damage_procs.dm" #include "code\modules\mob\living\death.dm" diff --git a/tgui/packages/tgui/components/DraggableControl.jsx b/tgui/packages/tgui/components/DraggableControl.jsx index bb55287b02a..c7f822ad3ed 100644 --- a/tgui/packages/tgui/components/DraggableControl.jsx +++ b/tgui/packages/tgui/components/DraggableControl.jsx @@ -137,12 +137,11 @@ export class DraggableControl extends Component { } else if (this.inputRef) { const input = this.inputRef.current; input.value = internalValue; - // IE8: Dies when trying to focus a hidden element - // (Error: Object does not support this action) - try { + + setTimeout(() => { input.focus(); input.select(); - } catch {} + }, 0); } }; } diff --git a/tgui/packages/tgui/interfaces/AbductorConsole.jsx b/tgui/packages/tgui/interfaces/AbductorConsole.tsx similarity index 74% rename from tgui/packages/tgui/interfaces/AbductorConsole.jsx rename to tgui/packages/tgui/interfaces/AbductorConsole.tsx index bb2f1dffccf..d8d33053627 100644 --- a/tgui/packages/tgui/interfaces/AbductorConsole.jsx +++ b/tgui/packages/tgui/interfaces/AbductorConsole.tsx @@ -5,10 +5,33 @@ import { Section, Tabs, } from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; import { useBackend, useSharedState } from '../backend'; import { Window } from '../layouts'; -import { GenericUplink } from './Uplink/GenericUplink'; +import { GenericUplink, Item } from './Uplink/GenericUplink'; + +type AbductorConsoleData = { + categories: { name: string; items: ConsoleItem[] }[]; + + compactMode: BooleanLike; + experiment: BooleanLike; + points?: number; + credits?: number; + pad: BooleanLike; + gizmo: BooleanLike; + vest: BooleanLike; + vest_mode?: number; + vest_lock?: BooleanLike; +}; + +type ConsoleItem = { + name: string; + cost: number; + desc: string; + icon: string; + icon_state: string; +}; export const AbductorConsole = (props) => { const [tab, setTab] = useSharedState('tab', 1); @@ -47,15 +70,15 @@ export const AbductorConsole = (props) => { }; const Abductsoft = (props) => { - const { act, data } = useBackend(); + const { act, data } = useBackend(); const { experiment, points, credits, categories } = data; if (!experiment) { return No Experiment Machine Detected; } - const categoriesList = []; - const items = []; + const categoriesList: string[] = []; + const items: Item[] = []; for (let i = 0; i < categories.length; i++) { const category = categories[i]; categoriesList.push(category.name); @@ -67,7 +90,9 @@ const Abductsoft = (props) => { category: category.name, cost: `${item.cost} Credits`, desc: item.desc, - disabled: credits < item.cost, + disabled: (credits || 0) < item.cost, + icon: item.icon, + icon_state: item.icon_state, }); } } @@ -92,7 +117,7 @@ const Abductsoft = (props) => { }; const EmergencyTeleporter = (props) => { - const { act, data } = useBackend(); + const { act, data } = useBackend(); const { pad, gizmo } = data; if (!pad) { @@ -115,10 +140,11 @@ const EmergencyTeleporter = (props) => { @@ -126,7 +152,7 @@ const EmergencyTeleporter = (props) => { }; const VestSettings = (props) => { - const { act, data } = useBackend(); + const { act, data } = useBackend(); const { vest, vest_mode, vest_lock } = data; if (!vest) { @@ -139,25 +165,25 @@ const VestSettings = (props) => { buttons={ } > - diff --git a/tgui/packages/tgui/interfaces/Aquarium.tsx b/tgui/packages/tgui/interfaces/Aquarium.tsx index 4f7eefd1c61..bbdc7532634 100644 --- a/tgui/packages/tgui/interfaces/Aquarium.tsx +++ b/tgui/packages/tgui/interfaces/Aquarium.tsx @@ -116,7 +116,7 @@ const FishInfo = (props) => { ml={1} style={{ fontSize: '13px', fontWeight: 'bold' }} > - {fish.fish_name.toUpperCase()} + {fish.fish_name} 0 ? -4 : 1}> {(fish.fish_health > 0 && ( diff --git a/tgui/packages/tgui/interfaces/ChemDispenser.tsx b/tgui/packages/tgui/interfaces/ChemDispenser.tsx index 401328dc54f..d42db1f273a 100644 --- a/tgui/packages/tgui/interfaces/ChemDispenser.tsx +++ b/tgui/packages/tgui/interfaces/ChemDispenser.tsx @@ -18,6 +18,7 @@ type DispensableReagent = { title: string; id: string; pH: number; + color: string; pHCol: string; }; @@ -43,7 +44,7 @@ export const ChemDispenser = (props) => { const { act, data } = useBackend(); const recording = !!data.recordingRecipe; const { recipeReagents = [], recipes = [], beaker } = data; - const [hasCol, setHasCol] = useState(false); + const [showPhCol, setShowPhCol] = useState(false); const beakerTransferAmounts = beaker ? beaker.transferAmounts : []; const recordedContents = @@ -84,8 +85,8 @@ export const ChemDispenser = (props) => { icon="cog" tooltip="Color code the reagents by pH" tooltipPosition="bottom-start" - selected={hasCol} - onClick={() => setHasCol(!hasCol)} + selected={showPhCol} + onClick={() => setShowPhCol(!showPhCol)} /> } @@ -191,17 +192,15 @@ export const ChemDispenser = (props) => { ))} diff --git a/tgui/packages/tgui/interfaces/Flatpacker.tsx b/tgui/packages/tgui/interfaces/Flatpacker.tsx index 83cac9b7393..a6d88a13a40 100644 --- a/tgui/packages/tgui/interfaces/Flatpacker.tsx +++ b/tgui/packages/tgui/interfaces/Flatpacker.tsx @@ -187,7 +187,7 @@ const CostPreview = (props: CostPreviewProps) => {
- {(material.amount / SHEET_MATERIAL_AMOUNT).toFixed(2)} + x{(material.amount / SHEET_MATERIAL_AMOUNT).toFixed(2)}
diff --git a/tgui/packages/tgui/interfaces/OreContainer.tsx b/tgui/packages/tgui/interfaces/OreContainer.tsx index 261523c6e95..daae93a8edf 100644 --- a/tgui/packages/tgui/interfaces/OreContainer.tsx +++ b/tgui/packages/tgui/interfaces/OreContainer.tsx @@ -2,23 +2,27 @@ import { createSearch, toTitleCase } from 'common/string'; import { useState } from 'react'; import { useBackend } from '../backend'; -import { Button, Flex, Image, Input, Section, Stack } from '../components'; +import { + Button, + DmIcon, + Flex, + Icon, + Input, + Section, + Stack, +} from '../components'; import { Window } from '../layouts'; type Ores = { id: string; name: string; amount: number; -}; - -type Ore_images = { - name: string; icon: string; + icon_state: string; }; type Data = { ores: Ores[]; - ore_images: Ore_images[]; }; export const OreContainer = (props) => { @@ -58,7 +62,13 @@ export const OreContainer = (props) => { - + } + /> @@ -87,30 +97,6 @@ export const OreContainer = (props) => { ); }; -const RetrieveIcon = (props) => { - const { data } = useBackend(); - const { ore_images = [] } = data; - const { ore } = props; - - let icon_display = ore_images.find((icon) => icon.name === ore.name); - - if (!icon_display) { - return null; - } - - return ( - - ); -}; - const Orename = (props) => { const { ore_name } = props; const return_name = ore_name.split(' '); diff --git a/tgui/packages/tgui/interfaces/OreRedemptionMachine.jsx b/tgui/packages/tgui/interfaces/OreRedemptionMachine.jsx index 3bb87d7dce2..b9088f32e0d 100644 --- a/tgui/packages/tgui/interfaces/OreRedemptionMachine.jsx +++ b/tgui/packages/tgui/interfaces/OreRedemptionMachine.jsx @@ -6,8 +6,8 @@ import { BlockQuote, Box, Button, + DmIcon, Icon, - Image, Input, LabeledList, Section, @@ -175,14 +175,7 @@ export const OreRedemptionMachine = (props) => { }; const MaterialRow = (props) => { - const { data } = useBackend(); - const { compact } = props; - const { material_icons } = data; - const { material, onRelease } = props; - - const display = material_icons.find( - (mat_icon) => mat_icon.id === material.id, - ); + const { compact, material, onRelease } = props; const sheet_amounts = Math.floor(material.amount); const print_amount = 5; @@ -192,14 +185,12 @@ const MaterialRow = (props) => { {!compact && ( - } /> )} diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/darkened_flash.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx similarity index 50% rename from tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/darkened_flash.tsx rename to tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx index 3184b43a456..a8a782b7f21 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/darkened_flash.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx @@ -2,10 +2,19 @@ import { CheckboxInput, FeatureToggle } from '../base'; export const darkened_flash: FeatureToggle = { name: 'Enable darkened flashes', - category: 'GAMEPLAY', + category: 'ACCESSIBILITY', description: ` When toggled, being flashed will show a dark screen rather than a bright one. `, component: CheckboxInput, }; + +export const screen_shake_darken: FeatureToggle = { + name: 'Darken screen shake', + category: 'ACCESSIBILITY', + description: ` + When toggled, experiencing screen shake will darken your screen. + `, + component: CheckboxInput, +}; diff --git a/tgui/packages/tgui/interfaces/ProduceConsole.tsx b/tgui/packages/tgui/interfaces/ProduceConsole.tsx index 686b194abea..b13fda8af07 100644 --- a/tgui/packages/tgui/interfaces/ProduceConsole.tsx +++ b/tgui/packages/tgui/interfaces/ProduceConsole.tsx @@ -8,8 +8,8 @@ import { Button, Dimmer, Divider, + DmIcon, Icon, - Image, Input, NumberInput, Section, @@ -26,7 +26,8 @@ type OrderDatum = { cat: string; ref: string; cost: number; - product_icon: string; + icon: string; + icon_state: string; }; type Item = { @@ -127,13 +128,13 @@ const ShoppingTab = (props) => { />{' '} {!condensed && ( - } /> )} diff --git a/tools/Tgstation.DiscordDiscussions/Program.cs b/tools/Tgstation.DiscordDiscussions/Program.cs index 1989ef61450..8766418cfec 100644 --- a/tools/Tgstation.DiscordDiscussions/Program.cs +++ b/tools/Tgstation.DiscordDiscussions/Program.cs @@ -174,7 +174,7 @@ async Task RunAsync(string[] args) var isReopen = Boolean.Parse(args[7]); var joinLink = args.Length > 8 ? args[8] : null; - var prTitle = Environment.GetEnvironmentVariable("GITHUB_PULL_REQUEST_TITLE"); + var prTitle = Environment.GetEnvironmentVariable("GITHUB_PULL_REQUEST_TITLE")!; var gitHubClient = new GitHubClient(new ProductHeaderValue("Tgstation.DiscordDiscussions")) { @@ -214,6 +214,12 @@ async Task RunAsync(string[] args) var prLink = $"https://github.com/{repoOwner}/{repoName}/pull/{prNumber}"; var messageContent = $"#{prNumber} - {prTitle}"; + // thread titles can only be 100 long + if (messageContent.Length > 100) + { + messageContent = $"#{prNumber} - {prTitle[..^(messageContent.Length - 97)]}..."; + } + var channelsClient = serviceProvider.GetRequiredService(); var channelId = new Snowflake(discussionsChannelId); diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index f52e113f285..5e43ac25ab1 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -263,6 +263,8 @@ function tag_pr($payload, $opened) { $tags[] = 'Revert'; if(strpos(strtolower($title), 'removes') !== FALSE) $tags[] = 'Removal'; + if(strpos(strtolower($title), 'unit test') !== FALSE) + $tags[] = 'Unit Tests'; } $remove = array('Test Merge Candidate');