diff --git a/.github/guides/VISUALS.md b/.github/guides/VISUALS.md index 82ee0c6b5d6..9c385ee8765 100644 --- a/.github/guides/VISUALS.md +++ b/.github/guides/VISUALS.md @@ -4,10 +4,10 @@ Welcome to a breakdown of visuals and visual effects in our codebase, and in BYO I will be describing all of the existing systems we use, alongside explaining and providing references to BYOND's ref for each tool. -Note, I will not be covering things that are trivial to understand, and which we don't mess with much. +Note, I will not be covering things that are trivial to understand, and which we don't mess with much. For a complete list of byond ref stuff relevant to this topic, see [here](https://www.byond.com/docs/ref/#/atom/var/appearance). -This is to some extent a collation of the BYOND ref, alongside a description of how we actually use these tools. +This is to some extent a collation of the BYOND ref, alongside a description of how we actually use these tools. My hope is after reading this you'll be able to understand and implement different visual effects in our codebase. Also please see the ref entry on the [renderer](https://www.byond.com/docs/ref/#/{notes}/renderer). @@ -53,10 +53,10 @@ You'll find links to the relevant reference entries at the heading of each entry ## Appearances in BYOND - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/appearance) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/appearance) Everything that is displayed on the map has an appearance variable that describes exactly how it should be rendered. -To be clear, it doesn't contain EVERYTHING, [plane masters](#planes) exist separately and so do many other factors. +To be clear, it doesn't contain EVERYTHING, [plane masters](#planes) exist separately and so do many other factors. But it sets out a sort of recipe of everything that could effect rendering. Appearances have a few quirks that can be helpful or frustrating depending on what you're trying to do. @@ -65,25 +65,27 @@ To start off with, appearances are static. You can't directly edit an appearance The way to edit them most of the time is to just modify the corresponding variable on the thing the appearance represents. -This doesn't mean it's impossible to modify them directly however. While appearances are static, +This doesn't mean it's impossible to modify them directly however. While appearances are static, their cousins mutable appearances [(Ref Entry)](https://www.byond.com/docs/ref/info.html#/mutable_appearance) **are**. -What we can do is create a new mutable appearance, set its appearance to be a copy of the static one (remember all appearance variables are static), +What we can do is create a new mutable appearance, set its appearance to be a copy of the static one (remember all appearance variables are static), edit it, and then set the desired thing's appearance var to the appearance var of the mutable. Somewhat like this ```byond -// NOTE: we do not actually have access to a raw appearance type, so we will often +// NOTE: we do not actually have access to a raw appearance type, so we will often // Lie to the compiler, and pretend we are using a mutable appearance // This lets us access vars as expected. Be careful with it tho -/proc/mutate_icon_state(mutable_appearance/thing) +/proc/mutate_icon_state(mutable_appearance/thing) var/mutable_appearance/temporary_lad = new() temporary_lad.appearance = thing temporary_lad.icon_state += "haha_owned" return temporary_lad.appearance ``` +> **Note:** More then being static, appearances are unique. Only one copy of each set of appearance vars exists, and when you modify any of those vars, the corrosponding appearance variable changes its value to whatever matches the new hash. That's why appearance vars can induce inconsistent cost on modification. + > **Warning:** BYOND has been observed to have issues with appearance corruption, it's something to be weary of when "realizing" appearances in this manner. ## Overlays @@ -91,7 +93,7 @@ Somewhat like this - [Table of Contents](#table-of-contents) - [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/overlays) (Also see [rendering](https://www.byond.com/docs/ref/#/{notes}/renderer)) -Overlays are a list of static [appearances](#appearances-in-byond) that we render on top of ourselves. +Overlays are a list of static [appearances](#appearances-in-byond) that we render on top of ourselves. Said appearances can be edited via the realizing method mentioned above. Their rendering order is determined by [layer](#layers) and [plane](#planes), but conflicts are resolved based off order of appearance inside the list. @@ -104,67 +106,67 @@ It's not significant, but it is there, and something to be aware of. ### Our Implementation -We use overlays as our primary method of overlaying visuals. +We use overlays as our primary method of overlaying visuals. However, since overlays are COPIES of a thing's appearance, ensuring that they can be cleared is semi troublesome. To solve this problem, we manage most overlays using `update_overlays()`. -This proc is called whenever an atom's appearance is updated with `update_appearance()` -(essentially just a way to tell an object to rerender anything static about it, like icon state or name), +This proc is called whenever an atom's appearance is updated with `update_appearance()` +(essentially just a way to tell an object to rerender anything static about it, like icon state or name), which will often call `update_icon()`. `update_icon()` handles querying the object for its desired icon, and also manages its overlays, by calling `update_overlays()`. -Said proc returns a list of things to turn into static appearances, which are then passed into `add_overlay()`, +Said proc returns a list of things to turn into static appearances, which are then passed into `add_overlay()`, which makes them static with `build_appearance_list()` before queuing an overlay compile. -This list of static appearances is then queued inside a list called `managed_overlays` on `/atom`. +This list of static appearances is then queued inside a list called `managed_overlays` on `/atom`. This is so we can clear old overlays out before running an update. -We actually compile queued overlay builds once every tick using a dedicated subsystem. +We actually compile queued overlay builds once every tick using a dedicated subsystem. This is done to avoid adding/removing/adding again to the overlays list in cases like humans where it's mutated a lot. -You can bypass this managed overlays system if you'd like, using `add_overlay()` and `cut_overlay()`, +You can bypass this managed overlays system if you'd like, using `add_overlay()` and `cut_overlay()`, but this is semi dangerous because you don't by default have a way to "clear" the overlay. Be careful of this. ## Visual Contents - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/vis_contents) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/vis_contents) The `vis_contents` list allows you to essentially say "Hey, render this thing ON me". -The definition of "ON" varies significantly with the `vis_flags` value of the *thing* being relayed. -See the ref [here](https://www.byond.com/docs/ref/#/atom/var/vis_flags). +The definition of "ON" varies significantly with the `vis_flags` value of the *thing* being relayed. +See the ref [here](https://www.byond.com/docs/ref/#/atom/var/vis_flags). Some flags of interest: -- `VIS_INHERIT_ID`: This allows you to link the object DIRECTLY to the thing it's drawn on, +- `VIS_INHERIT_ID`: This allows you to link the object DIRECTLY to the thing it's drawn on, so clicking on the `vis_contents`'d object is just like clicking on the thing -- `VIS_INHERIT_PLANE`: We will discuss [planes](#planes) more in future, but we use them to both effect rendering order and apply effects as a group. -This flag changes the plane of any `vis_contents`'d object (while displayed on the source object) to the source's. +- `VIS_INHERIT_PLANE`: We will discuss [planes](#planes) more in future, but we use them to both effect rendering order and apply effects as a group. +This flag changes the plane of any `vis_contents`'d object (while displayed on the source object) to the source's. This is occasionally useful, but should be used with care as it breaks any effects that rely on plane. -Anything inside a `vis_contents` list will have its loc stored in its `vis_locs` variable. +Anything inside a `vis_contents` list will have its loc stored in its `vis_locs` variable. We very rarely use this, primarily just for clearing references from `vis_contents`. -`vis_contents`, unlike `overlays` is a reference, not a copy. So you can update a `vis_contents`'d thing and have it mirror properly. +`vis_contents`, unlike `overlays` is a reference, not a copy. So you can update a `vis_contents`'d thing and have it mirror properly. This is how we do multiz by the by, with uh, some more hell discussed under [multiz](#multiz). -To pay for this additional behavior however, vis_contents has additional cost in maptick. -Because it's not a copy, we need to constantly check if it's changed at all, which leads to cost scaling with player count. +To pay for this additional behavior however, vis_contents has additional cost in maptick. +Because it's not a copy, we need to constantly check if it's changed at all, which leads to cost scaling with player count. Careful how much you use it. ## Images - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/image) +- [Reference Entry](https://www.byond.com/docs/ref/#/image) Images are technically parents of [mutable appearances](#appearances-in-byond). We don't often use them, mostly because we can accomplish their behavior with just MAs. -Images exist both to be used in overlays, and to display things to only select clients on the map. +Images exist both to be used in overlays, and to display things to only select clients on the map. See [/client/var/images](#client-images) > Note: the inheritance between the two is essentially for engine convenience. Don't rely on it. @@ -172,7 +174,7 @@ See [/client/var/images](#client-images) ## Client Images - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/client/var/images) +- [Reference Entry](https://www.byond.com/docs/ref/#/client/var/images) `/client/var/images` is a list of image objects to display to JUST that particular client. @@ -180,35 +182,35 @@ The image objects are displayed at their loc variable, and can be shown to more ### Our Implementation -We use client images in a few ways. Often they will be used just as intended, to modify the view of just one user. +We use client images in a few ways. Often they will be used just as intended, to modify the view of just one user. Think tray scanner or technically ai static. -However, we often want to show a set of images to the same GROUP of people, but in a limited manner. +However, we often want to show a set of images to the same GROUP of people, but in a limited manner. For this, we use the `/datum/atom_hud` (hereafter hud) system. This is different from `/datum/hud`, which I will discuss later. -HUDs are datums that represent categories of images to display to users. +HUDs are datums that represent categories of images to display to users. They are most often global, but can be created on an atom to atom bases in rare cases. They store a list of images to display (sorted by source z level to reduce lag) and a list of clients to display to. -We then mirror this group of images into/out of the client's images list, based on what HUDs they're able to see. +We then mirror this group of images into/out of the client's images list, based on what HUDs they're able to see. This is the pattern we use for things like the medihud, or robot trails. ## View - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/client/var/view) +- [Reference Entry](https://www.byond.com/docs/ref/#/client/var/view) -`/client/var/view` is actually a pretty simple topic, -but I'm gonna take this chance to discuss the other things we do to manage pixel sizing and such since there isn't a better place for it, +`/client/var/view` is actually a pretty simple topic, +but I'm gonna take this chance to discuss the other things we do to manage pixel sizing and such since there isn't a better place for it, and they're handled in the same place by us. Alright then, view. This is pretty simple, but it basically just lets us define the tile bound we want to show to our client. This can either be a number for an X by X square, or a string in the form "XxY" for more control. -We use `/datum/view_data` to manage and track view changes, so zoom effects can work without canceling or being canceled by anything else. +We use `/datum/view_data` to manage and track view changes, so zoom effects can work without canceling or being canceled by anything else. ### Client Rendering Modes @@ -218,29 +220,29 @@ Clients get some choice in literally how they want the game to be rendered to th The two I'm gonna discuss here are `zoom`, and `zoom-mode` mode, both of which are skin params (basically just variables that live on the client) -`zoom` decides how the client wants to display the turfs shown to it. -It can have two types of values. -If it's equal to 0 it will stretch the tiles sent to the client to fix the size of the map-window. -Otherwise, any other numbers will lead to pixels being scaled by some multiple. +`zoom` decides how the client wants to display the turfs shown to it. +It can have two types of values. +If it's equal to 0 it will stretch the tiles sent to the client to fix the size of the map-window. +Otherwise, any other numbers will lead to pixels being scaled by some multiple. This effect can only really result in nice clean edges if you pass in whole numbers which is why most of the constant scaling we give players are whole numbers. -`zoom-mode` controls how a pixel will be up-scaled, if it needs to be. -See the ref for more details, but `normal` is gonna have the sharpest output, `distort` uses nearest neighbor, +`zoom-mode` controls how a pixel will be up-scaled, if it needs to be. +See the ref for more details, but `normal` is gonna have the sharpest output, `distort` uses nearest neighbor, which causes some blur, and `blur` uses bilinear sampling, which causes a LOT of blur. ## Eye - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/client/var/eye) +- [Reference Entry](https://www.byond.com/docs/ref/#/client/var/eye) -`/client/var/eye` is the atom or mob at which our view should be centered. +`/client/var/eye` is the atom or mob at which our view should be centered. Any screen objects we display will show "off" this, as will our actual well eye position. -It is by default `/client/var/mob` but it can be modified. +It is by default `/client/var/mob` but it can be modified. This is how we accomplish ai eyes and ventcrawling, alongside most other effects that involve a player getting "into" something. ## Client Screen - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/HUD) +- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/HUD) Similar to client images but not *quite* the same, we can also insert objects onto our client's literal screen @@ -256,21 +258,21 @@ The classic `screen_loc` format looks something like this (keeping in mind it co The pixel offsets can be discarded as optional, but crucially the x and y values do not NEED to be absolute. -We can use cardinal keywords like `NORTH` to anchor screen objects to the view size of the client (a topic that will be discussed soon). -You can also use directional keywords like `TOP` to anchor to the actual visible map-window, which prevents any accidental out of bounds. -Oh yeah you can use absolute offsets to position screen objects out of the view range, which will cause the map-window to forcefully expand, +We can use cardinal keywords like `NORTH` to anchor screen objects to the view size of the client (a topic that will be discussed soon). +You can also use directional keywords like `TOP` to anchor to the actual visible map-window, which prevents any accidental out of bounds. +Oh yeah you can use absolute offsets to position screen objects out of the view range, which will cause the map-window to forcefully expand, exposing the parts of the map byond uses to ahead of time render border things so moving is smooth. ### Secondary Maps While we're here, this is a bit of a side topic but you can have more then one map-window on a client's screen at once. -This gets into dmf fuckery but you can use [window ids](https://www.byond.com/docs/ref/#/{skin}/param/id) to tell a screen object to render to a secondary map. +This gets into dmf fuckery but you can use [window ids](https://www.byond.com/docs/ref/#/{skin}/param/id) to tell a screen object to render to a secondary map. Useful for creating popup windows and such. ## Blend Mode - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/blend_mode) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/blend_mode) `/atom/var/blend_mode` defines how an atom well, renders onto the map. @@ -280,7 +282,7 @@ This is how we do lighting effects, since the lighting [plane](#planes) can be u ## Appearance Flags - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/appearance_flags) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/appearance_flags) `/atom/var/appearance_flags` is a catch all for toggles that apply to visual elements of an atom. I won't go over all of them, but I will discuss a few. @@ -293,8 +295,8 @@ Flags of interest: ## Gliding - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/gliding) - +- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/gliding) + You may have noticed that moving between tiles is smooth, or at least as close as we can get it. Moving at 0.2 or 10 tiles per second will be smooth. This is because we have control over the speed at which atoms animate between moves. @@ -306,37 +308,37 @@ This is done using `/atom/movable/proc/set_glide_size`, which will inform anythi Glide size is often set in the context of some rate of movement. Either the movement delay of a mob, set in `/client/Move()`, or the delay of a movement subsystem. We use defines to turn delays into pixels per tick. -Client moves will be limited by `DELAY_TO_GLIDE_SIZE` which will allow at most 32 pixels a tick. -Subsystems and other niche uses use `MOVEMENT_ADJUSTED_GLIDE_SIZE`. -We will also occasionally use glide size as a way to force a transition between different movement types, like space-drift into normal walking. +Client moves will be limited by `DELAY_TO_GLIDE_SIZE` which will allow at most 32 pixels a tick. +Subsystems and other niche uses use `MOVEMENT_ADJUSTED_GLIDE_SIZE`. +We will also occasionally use glide size as a way to force a transition between different movement types, like space-drift into normal walking. There's extra cruft here. -> Something you should know: Our gliding system attempts to account for time dilation when setting move rates. +> Something you should know: Our gliding system attempts to account for time dilation when setting move rates. This is done in a very simplistic way however, so a spike in td will lead to jumping around as glide rate is outpaced by mob movement rate. -On that note, it is VERY important that glide rate is the same or near the same as actual move rate. -Otherwise you will get strange jumping and jitter. +On that note, it is VERY important that glide rate is the same or near the same as actual move rate. +Otherwise you will get strange jumping and jitter. This can also lead to stupid shit where people somehow manage to intentionally shorten a movement delay to jump around. Dumb. Related to the above, we are not always able to maintain sync between glide rate and mob move rate. -This is because mob move rate is a function of the initial move delay and a bunch of slowdown/speedup modifiers. -In order to maintain sync we would need to issue a move command the MOMENT a delay is up, and if delays are not cleanly divisible by our tick rate (0.5 deciseconds) this is impossible. +This is because mob move rate is a function of the initial move delay and a bunch of slowdown/speedup modifiers. +In order to maintain sync we would need to issue a move command the MOMENT a delay is up, and if delays are not cleanly divisible by our tick rate (0.5 deciseconds) this is impossible. This is why you'll sometime see a stutter in your step when slowed Just so you know, client movement works off `/client/var/move_delay` which sets the next time an input will be accepted. It's typically glide rate, but is in some cases just 1 tick. ## Sight - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/mob/var/sight) +- [Reference Entry](https://www.byond.com/docs/ref/#/mob/var/sight) `/mob/var/sight` is a set of bitflags that *mostly* set what HAS to render on your screen. Be that mobs, turfs, etc. That said, there is some nuance here so I'ma get into that. -- `SEE_INFRA`: I'll get into this later, but infrared is essentially a copy of BYOND darkness, it's not something we currently use. -- `SEE_BLACKNESS`: This relates heavily to [planes](#planes), essentially typically the "blackness" (that darkness that masks things that you can't see) -is rendered separately, out of our control as "users". +- `SEE_INFRA`: I'll get into this later, but infrared is essentially a copy of BYOND darkness, it's not something we currently use. +- `SEE_BLACKNESS`: This relates heavily to [planes](#planes), essentially typically the "blackness" (that darkness that masks things that you can't see) +is rendered separately, out of our control as "users". However, if the `SEE_BLACKNESS` flag is set, it will instead render on plane 0, the default BYOND plane. -This allows us to capture it, and say, blur it, or redraw it elsewhere. This is in theory very powerful, but not possible with the 'side_map' [map format](https://www.byond.com/docs/ref/#/world/var/map_format) +This allows us to capture it, and say, blur it, or redraw it elsewhere. This is in theory very powerful, but not possible with the 'side_map' [map format](https://www.byond.com/docs/ref/#/world/var/map_format) ## BYOND Lighting @@ -346,14 +348,14 @@ Alongside OUR lighting implementation, which is discussed in with color matrixes It's very basic. Essentially, a tile is either "lit" or it's not. -If a tile is not lit, and it matches some other preconditions, it and all its contents will be hidden from the user, +If a tile is not lit, and it matches some other preconditions, it and all its contents will be hidden from the user, sort of like if there was a wall between them. This hiding uses BYOND darkness, and is thus controllable. I'll use this section to discuss all the little bits that contribute to this behavior ### Luminosity - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/luminosity) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/luminosity) `/atom/var/luminosity` is a variable that lets us inject light into BYOND's lighting system. It's real simple, just a range of tiles that will be lit, respecting sight-lines and such of course. @@ -363,16 +365,16 @@ You can actually force it to use a particular mob's sight to avoid aspects of th ### See in Dark - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/mob/var/see_in_dark) +- [Reference Entry](https://www.byond.com/docs/ref/#/mob/var/see_in_dark) This is why when you stand in darkness you can see yourself, and why you can see a line of objects appear when you use mesons (horrible effect btw). It's quite simple, but worth describing. ### Infrared - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/mob/var/see_infrared) +- [Reference Entry](https://www.byond.com/docs/ref/#/mob/var/see_infrared) -Infrared vision can be thought of as a hidden copy of standard BYOND darkness. +Infrared vision can be thought of as a hidden copy of standard BYOND darkness. It's not something we actually use, but I think you should know about it, because the whole thing is real confusing without context. ## Invisibility @@ -388,16 +390,16 @@ It's also used to hide some more then ghost invisible things, like some timers a ## Layers - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/layer) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/layer) -`/atom/var/layer` is the first bit of logic that decides the order in which things on the map render. -Rendering order depends a LOT on the [map format](https://www.byond.com/docs/ref/#/world/var/map_format), -which I will not get into in this document because it is not yet relevant. -All you really need to know is for our current format, -the objects that appear first in something's contents will draw first, and render lowest. -Think of it like stacking little paper cutouts. +`/atom/var/layer` is the first bit of logic that decides the order in which things on the map render. +Rendering order depends a LOT on the [map format](https://www.byond.com/docs/ref/#/world/var/map_format), +which I will not get into in this document because it is not yet relevant. +All you really need to know is for our current format, +the objects that appear first in something's contents will draw first, and render lowest. +Think of it like stacking little paper cutouts. -Layer has a bit more nuance then just being lowest to highest, tho it's not a lot. +Layer has a bit more nuance then just being lowest to highest, tho it's not a lot. There are a few snowflake layers that can be used to accomplish niche goals, alongside floating layers, which are essentially just any layer that is negative. Floating layers will float "up" the chain of things they're being drawn onto, until they find a real layer. They'll then offset off of that. @@ -406,7 +408,7 @@ This allows us to keep relative layer differences while not needing to make all ## Planes - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/plane) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/plane) Allllright `/atom/var/plane`s. Let's talk about em. @@ -415,16 +417,16 @@ Higher planes will (**normally**) render over lower ones. Very clearcut. Similarly to [layers](#layers), planes also support "floating" with `FLOAT_PLANE`. See above for an explanation of that. -However, they can be used for more complex and... fun things too! +However, they can be used for more complex and... fun things too! If a client has an atom with the `PLANE_MASTER` [appearance flag](#appearance-flags) in their [screen](#client-screen), then rather then being all rendered normally, anything in the client's view is instead first rendered onto the plane master. -This is VERY powerful, because it lets us [hide](https://www.byond.com/docs/ref/#/atom/var/alpha), [color](#color), +This is VERY powerful, because it lets us [hide](https://www.byond.com/docs/ref/#/atom/var/alpha), [color](#color), and [distort](#filters) whole classes of objects, among other things. I cannot emphasize enough how useful this is. It does have some downsides however. Because planes are tied to both grouping and rendering order, there are some effects that require splitting a plane into bits. -It's also possible for some effects, especially things relating to [map format](https://www.byond.com/docs/ref/#/world/var/map_format), +It's also possible for some effects, especially things relating to [map format](https://www.byond.com/docs/ref/#/world/var/map_format), to just be straight up impossible, or conflict with each other. It's dumb, but it's what we've got brother so we're gonna use it like it's a free ticket to the bahamas. @@ -432,15 +434,15 @@ We have a system that allows for arbitrary grouping of plane masters for the pur called `/atom/movable/plane_master_controller`. This is somewhat outmoded by our use of [render relays](#render-targetsource), but it's still valid and occasionally useful. -> Something you should know: Plane masters effect ONLY the map their screen_loc is on. +> Something you should know: Plane masters effect ONLY the map their screen_loc is on. For this reason, we are forced to generate whole copies of the set of plane masters with the proper screen_loc to make subviews look right -> Warning: Planes have some restrictions on valid values. They NEED to be whole integers, and they NEED to have an absolute value of `10000`. +> Warning: Planes have some restrictions on valid values. They NEED to be whole integers, and they NEED to have an absolute value of `10000`. This is to support `FLOAT_PLANE`, which lives out at the very edge of the 32 bit int range. ## Render Target/Source - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/render_target) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/render_target) Render targets are a way of rendering one thing onto another. Not like vis_contents but in a literal sense ONTO. The target object is given a `/atom/var/render_target` value, and anything that wishes to "take" it sets its `/atom/var/render_source` var to match. @@ -475,8 +477,8 @@ This meant the turf below looked as if it was offset, and everything was good. Except not, for 2 reasons. One more annoying then the other. - 1: It looked like dog doo-doo. This pattern destroyed the old planes of everything vis_contents'd, so effects/lighting/dropshadows broke bad. -- 2: I alluded to this earlier, but it totally breaks the `side_map` [map format](https://www.byond.com/docs/ref/#/world/var/map_format) -which I need for a massive resprite I'm helping with. This is because `side_map` changes how rendering order works, +- 2: I alluded to this earlier, but it totally breaks the `side_map` [map format](https://www.byond.com/docs/ref/#/world/var/map_format) +which I need for a massive resprite I'm helping with. This is because `side_map` changes how rendering order works, going off "distance" from the front of the frame. The issue here is it of course needs a way to group things that are even allowed to overlap, so it uses plane. So when you squish everything down onto one plane, this of course breaks horribly and fucks you. @@ -491,7 +493,7 @@ to the openspace plane master one level up. More then doable. SECOND problem. How do we get everything below to "land" on the right plane? The answer to this is depressing but still true. We manually offset every single object on the map's plane based off its "z layer". -This includes any `overlays` or `vis_contents` with a unique plane value. +This includes any `overlays` or `vis_contents` with a unique plane value. Mostly we require anything that sets the plane var to pass in a source of context, like a turf or something that can be used to derive a turf. There are a few edge cases where we need to work in explicitly offsets, but those are much rarer. @@ -500,18 +502,18 @@ This is stupid, but it's makable, and what we do. ## Mouse Opacity - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/mouse_opacity) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/mouse_opacity) `/atom/var/mouse_opacity` tells clients how to treat mousing over the atom in question. A value of 0 means it is completely ignored, no matter what. A value of 1 means it is transparent/opaque based off the alpha of the icon at any particular part. -A value of 2 means it will count as opaque across ALL of the icon-state. All 32x32 (or whatever) of it. +A value of 2 means it will count as opaque across ALL of the icon-state. All 32x32 (or whatever) of it. -We will on occasion use mouse opacity to expand hitboxes, but more often this is done with [vis_contents](#visual-contents), +We will on occasion use mouse opacity to expand hitboxes, but more often this is done with [vis_contents](#visual-contents), or just low alpha pixels on the sprite. -> Note: Mouse opacity will only matter if the atom is being rendered on its own. [Overlays](#overlays)(and [images](#images)) +> Note: Mouse opacity will only matter if the atom is being rendered on its own. [Overlays](#overlays)(and [images](#images)) will NOT work as expected with this. However, you can still have totally transparent overlays. If you render them onto a [plane master](#planes) with the desired mouse opacity value it will work as expected. This is because as a step of the rendering pipeline the overlay is rendered ONTO the plane master, and then the plane @@ -519,10 +521,10 @@ master's effects are applied. ## Filters - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/filters) +- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/filters) Filters are a general purpose system for applying a limited set of shaders to a render. -These shaders run on the client's machine. This has upsides and downsides. +These shaders run on the client's machine. This has upsides and downsides. Upside: Very cheap for the server. Downside: Potentially quite laggy for the client. Take care with these @@ -544,7 +546,7 @@ It'll let you add and tweak *most* of the filters in BYOND. ## Particles - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/particles) +- [Reference Entry](https://www.byond.com/docs/ref/#/{notes}/particles) Particles are a system that allows you to attach "generators" to atoms on the world, and have them spit out little visual effects. This is done by creating a subtype of the `/particles` type, and giving it the values you want. @@ -558,7 +560,7 @@ It'll let you add and tweak the particles attached to that atom. ## Pixel Offsets - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/pixel_x) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/pixel_x) This is a real simple idea and I normally wouldn't mention it, but I have something else I wanna discuss related to it, so I'ma take this chance. @@ -571,7 +573,7 @@ There are two "types" of each direction offset. There's the "real" offset (x/y) Real offsets will change both the visual position (IE: where it renders) and also the positional position (IE: where the renderer thinks they are). Fake offsets only effect visual position. -This doesn't really matter for our current map format, but for anything that takes position into account when layering, like `side_map` or `isometric_map` +This doesn't really matter for our current map format, but for anything that takes position into account when layering, like `side_map` or `isometric_map` it matters a whole ton. It's kinda a hard idea to get across, but I hope you have at least some idea. ## Map Formats @@ -585,10 +587,10 @@ There are 4 types currently. Only 2 that are interesting to us, and one that's n Most of them involve changing how layering works, from the standard [layers](#layers) and [planes](#planes) method. There's a bit more detail here, not gonna go into it, stuff like [underlays](https://www.byond.com/docs/ref/#/atom/var/underlays) drawing under things. See [Understanding The Renderer](https://www.byond.com/docs/ref/#/{notes}/renderer) -> There is very technically more nuance here. +> There is very technically more nuance here. > In default rendering modes, byond will conflict break by using the thing that is highest in the contents list of its location. Or lowest. Don't remember. -### [`TOPDOWN_MAP`](https://www.byond.com/docs/ref/#/{notes}/topdown) +### [`TOPDOWN_MAP`](https://www.byond.com/docs/ref/#/{notes}/topdown) This is the default rendering format. What we used to use. It tells byond to render going off [plane](#planes) first, then [layer](#layers). There's a few edgecases involving big icons, but it's small peanuts. @@ -604,7 +606,7 @@ The idea is the closer to the front of the screen something is, the higher its l `pixel_y` + `y` tell the engine where something "is". `/atom/var/bound_width`, `/atom/var/bound_height` and `/atom/var/bound_x/y` describe how big it is, which lets us in theory control what it tries to layer "against". -I'm not bothering with reference links because they are entirely unrelated. +I'm not bothering with reference links because they are entirely unrelated. An issue that will crop up with this map format is needing to manage the "visual" (how/where it renders) and physical (where it is in game) aspects of position and size. Physical position tells the renderer how to layer things. Visual position and a combination of physical bounds (manually set) and visual bounds (inferred from other aspects of it. Sprite width/height, physical bounds, transforms, filters, etc) tell it what the sprite might be rendering OVER. @@ -645,28 +647,28 @@ One more thing. Big icons are fucked From the byond reference >If you use an icon wider than one tile, the "footprint" of the isometric icon (the actual map tiles it takes up) will always be a square. That is, if your normal tile size is 64 and you want to show a 128x128 icon, the icon is two tiles wide and so it will take up a 2×2-tile area on the map. The height of a big icon is irrelevant--any excess height beyond width/2 is used to show vertical features. To draw this icon properly, other tiles on that same ground will be moved behind it in the drawing order. -> One important warning about using big icons in isometric mode is that you should only do this with dense atoms. If part of a big mob icon covers the same tile as a tall building for instance, the tall building is moved back and it could be partially covered by other turfs that are actually behind it. A mob walking onto a very large non-dense turf icon would experience similar irregularities. +> One important warning about using big icons in isometric mode is that you should only do this with dense atoms. If part of a big mob icon covers the same tile as a tall building for instance, the tall building is moved back and it could be partially covered by other turfs that are actually behind it. A mob walking onto a very large non-dense turf icon would experience similar irregularities. These can cause very annoying flickering. In fact, MUCH of how rendering works causes flickering. This is because we don't decide on a pixel by pixel case, the engine groups sprites up into a sort of rendering stack, unable to split them up. -This combined with us being unable to modify bounds means that if one bit of the view is conflicting. +This combined with us being unable to modify bounds means that if one bit of the view is conflicting. If A wants to be above B and below C, but B wants to be below A and above C, we'll be unable to resolve the rendering properly, leading to flickering depending on other aspects of the layering. This can just sort of spread. Very hard to debug. -### [`ISOMETRIC_MAP`](https://www.byond.com/docs/ref/#/{notes}/isometric) - +### [`ISOMETRIC_MAP`](https://www.byond.com/docs/ref/#/{notes}/isometric) + Isometric mode, renders everything well, isometrically, biased to the north east. This gives the possibility for fake 3d, assuming you get things drawn properly. It will render things in the foreground "last", after things in the background. This is the right way of thinking about it, it's not rendering things above or below, but in a layering order. This is interesting mostly in the context of understanding [side map](#side_map-check-the-main-page-too), but we did actually run an isometric station for april fools once. It was really cursed and flickered like crazy (which causes client lag). Fun as hell though. -The mode essentially overrides the layer/plane layering discussed before, and inserts new rules. -I wish I knew what those rules EXACTLY are, but I'm betting they're similar to [side map's](#side_map-check-the-main-page-too), and lummy's actually told me those. +The mode essentially overrides the layer/plane layering discussed before, and inserts new rules. +I wish I knew what those rules EXACTLY are, but I'm betting they're similar to [side map's](#side_map-check-the-main-page-too), and lummy's actually told me those. Yes this is all rather poorly documented. Similar to sidemap, we take physical position into account when deciding layering. In addition to its height positioning, we also account for width. -So both `pixel_y` and `pixel_x` can effect layering. `pixel_z` handles strictly visual y, and `pixel_w` handles x. +So both `pixel_y` and `pixel_x` can effect layering. `pixel_z` handles strictly visual y, and `pixel_w` handles x. This has similar big icon problems to [sidemap](#side_map-check-the-main-page-too). @@ -677,14 +679,14 @@ it would be automatically broken down into smaller icon states, which you would ## Color - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/color) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/color) `/atom/var/color` is another one like [pixel offsets](#pixel-offsets) where its most common use is really uninteresting, but it has an interesting edge case I think is fun to discuss/important to know. So let's get the base case out of the way shall we? -At base, you can set an atom's color to some `rrggbbaa` string (see [here](https://www.byond.com/docs/ref/#/{{appendix}}/html-colors)). This will shade every pixel on that atom to said color, and override its [`/atom/var/alpha`](https://www.byond.com/docs/ref/#/atom/var/alpha) value. +At base, you can set an atom's color to some `rrggbbaa` string (see [here](https://www.byond.com/docs/ref/#/{{appendix}}/html-colors)). This will shade every pixel on that atom to said color, and override its [`/atom/var/alpha`](https://www.byond.com/docs/ref/#/atom/var/alpha) value. See [appearance flags](#appearance-flags) for how this effect can carry into overlays and such. That's the boring stuff, now the fun shit. @@ -703,7 +705,7 @@ It'll help visualize this process quite well. Play around with it, it's fun. ## Transform - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/transform) +- [Reference Entry](https://www.byond.com/docs/ref/#/atom/var/transform) `/atom/var/transform` allows you to shift, contort, rotate and scale atoms visually. This is done using a matrix, similarly to color matrixes. You will likely never need to use it manually however, since there are @@ -730,17 +732,17 @@ and forget to update this file. ## Animate() - [Table of Contents](#table-of-contents) -- [Reference Entry](https://www.byond.com/docs/ref/#/proc/animate) +- [Reference Entry](https://www.byond.com/docs/ref/#/proc/animate) The animate proc allows us to VISUALLY transition between different values on an appearance on clients, while in actuality setting the values instantly on the servers. This is quite powerful, and lets us do many things, like slow fades, shakes, hell even parallax using matrixes. -It doesn't support everything, and it can be quite temperamental especially if you use things like the flag that makes it work in +It doesn't support everything, and it can be quite temperamental especially if you use things like the flag that makes it work in parallel. It's got a lot of nuance to it, but it's real useful. Works on filters and their variables too, which is AGGRESSIVELY useful. -Lets you give radiation glow a warm pulse, that sort of thing. +Lets you give radiation glow a warm pulse, that sort of thing. ## GAGS - [Table of Contents](#table-of-contents) diff --git a/_maps/deathmatch/ragin_mages.dmm b/_maps/deathmatch/ragin_mages.dmm new file mode 100644 index 00000000000..37939643b72 --- /dev/null +++ b/_maps/deathmatch/ragin_mages.dmm @@ -0,0 +1,1880 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ay" = ( +/obj/structure/railing/corner/end{ + dir = 4 + }, +/obj/machinery/door/airlock/wood, +/obj/structure/railing/corner/end/flip{ + dir = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"aT" = ( +/obj/item/cardboard_cutout/adaptive{ + pixel_y = 14; + pixel_x = 8 + }, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"bb" = ( +/obj/structure/chair/wood/wings{ + dir = 8 + }, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"bg" = ( +/obj/effect/spawner/random/entertainment/arcade, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"bv" = ( +/obj/machinery/power/shuttle_engine/propulsion, +/turf/open/floor/plating/airless, +/area/deathmatch/teleport) +"co" = ( +/obj/structure/table/reinforced, +/obj/item/paper_bin/carbon{ + pixel_y = 12; + pixel_x = 7 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"ct" = ( +/obj/structure/flora/bush/grassy/style_random, +/mob/living/simple_animal/pet/gondola{ + name = "Jommy"; + faction = list("gondola", "Wizard") + }, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"cU" = ( +/obj/structure/chair/wood/wings{ + dir = 1 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"dj" = ( +/obj/machinery/door/airlock/wood, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"ds" = ( +/turf/open/floor/carpet/purple, +/area/deathmatch/teleport) +"ez" = ( +/obj/structure/closet/crate, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"fH" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/machinery/griddle, +/obj/item/food/burger/spell{ + pixel_y = 11; + pixel_x = -3 + }, +/obj/item/stack/medical/ointment{ + pixel_y = -2; + pixel_x = 9 + }, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"fI" = ( +/turf/open/lava, +/area/deathmatch/teleport) +"gn" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"gr" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/structure/chair/wood, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"hg" = ( +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/obj/machinery/door/airlock/wood, +/obj/structure/railing/corner/end{ + dir = 8 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"hk" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 21; + pixel_x = -7 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"hK" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"ig" = ( +/obj/structure/table/wood, +/obj/item/stack/medical/bruise_pack{ + pixel_x = -12 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"iz" = ( +/obj/structure/chair/comfy/brown{ + dir = 1 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"iL" = ( +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"iQ" = ( +/obj/structure/table, +/obj/structure/bedsheetbin{ + pixel_y = 4; + pixel_x = 3 + }, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"iZ" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/structure/sink/directional/west, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"jb" = ( +/obj/machinery/door/airlock/wood, +/obj/structure/railing/corner/end/flip, +/obj/structure/railing/corner/end, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"jg" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/effect/landmark/deathmatch_player_spawn, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"jm" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/mystery_box/wands, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"js" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"jM" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"jV" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/machinery/door/airlock/wood, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"kl" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/machinery/light/floor, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"li" = ( +/obj/structure/table, +/obj/item/extinguisher{ + pixel_x = 7; + pixel_y = -6 + }, +/obj/item/clothing/suit/wizrobe/red{ + pixel_y = 3; + pixel_x = -6 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"lM" = ( +/obj/structure/bed{ + dir = 1 + }, +/obj/item/bedsheet/wiz{ + dir = 1 + }, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"lO" = ( +/obj/structure/closet/crate, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"mu" = ( +/obj/effect/turf_decal/stripes, +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"mV" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/mystery_box/tdome, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"nk" = ( +/obj/item/gun/magic/wand/death, +/obj/structure/window/reinforced/plasma/spawner/directional/east, +/obj/structure/window/reinforced/plasma/spawner/directional/north, +/obj/structure/window/reinforced/plasma/spawner/directional/west, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"nx" = ( +/obj/effect/landmark/deathmatch_player_spawn, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"nQ" = ( +/obj/machinery/door/airlock/wood, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"on" = ( +/obj/structure/table/wood, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"oP" = ( +/obj/structure/destructible/cult/item_dispenser/archives/library, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"pe" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 21; + pixel_x = -7 + }, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"ph" = ( +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"pv" = ( +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"pL" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/obj/structure/mystery_box/wands, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"pV" = ( +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"qx" = ( +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/carpet/purple, +/area/deathmatch/teleport) +"qY" = ( +/obj/structure/closet/crate/bin, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"rj" = ( +/obj/machinery/door/window/right/directional/east, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"rD" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"sf" = ( +/obj/structure/mirror/directional/east, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"tL" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/mob/living/simple_animal/hostile/ooze/gelatinous{ + name = "Jimmy"; + faction = list("slime", "Wizard") + }, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"ue" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/item/food/burger/yellow{ + pixel_x = -11; + pixel_y = 8 + }, +/obj/item/food/burger/red{ + pixel_y = 13; + pixel_x = 6 + }, +/obj/item/food/burger/purple{ + pixel_y = 3 + }, +/obj/structure/table/reinforced, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"ui" = ( +/obj/effect/turf_decal/stripes, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"uz" = ( +/turf/open/floor/iron, +/area/deathmatch/teleport) +"uR" = ( +/obj/item/clothing/shoes/sandal/magic{ + pixel_y = 16 + }, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"vh" = ( +/obj/structure/mystery_box/wands, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"vv" = ( +/obj/vehicle/ridden/scooter/skateboard{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"vR" = ( +/obj/structure/bookcase/random, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"wd" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/structure/mystery_box/wands, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"wl" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 1; + pixel_x = -6 + }, +/turf/open/floor/carpet/purple, +/area/deathmatch/teleport) +"wL" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/machinery/gibber/autogibber, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"xk" = ( +/obj/structure/sink/directional/south, +/obj/structure/mirror/directional/north{ + pixel_y = 36 + }, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"xs" = ( +/obj/structure/flora/bush/grassy/style_random, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"yA" = ( +/obj/structure/chair/wood/wings, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"zN" = ( +/obj/structure/mystery_box/wands, +/obj/structure/sign/poster/contraband/the_big_gas_giant_truth/directional/north, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"zO" = ( +/obj/structure/closet, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Au" = ( +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"AD" = ( +/obj/structure/sign/departments/restroom/directional/west, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Bm" = ( +/obj/effect/landmark/deathmatch_player_spawn, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"Cb" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/structure/table/wood, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"Cj" = ( +/obj/structure/table, +/obj/item/clothing/ears/earmuffs{ + pixel_y = 14; + pixel_x = 4 + }, +/obj/item/toy/gun{ + pixel_y = 2; + pixel_x = -3 + }, +/obj/item/clothing/head/wizard/red{ + pixel_x = 6; + pixel_y = -10 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Cq" = ( +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"CM" = ( +/obj/structure/railing/corner, +/obj/structure/railing/corner{ + dir = 8 + }, +/obj/structure/railing/corner{ + dir = 4 + }, +/obj/structure/railing/corner{ + dir = 1 + }, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"DK" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"DW" = ( +/obj/machinery/computer, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"Eh" = ( +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Fb" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Fm" = ( +/obj/structure/chair/comfy/black{ + dir = 1 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Fv" = ( +/obj/structure/chair/wood/wings{ + dir = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Fx" = ( +/obj/item/target, +/obj/structure/sign/flag/nanotrasen/directional/north, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"FL" = ( +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"Ge" = ( +/obj/item/flashlight/flare{ + pixel_x = -5; + pixel_y = -12 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Gv" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 2; + pixel_x = 5 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"GC" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"GZ" = ( +/obj/structure/curtain, +/obj/machinery/shower/directional/north, +/obj/item/soap/syndie, +/turf/open/floor/noslip, +/area/deathmatch/teleport) +"Hf" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 1; + pixel_x = -6 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Hs" = ( +/turf/template_noop, +/area/template_noop) +"HM" = ( +/obj/structure/rack, +/obj/item/knife/ritual{ + pixel_y = 5 + }, +/obj/item/staff{ + pixel_x = -4; + pixel_y = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"HP" = ( +/obj/structure/chair/comfy/black{ + dir = 1 + }, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"HS" = ( +/obj/structure/table/wood/fancy, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"IE" = ( +/obj/structure/table/wood, +/obj/item/clothing/suit/wizrobe/black{ + pixel_y = 3; + pixel_x = -1 + }, +/obj/item/clothing/head/wizard/black{ + pixel_y = 13; + pixel_x = 6 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"IM" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 2; + pixel_x = 5 + }, +/turf/open/floor/carpet/purple, +/area/deathmatch/teleport) +"Jm" = ( +/turf/closed/wall/mineral/wood, +/area/deathmatch/teleport) +"Jo" = ( +/obj/structure/toilet{ + dir = 4 + }, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"Kr" = ( +/obj/effect/landmark/deathmatch_player_spawn, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"KW" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Le" = ( +/obj/structure/filingcabinet, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Mg" = ( +/obj/machinery/computer, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Nl" = ( +/obj/machinery/power/shuttle_engine/heater{ + resistance_flags = 3 + }, +/obj/structure/window/reinforced/spawner/directional/north{ + resistance_flags = 3 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Nm" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 21; + pixel_x = 6 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Nt" = ( +/obj/item/target{ + pixel_y = 11 + }, +/obj/effect/turf_decal/stripes, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"NW" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Ok" = ( +/obj/machinery/vending/cigarette, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"OD" = ( +/obj/structure/filingcabinet, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"OK" = ( +/obj/item/kirbyplants/organic/plant10{ + pixel_y = 21; + pixel_x = 6 + }, +/turf/open/floor/carpet/red, +/area/deathmatch/teleport) +"PD" = ( +/obj/structure/table/wood, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Qj" = ( +/obj/structure/dresser, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"QH" = ( +/obj/structure/table, +/obj/item/clothing/head/wizard{ + pixel_y = 14; + pixel_x = 4 + }, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"QT" = ( +/obj/structure/mystery_box/wands, +/turf/open/floor/plastic, +/area/deathmatch/teleport) +"RB" = ( +/obj/machinery/vending/snack, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"RI" = ( +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"RT" = ( +/obj/machinery/power/shuttle_engine/heater{ + resistance_flags = 3 + }, +/obj/structure/window/reinforced/spawner/directional/north{ + resistance_flags = 3 + }, +/turf/open/lava, +/area/deathmatch/teleport) +"Sa" = ( +/turf/open/floor/grass, +/area/deathmatch/teleport) +"SK" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"Th" = ( +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/structure/table/reinforced, +/obj/item/food/burger/rat{ + pixel_y = 9; + pixel_x = -2 + }, +/obj/item/food/bun{ + pixel_x = 8; + pixel_y = 2 + }, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/iron, +/area/deathmatch/teleport) +"Vk" = ( +/obj/machinery/door/window/left/directional/east, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"VM" = ( +/obj/structure/table/wood/poker, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Wl" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/light_emitter{ + set_cap = 2; + light_color = "#DEEFFF"; + set_luminosity = 4 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"WX" = ( +/obj/machinery/vending/magivend, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Xv" = ( +/obj/structure/railing{ + layer = 3.1 + }, +/obj/structure/railing{ + layer = 3.1; + dir = 1 + }, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"YP" = ( +/obj/structure/closet/crate/coffin, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"YS" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine/cult, +/area/deathmatch/teleport) +"Zo" = ( +/obj/structure/flora/bush/flowers_pp/style_random, +/turf/open/floor/grass, +/area/deathmatch/teleport) +"ZS" = ( +/obj/structure/railing/corner/end/flip, +/turf/open/floor/iron, +/area/deathmatch/teleport) + +(1,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(2,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(3,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(4,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(5,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Jm +Jm +Jm +Jm +Jm +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(6,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Jm +Jm +vR +lM +Qj +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Hs +Hs +Hs +Hs +"} +(7,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Jm +Jm +vR +ph +ph +ph +Jm +QT +Jo +HS +iQ +GZ +Jm +Fx +uz +ui +Fb +ph +ph +ph +ph +RT +bv +Hs +Hs +Hs +"} +(8,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +gn +PD +iz +ph +ph +ph +dj +FL +FL +Bm +QH +uR +Jm +Fx +pv +Nt +Fb +Kr +ph +Eh +ph +RT +bv +Hs +Hs +Hs +"} +(9,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +gn +ig +ph +Kr +qY +Jm +Jm +Jm +Jm +xk +FL +FL +Jm +Fx +ZS +mu +NW +Wl +Au +Vk +rj +RT +bv +Hs +Hs +Hs +"} +(10,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Jm +HM +ph +Eh +Jm +Jm +qx +wl +Jm +Jm +nQ +Jm +Jm +dj +Jm +Jm +pL +ph +ph +ph +Gv +Jm +Hs +Hs +Hs +Hs +"} +(11,1,1) = {" +Hs +Hs +Hs +gn +gn +gn +Jm +zN +ph +ph +Jm +WX +ds +ds +Hf +Jm +ph +AD +Eh +ph +vR +Jm +Jm +Cj +li +ph +Jm +Jm +Hs +Hs +Hs +Hs +"} +(12,1,1) = {" +Hs +Hs +gn +gn +IE +PD +Jm +oP +ph +ph +dj +ph +ds +ds +ph +dj +ph +ph +ph +ph +ph +vR +Jm +Jm +Jm +ay +Jm +Hs +Hs +Hs +Hs +Hs +"} +(13,1,1) = {" +Hs +Hs +gn +Mg +Fm +Hf +Jm +Jm +sf +Gv +Jm +vR +ds +ds +ph +Jm +Jm +Jm +Jm +Nm +ph +ph +vR +Jm +fI +Xv +Jm +Jm +Hs +Hs +Hs +Hs +"} +(14,1,1) = {" +Hs +Hs +gn +Mg +ph +ph +vh +Jm +Jm +Jm +Jm +vR +ds +ds +ph +Jm +xs +tL +Jm +Jm +ph +ph +vR +Jm +fI +Xv +fI +Jm +Jm +Hs +Hs +Hs +"} +(15,1,1) = {" +Hs +Hs +gn +on +Cq +Cq +Cq +Cq +Cq +Cq +Cq +Cq +ds +ds +Cq +GC +Zo +Sa +xs +Jm +OK +Cq +Cq +Jm +fI +Xv +fI +fI +RT +bv +Hs +Hs +"} +(16,1,1) = {" +Hs +Hs +gn +DW +HP +iL +nx +Cq +Cq +Cq +iL +Cq +ds +ds +Cq +GC +Sa +kl +nk +Jm +nx +iL +Cq +jb +DK +CM +rD +mV +Nl +bv +Hs +Hs +"} +(17,1,1) = {" +Hs +Hs +gn +on +Cq +Cq +Cq +Cq +Cq +Cq +Cq +Cq +ds +ds +Cq +GC +Sa +pV +SK +Jm +pe +Cq +Cq +Jm +fI +Xv +fI +fI +RT +bv +Hs +Hs +"} +(18,1,1) = {" +Hs +Hs +gn +Mg +ph +ph +Ok +Jm +Jm +Jm +Jm +vR +ds +ds +ph +Jm +SK +ct +Jm +Jm +ph +ph +vR +Jm +fI +Xv +fI +Jm +Jm +Hs +Hs +Hs +"} +(19,1,1) = {" +Hs +Hs +gn +Mg +Fm +Gv +Jm +Jm +PD +vh +Jm +vR +ds +ds +ph +Jm +Jm +Jm +Jm +hk +ph +ph +vR +Jm +fI +Xv +Jm +Jm +Hs +Hs +Hs +Hs +"} +(20,1,1) = {" +Hs +Hs +gn +gn +PD +PD +Jm +PD +ph +ph +dj +ph +ds +ds +ph +dj +ph +ph +ph +ph +ph +vR +Jm +Jm +Jm +hg +Jm +Hs +Hs +Hs +Hs +Hs +"} +(21,1,1) = {" +Hs +Hs +Hs +gn +gn +gn +Jm +PD +ph +ph +Jm +RB +ds +ds +Gv +Jm +ph +ph +Eh +ph +vh +Jm +Jm +YS +KW +Ge +Jm +Jm +Hs +Hs +Hs +Hs +"} +(22,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Jm +PD +ph +Eh +Jm +Jm +qx +IM +Jm +Jm +jV +Jm +Jm +dj +Jm +Jm +RI +ph +vR +ph +lO +Jm +Hs +Hs +Hs +Hs +"} +(23,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +gn +zO +ph +Kr +ph +Jm +Jm +Jm +Jm +wL +js +fH +Jm +aT +ph +KW +ph +hK +vR +KW +ez +RT +bv +Hs +Hs +Hs +"} +(24,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +gn +bg +ph +ph +Fv +ph +dj +js +js +jg +js +Th +Jm +jm +Eh +vR +KW +Kr +KW +Eh +vv +RT +bv +Hs +Hs +Hs +"} +(25,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Jm +Jm +ph +yA +VM +cU +Jm +wd +gr +Cb +iZ +ue +Jm +YP +KW +KW +ph +Le +OD +co +jM +RT +bv +Hs +Hs +Hs +"} +(26,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Jm +Jm +ph +bb +Gv +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Jm +Hs +Hs +Hs +Hs +"} +(27,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Jm +Jm +Jm +Jm +Jm +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(28,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(29,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(30,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(31,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} +(32,1,1) = {" +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +Hs +"} diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index eec9705fcf4..ba86d17dc61 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -254,19 +254,6 @@ /obj/structure/table, /turf/open/floor/iron, /area/station/maintenance/starboard/aft) -"agb" = ( -/obj/effect/turf_decal/tile/green{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/structure/chair/office/light{ - dir = 8 - }, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white, -/area/station/medical/virology) "agy" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/components/tank/oxygen{ @@ -2799,12 +2786,6 @@ }, /turf/open/floor/circuit/green, /area/station/science/robotics/mechbay) -"boT" = ( -/obj/effect/turf_decal/bot, -/obj/machinery/light/cold/dim/directional/west, -/obj/machinery/vending/wardrobe/engi_wardrobe, -/turf/open/floor/iron, -/area/station/engineering/main) "boW" = ( /obj/structure/table/glass, /obj/machinery/status_display/ai/directional/south, @@ -10013,6 +9994,22 @@ /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood/tile, /area/station/science/lower) +"erJ" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/table/greyscale, +/obj/item/folder/yellow{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/clothing/glasses/meson, +/obj/item/grenade/chem_grenade/smart_metal_foam{ + pixel_x = -8; + pixel_y = 14 + }, +/turf/open/floor/iron/grimy, +/area/station/engineering/main) "erK" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/thinplating_new, @@ -11507,6 +11504,14 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"eWf" = ( +/obj/structure/closet/cardboard, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/item/airlock_painter, +/turf/open/floor/iron/grimy, +/area/station/engineering/main) "eWj" = ( /obj/machinery/atmospherics/components/unary/thermomachine/heater/on{ dir = 4; @@ -11986,6 +11991,17 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron/cafeteria, /area/station/service/cafeteria) +"fhX" = ( +/obj/structure/table/greyscale, +/obj/item/lightreplacer{ + pixel_y = 7 + }, +/obj/item/lightreplacer{ + pixel_y = 2; + pixel_x = -2 + }, +/turf/open/floor/iron/grimy, +/area/station/engineering/main) "fib" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -19298,13 +19314,6 @@ }, /turf/open/floor/wood, /area/station/engineering/main) -"hGt" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "hGE" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -24920,16 +24929,6 @@ }, /turf/open/floor/iron/dark/small, /area/station/ai_monitored/security/armory) -"jBA" = ( -/obj/structure/cable, -/obj/machinery/power/smes/full, -/obj/machinery/camera/directional/north{ - c_tag = "AI Chamber - SMES"; - network = list("aicore") - }, -/obj/machinery/flasher/directional/north, -/turf/open/floor/circuit/red, -/area/station/ai_monitored/turret_protected/ai) "jBD" = ( /obj/structure/table/wood, /obj/effect/mapping_helpers/broken_floor, @@ -25638,10 +25637,6 @@ "jKU" = ( /turf/closed/wall, /area/station/engineering/atmos/storage/gas) -"jLi" = ( -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/showroomfloor, -/area/station/medical/virology) "jLl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -25705,6 +25700,13 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/iron/smooth_large, /area/station/cargo/warehouse) +"jMq" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white/small, +/area/station/medical/virology) "jMy" = ( /obj/machinery/atmospherics/components/binary/pump/on{ dir = 8; @@ -26989,12 +26991,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"kiQ" = ( -/obj/structure/cable, -/obj/machinery/power/smes/full, -/obj/machinery/status_display/ai/directional/north, -/turf/open/floor/iron/smooth, -/area/station/ai_monitored/turret_protected/aisat/equipment) "kjg" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -28885,6 +28881,13 @@ /obj/effect/turf_decal/trimline/blue/warning, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"kNk" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "kNn" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -31141,18 +31144,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"lwl" = ( -/obj/effect/gibspawner/human, -/obj/structure/table/optable{ - desc = "A cold, hard place for your final rest."; - name = "Morgue Slab" - }, -/mob/living/carbon/human/species/monkey/humand_legged{ - name = "Charles"; - real_name = "Charles" - }, -/turf/open/floor/iron/white/diagonal, -/area/station/maintenance/department/science/xenobiology) "lwn" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/hatch, @@ -33039,14 +33030,6 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) -"lWK" = ( -/obj/structure/closet/cardboard, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/item/airlock_painter, -/turf/open/floor/iron/grimy, -/area/station/engineering/main) "lWQ" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/ticket_machine/directional/north, @@ -35262,13 +35245,6 @@ /obj/machinery/atmospherics/pipe/smart/simple/dark/hidden, /turf/open/floor/iron/grimy, /area/station/tcommsat/server) -"mIa" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white/small, -/area/station/medical/virology) "mIg" = ( /obj/machinery/light/small/directional/west, /turf/open/floor/catwalk_floor/iron_dark, @@ -36955,6 +36931,12 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/iron/textured_half, /area/station/security) +"nki" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/light/cold/dim/directional/west, +/obj/machinery/vending/wardrobe/engi_wardrobe, +/turf/open/floor/iron, +/area/station/engineering/main) "nkl" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -56939,6 +56921,19 @@ "sSB" = ( /turf/open/floor/catwalk_floor, /area/station/engineering/break_room) +"sSF" = ( +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white, +/area/station/medical/virology) "sSK" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -60129,6 +60124,18 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_dark, /area/station/cargo/bitrunning/den) +"tQd" = ( +/obj/effect/gibspawner/human, +/obj/structure/table/optable{ + desc = "A cold, hard place for your final rest."; + name = "Morgue Slab" + }, +/mob/living/carbon/human/species/monkey/humand_legged{ + name = "Charles"; + real_name = "Charles" + }, +/turf/open/floor/iron/white/diagonal, +/area/station/maintenance/department/science/xenobiology) "tQx" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/reagent_dispensers/fueltank, @@ -67782,6 +67789,16 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron/cafeteria, /area/station/service/cafeteria) +"vVd" = ( +/obj/structure/cable, +/obj/machinery/power/smes/full, +/obj/machinery/camera/directional/north{ + c_tag = "AI Chamber - SMES"; + network = list("aicore") + }, +/obj/machinery/flasher/directional/north, +/turf/open/floor/circuit/red, +/area/station/ai_monitored/turret_protected/ai) "vVo" = ( /obj/machinery/light/cold/directional/south, /obj/structure/table/reinforced, @@ -68883,17 +68900,6 @@ }, /turf/open/space/basic, /area/station/engineering/atmos/space_catwalk) -"wlW" = ( -/obj/structure/table/greyscale, -/obj/item/lightreplacer{ - pixel_y = 7 - }, -/obj/item/lightreplacer{ - pixel_y = 2; - pixel_x = -2 - }, -/turf/open/floor/iron/grimy, -/area/station/engineering/main) "wmd" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible/layer2{ @@ -68968,6 +68974,10 @@ }, /turf/open/floor/iron/white, /area/station/security/medical) +"wmT" = ( +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/showroomfloor, +/area/station/medical/virology) "wmV" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -74884,22 +74894,6 @@ }, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den/gaming) -"xMU" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/table/greyscale, -/obj/item/folder/yellow{ - pixel_x = 4; - pixel_y = 4 - }, -/obj/item/clothing/glasses/meson, -/obj/item/grenade/chem_grenade/smart_metal_foam{ - pixel_x = -8; - pixel_y = 14 - }, -/turf/open/floor/iron/grimy, -/area/station/engineering/main) "xMY" = ( /turf/closed/wall/r_wall, /area/station/command/teleporter) @@ -75496,6 +75490,12 @@ /obj/effect/landmark/start/paramedic, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"xTL" = ( +/obj/structure/cable, +/obj/machinery/power/smes/full, +/obj/machinery/status_display/ai/directional/north, +/turf/open/floor/iron/smooth, +/area/station/ai_monitored/turret_protected/aisat/equipment) "xTM" = ( /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ dir = 6 @@ -91992,7 +91992,7 @@ dgV sHH rQi rPV -boT +nki uOk nmH sHO @@ -92257,7 +92257,7 @@ dgm wIu oHO sDo -wlW +fhX lsd jJu kya @@ -92768,11 +92768,11 @@ rmM btV lMl ayR -xMU +erJ vDg euP all -lWK +eWf eIx kWg bNq @@ -103045,7 +103045,7 @@ aJq yjV fpY uTA -jBA +vVd xTV dua gnA @@ -104086,7 +104086,7 @@ wct hJp wct gOm -kiQ +xTL eFe eYk xvT @@ -106247,7 +106247,7 @@ tRc tRc tRc tRc -hGt +kNk dHT sSQ sSQ @@ -107022,7 +107022,7 @@ bUv cSk gLb nlS -mIa +jMq gpM sSQ hrF @@ -108560,12 +108560,12 @@ jrk gIF wYA bpS -jLi +wmT nYk vVP xAA hgf -agb +sSF uGj wgL oiA @@ -113421,7 +113421,7 @@ dDB blb dDB ldq -lwl +tQd vXn ldq ldq diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index d97755766cb..3d1f3a212d7 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -1144,14 +1144,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/engineering/gravity_generator) -"anU" = ( -/obj/structure/sign/warning/secure_area/directional/south, -/obj/effect/turf_decal/trimline/purple/filled/line{ - dir = 10 - }, -/obj/item/kirbyplants/organic/plant10, -/turf/open/floor/iron/white, -/area/station/science/research) "anV" = ( /obj/effect/landmark/start/hangover/closet, /obj/structure/closet/firecloset, @@ -1415,20 +1407,6 @@ /obj/item/pillow/random, /turf/open/floor/wood, /area/station/commons/dorms) -"aqU" = ( -/obj/machinery/light/directional/west, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/effect/turf_decal/bot/left, -/obj/structure/sign/nanotrasen{ - pixel_x = -32 - }, -/obj/machinery/modular_computer/preset/cargochat/science{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/science/research) "aqW" = ( /obj/structure/table/reinforced, /obj/machinery/newscaster/directional/north, @@ -2379,18 +2357,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) -"aCA" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Research Division"; - name = "Research Division Fax Machine"; - pixel_x = 1 - }, -/turf/open/floor/iron, -/area/station/science/research) "aCJ" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -2570,6 +2536,14 @@ /obj/structure/grille/broken, /turf/open/space, /area/space/nearstation) +"aFp" = ( +/obj/structure/sign/warning/secure_area/directional/south, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 10 + }, +/obj/item/kirbyplants/organic/plant10, +/turf/open/floor/iron/white, +/area/station/science/research) "aFv" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -2914,14 +2888,6 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"aJj" = ( -/obj/machinery/airalarm/directional/west, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/machinery/recharge_station, -/turf/open/floor/iron, -/area/station/science/research) "aJu" = ( /obj/structure/cable, /obj/machinery/power/smes/engineering, @@ -3773,6 +3739,15 @@ }, /turf/open/space/basic, /area/space/nearstation) +"aUZ" = ( +/obj/machinery/airalarm/directional/north, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Service Hallway"; + name = "Service Fax Machine" + }, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "aVo" = ( /obj/machinery/computer/security/hos{ dir = 1 @@ -6501,9 +6476,6 @@ }, /turf/open/floor/plating, /area/station/security/prison) -"bDx" = ( -/turf/open/floor/iron, -/area/station/security/office) "bDy" = ( /obj/machinery/camera/directional/north{ c_tag = "Chapel - Confessional"; @@ -7066,13 +7038,6 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron, /area/station/engineering/atmos/project) -"bJi" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/service) "bJs" = ( /obj/structure/table/reinforced, /obj/item/stack/sheet/iron{ @@ -8840,16 +8805,6 @@ "cfu" = ( /turf/open/floor/circuit/green, /area/station/ai_monitored/turret_protected/ai_upload) -"cfx" = ( -/obj/structure/plaque/static_plaque/golden{ - pixel_y = -32 - }, -/obj/structure/reagent_dispensers/water_cooler, -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/security/office) "cfy" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -8988,6 +8943,13 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron, /area/station/security/checkpoint/engineering) +"chv" = ( +/obj/structure/cable, +/obj/machinery/power/smes/full, +/obj/effect/turf_decal/bot, +/obj/item/radio/intercom/directional/west, +/turf/open/floor/iron, +/area/station/engineering/gravity_generator) "chF" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -9329,6 +9291,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/visible, /turf/open/floor/iron/dark/corner, /area/station/maintenance/disposal/incinerator) +"clB" = ( +/obj/structure/table/glass, +/obj/machinery/computer/records/medical/laptop, +/obj/item/toy/figure/virologist, +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/iron/white, +/area/station/medical/virology) "clE" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/maintenance_hatch{ @@ -10586,12 +10558,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel/storage) -"cBB" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/service) "cBC" = ( /obj/structure/table/reinforced, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -11264,16 +11230,6 @@ }, /turf/open/floor/iron/white/corner, /area/station/hallway/secondary/exit/departure_lounge) -"cJQ" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 8 - }, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/item/kirbyplants/random, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/station/medical/storage) "cJX" = ( /obj/structure/table/reinforced, /obj/machinery/status_display/evac/directional/west, @@ -12168,13 +12124,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/central) -"cVD" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/item/radio/intercom/directional/north, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/service) "cVN" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -17175,6 +17124,17 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/qm) +"ekF" = ( +/obj/structure/sign/poster/official/random/directional/south, +/obj/machinery/light/directional/south, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron, +/area/station/engineering/storage_shared) "ekM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -18240,6 +18200,15 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"eyl" = ( +/obj/machinery/firealarm/directional/east, +/obj/effect/turf_decal/trimline/purple/filled/corner{ + dir = 8 + }, +/obj/machinery/airalarm/directional/south, +/obj/machinery/photocopier, +/turf/open/floor/iron/white, +/area/station/science/research) "eyr" = ( /obj/item/kirbyplants/random, /obj/machinery/power/apc/auto_name/directional/north, @@ -18981,28 +18950,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/abandoned_gambling_den/gaming) -"eIu" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/machinery/door/poddoor/preopen{ - id = "hopblast"; - name = "HoP Blast Door" - }, -/obj/machinery/door/window/brigdoor/left/directional/east{ - name = "Access Desk"; - req_access = list("hop") - }, -/obj/machinery/door/window/right/directional/west{ - name = "Access Queue" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/structure/desk_bell{ - pixel_x = 7 - }, -/turf/open/floor/iron, -/area/station/command/heads_quarters/hop) "eIy" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -20757,6 +20704,13 @@ }, /turf/open/floor/wood/large, /area/station/service/theater) +"fes" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/security/office) "fez" = ( /obj/effect/landmark/start/hangover, /obj/effect/turf_decal/siding/wood/corner, @@ -22781,6 +22735,18 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den) +"fEV" = ( +/obj/structure/sign/poster/official/moth_epi/directional/west, +/obj/effect/turf_decal/bot, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/medical/storage) "fFb" = ( /obj/structure/table, /obj/effect/spawner/random/entertainment/drugs{ @@ -24068,6 +24034,13 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"fWB" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/service) "fWH" = ( /obj/effect/turf_decal/trimline/blue/filled/corner, /turf/open/floor/iron/white, @@ -24546,6 +24519,14 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics) +"gch" = ( +/obj/structure/table, +/obj/item/clipboard, +/obj/item/stack/package_wrap, +/obj/item/hand_labeler, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "gci" = ( /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/shutters/window/preopen{ @@ -26257,6 +26238,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/hop) +"guZ" = ( +/obj/machinery/light/small/directional/west, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/photobooth/security, +/turf/open/floor/iron/dark, +/area/station/security/execution/transfer) "gvf" = ( /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/lattice, @@ -27861,18 +27848,6 @@ /obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron, /area/station/security/prison) -"gPH" = ( -/obj/structure/sign/poster/official/moth_epi/directional/west, -/obj/effect/turf_decal/bot, -/obj/structure/disposalpipe/trunk{ - dir = 1 - }, -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/medical/storage) "gPO" = ( /obj/structure/table/reinforced, /obj/item/flashlight/lamp/green, @@ -29294,11 +29269,6 @@ /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/floor/iron, /area/station/medical/pharmacy) -"hjH" = ( -/obj/item/radio/intercom/directional/north, -/obj/machinery/photocopier, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "hjJ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -29398,14 +29368,6 @@ dir = 1 }, /area/station/science/ordnance/storage) -"hkZ" = ( -/obj/structure/sign/warning/secure_area/directional/south, -/obj/effect/turf_decal/trimline/purple/filled/line{ - dir = 6 - }, -/obj/item/kirbyplants/organic/plant10, -/turf/open/floor/iron/white, -/area/station/science/research) "hlj" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/holopad, @@ -30815,6 +30777,16 @@ /obj/effect/mapping_helpers/airlock/access/all/service/kitchen, /turf/open/floor/iron/freezer, /area/station/service/kitchen/coldroom) +"hFQ" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 8 + }, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/item/kirbyplants/random, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron, +/area/station/medical/storage) "hFS" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -31546,6 +31518,18 @@ }, /turf/open/floor/iron, /area/station/maintenance/department/security) +"hPH" = ( +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/tile/neutral/full, +/turf/open/floor/iron/large, +/area/station/medical/virology) "hPJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ dir = 8 @@ -31696,15 +31680,6 @@ /obj/effect/turf_decal/tile/dark_blue/fourcorners, /turf/open/floor/iron, /area/station/commons/dorms/laundry) -"hRU" = ( -/obj/effect/turf_decal/bot, -/obj/structure/extinguisher_cabinet/directional/south, -/obj/machinery/light/small/directional/south, -/obj/machinery/modular_computer/preset/cargochat/service{ - dir = 1 - }, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "hRV" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -32081,6 +32056,28 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/engineering/atmos/hfr_room) +"hWA" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/preopen{ + id = "hopblast"; + name = "HoP Blast Door" + }, +/obj/machinery/door/window/brigdoor/left/directional/east{ + name = "Access Desk"; + req_access = list("hop") + }, +/obj/machinery/door/window/right/directional/west{ + name = "Access Queue" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/desk_bell{ + pixel_x = 7 + }, +/turf/open/floor/iron, +/area/station/command/heads_quarters/hop) "hWF" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -32231,16 +32228,6 @@ /obj/machinery/airalarm/directional/south, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) -"hYh" = ( -/obj/machinery/newscaster/directional/east, -/obj/machinery/airalarm/directional/south, -/obj/structure/tank_holder/extinguisher, -/obj/machinery/camera/directional/south{ - c_tag = "Library - Art Gallery"; - name = "library camera" - }, -/turf/open/floor/wood/tile, -/area/station/service/library/artgallery) "hYn" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -35456,15 +35443,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos) -"iOp" = ( -/obj/machinery/light_switch/directional/north, -/obj/structure/cable, -/obj/effect/turf_decal/loading_area{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron/textured, -/area/station/medical/storage) "iOu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -36996,18 +36974,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/engineering/supermatter/room) -"jgG" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/machinery/firealarm/directional/north, -/obj/machinery/camera/directional/north{ - c_tag = "Service - Service Hall"; - dir = 9; - name = "service camera" - }, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/service) "jgN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -41333,6 +41299,15 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"kix" = ( +/obj/effect/turf_decal/bot, +/obj/structure/extinguisher_cabinet/directional/south, +/obj/machinery/light/small/directional/south, +/obj/machinery/modular_computer/preset/cargochat/service{ + dir = 1 + }, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "kiz" = ( /obj/structure/sign/poster/random/directional/east, /obj/structure/table, @@ -41914,6 +41889,16 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) +"kqI" = ( +/obj/structure/plaque/static_plaque/golden{ + pixel_y = -32 + }, +/obj/structure/reagent_dispensers/water_cooler, +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/security/office) "kqJ" = ( /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 1 @@ -43511,6 +43496,13 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/transit_tube) +"kNB" = ( +/obj/structure/table/wood, +/obj/item/papercutter, +/obj/item/paper/fluff/ids_for_dummies, +/obj/item/radio/intercom/directional/east, +/turf/open/floor/wood, +/area/station/command/heads_quarters/hop) "kNC" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -44615,6 +44607,15 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/maintenance/department/eva/abandoned) +"lcl" = ( +/obj/machinery/light_switch/directional/north, +/obj/structure/cable, +/obj/effect/turf_decal/loading_area{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/textured, +/area/station/medical/storage) "lcm" = ( /turf/open/floor/wood, /area/station/security/detectives_office/private_investigators_office) @@ -46459,20 +46460,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/service/theater) -"lAe" = ( -/obj/machinery/light/directional/south, -/obj/machinery/camera/directional/south{ - c_tag = "Security - Office Aft" - }, -/obj/machinery/computer/security/telescreen/entertainment/directional/south, -/obj/machinery/modular_computer/preset/cargochat/security{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 9 - }, -/turf/open/floor/iron/dark, -/area/station/security/office) "lAg" = ( /obj/structure/table/wood, /obj/item/folder/red, @@ -48436,6 +48423,42 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"lZC" = ( +/obj/structure/table/wood, +/obj/machinery/computer/records/medical/laptop, +/obj/machinery/light_switch/directional/west{ + pixel_x = -38; + pixel_y = 8 + }, +/obj/machinery/button/flasher{ + id = "hopflash"; + pixel_x = -38; + pixel_y = -7; + req_access = list("kitchen") + }, +/obj/machinery/button/ticket_machine{ + pixel_y = 22; + pixel_x = -6 + }, +/obj/machinery/button/door/directional/west{ + id = "hopblast"; + name = "Lockdown Blast Doors"; + pixel_y = 6; + req_access = list("hop") + }, +/obj/machinery/button/door/directional/west{ + id = "hopline"; + name = "Queue Shutters Control"; + pixel_y = -6; + req_access = list("hop") + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/button/photobooth{ + pixel_y = 22; + pixel_x = 6 + }, +/turf/open/floor/iron/dark, +/area/station/command/heads_quarters/hop) "lZF" = ( /obj/machinery/power/shieldwallgen/xenobiologyaccess, /obj/structure/cable, @@ -48451,6 +48474,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/textured_large, /area/station/science/xenobiology) +"lZV" = ( +/obj/structure/chair/office/light, +/obj/effect/landmark/start/virologist, +/obj/effect/turf_decal/trimline/green/filled/warning, +/turf/open/floor/iron/white, +/area/station/medical/virology) "lZX" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/south, @@ -49251,42 +49280,6 @@ "mlE" = ( /turf/closed/wall/r_wall, /area/station/ai_monitored/command/storage/eva) -"mlM" = ( -/obj/structure/table/wood, -/obj/machinery/computer/records/medical/laptop, -/obj/machinery/light_switch/directional/west{ - pixel_x = -38; - pixel_y = 8 - }, -/obj/machinery/button/flasher{ - id = "hopflash"; - pixel_x = -38; - pixel_y = -7; - req_access = list("kitchen") - }, -/obj/machinery/button/ticket_machine{ - pixel_y = 22; - pixel_x = -6 - }, -/obj/machinery/button/door/directional/west{ - id = "hopblast"; - name = "Lockdown Blast Doors"; - pixel_y = 6; - req_access = list("hop") - }, -/obj/machinery/button/door/directional/west{ - id = "hopline"; - name = "Queue Shutters Control"; - pixel_y = -6; - req_access = list("hop") - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/button/photobooth{ - pixel_y = 22; - pixel_x = 6 - }, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/hop) "mlW" = ( /obj/structure/sign/nanotrasen{ pixel_y = 32 @@ -49700,6 +49693,16 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"msL" = ( +/obj/machinery/newscaster/directional/east, +/obj/machinery/airalarm/directional/south, +/obj/structure/tank_holder/extinguisher, +/obj/machinery/camera/directional/south{ + c_tag = "Library - Art Gallery"; + name = "library camera" + }, +/turf/open/floor/wood/tile, +/area/station/service/library/artgallery) "msR" = ( /obj/effect/turf_decal/tile/red/opposingcorners{ dir = 1 @@ -49789,6 +49792,23 @@ /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/floor/iron, /area/station/engineering/storage) +"mtD" = ( +/obj/machinery/requests_console/directional/north{ + department = "Medbay"; + name = "Medbay Requests Console" + }, +/obj/effect/mapping_helpers/requests_console/assistance, +/obj/structure/cable, +/obj/effect/turf_decal/bot, +/obj/machinery/camera/directional/north{ + c_tag = "Medbay - Storage"; + name = "medbay camera"; + network = list("ss13","medbay") + }, +/obj/machinery/modular_computer/preset/cargochat/medical, +/obj/effect/turf_decal/trimline/brown/filled/end, +/turf/open/floor/iron, +/area/station/medical/storage) "mtO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/tile/yellow{ @@ -51035,14 +51055,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/hallway/secondary/construction) -"mIg" = ( -/obj/structure/chair/office/light, -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 10 - }, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white, -/area/station/medical/virology) "mIs" = ( /turf/closed/wall, /area/station/command/gateway) @@ -51748,6 +51760,18 @@ }, /turf/open/floor/iron, /area/station/service/abandoned_gambling_den/gaming) +"mRl" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Research Division"; + name = "Research Division Fax Machine"; + pixel_x = 1 + }, +/turf/open/floor/iron, +/area/station/science/research) "mRs" = ( /obj/structure/cable, /obj/effect/landmark/start/depsec/science, @@ -52028,12 +52052,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/commons/locker) -"mVX" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark/telecomms, -/area/station/tcommsat/server) "mVY" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -54518,6 +54536,20 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/iron, /area/station/service/hydroponics) +"nFf" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ + dir = 1 + }, +/obj/machinery/door/window/left/directional/east{ + name = "Medical Delivery"; + req_access = list("medical") + }, +/turf/open/floor/iron/textured, +/area/station/medical/storage) "nFr" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -58034,13 +58066,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"oBa" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/item/kirbyplants/random, -/turf/open/floor/iron, -/area/station/engineering/storage_shared) "oBd" = ( /obj/machinery/newscaster/directional/east, /obj/effect/turf_decal/trimline/blue/filled/corner{ @@ -58184,16 +58209,6 @@ }, /turf/open/floor/iron/dark/textured_half, /area/station/service/janitor) -"oDw" = ( -/obj/structure/table/glass, -/obj/machinery/computer/records/medical/laptop, -/obj/item/toy/figure/virologist, -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 1 - }, -/obj/structure/cable, -/turf/open/floor/iron/white, -/area/station/medical/virology) "oDx" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/security{ @@ -58717,6 +58732,21 @@ }, /turf/open/floor/wood, /area/station/service/electronic_marketing_den) +"oLD" = ( +/obj/machinery/camera/directional/north{ + c_tag = "Science - Central Access"; + dir = 9; + name = "science camera"; + network = list("ss13","rd") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/item/radio/intercom/directional/north, +/obj/effect/turf_decal/trimline/purple/filled/corner{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/science/research) "oLL" = ( /obj/structure/cable, /obj/effect/turf_decal/delivery, @@ -59051,21 +59081,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/science/lobby) -"oPF" = ( -/obj/machinery/camera/directional/north{ - c_tag = "Science - Central Access"; - dir = 9; - name = "science camera"; - network = list("ss13","rd") - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/item/radio/intercom/directional/north, -/obj/effect/turf_decal/trimline/purple/filled/corner{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/science/research) "oPL" = ( /obj/machinery/door/window/right/directional/east{ name = "Danger: Conveyor Access"; @@ -59159,6 +59174,20 @@ /obj/machinery/light/small/dim/directional/north, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"oRf" = ( +/obj/machinery/light/directional/south, +/obj/machinery/camera/directional/south{ + c_tag = "Security - Office Aft" + }, +/obj/machinery/computer/security/telescreen/entertainment/directional/south, +/obj/machinery/modular_computer/preset/cargochat/security{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/turf/open/floor/iron/dark, +/area/station/security/office) "oRh" = ( /obj/machinery/status_display/evac/directional/east, /obj/structure/chair{ @@ -59182,11 +59211,6 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/plating, /area/station/commons/fitness/recreation) -"oRq" = ( -/obj/structure/cable, -/mob/living/basic/slime, -/turf/open/floor/circuit/green, -/area/station/science/xenobiology) "oRs" = ( /obj/structure/disposalpipe/segment, /obj/effect/decal/cleanable/dirt, @@ -59452,23 +59476,6 @@ }, /turf/open/floor/iron/dark, /area/station/service/abandoned_gambling_den) -"oUf" = ( -/obj/machinery/requests_console/directional/north{ - department = "Medbay"; - name = "Medbay Requests Console" - }, -/obj/effect/mapping_helpers/requests_console/assistance, -/obj/structure/cable, -/obj/effect/turf_decal/bot, -/obj/machinery/camera/directional/north{ - c_tag = "Medbay - Storage"; - name = "medbay camera"; - network = list("ss13","medbay") - }, -/obj/machinery/modular_computer/preset/cargochat/medical, -/obj/effect/turf_decal/trimline/brown/filled/end, -/turf/open/floor/iron, -/area/station/medical/storage) "oUh" = ( /obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ dir = 1 @@ -59670,15 +59677,6 @@ dir = 8 }, /area/station/engineering/atmos/project) -"oXX" = ( -/obj/machinery/disposal/bin, -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/trunk{ - dir = 1 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "oYe" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -59814,13 +59812,6 @@ }, /turf/open/floor/wood, /area/station/security/detectives_office/private_investigators_office) -"paD" = ( -/obj/structure/table/wood, -/obj/item/papercutter, -/obj/item/paper/fluff/ids_for_dummies, -/obj/item/radio/intercom/directional/east, -/turf/open/floor/wood, -/area/station/command/heads_quarters/hop) "paQ" = ( /obj/effect/turf_decal/trimline/purple/filled/line, /turf/open/floor/iron/white, @@ -61082,6 +61073,16 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/security/detectives_office/private_investigators_office) +"pqo" = ( +/obj/machinery/flasher/directional/east{ + id = "hopflash"; + pixel_x = 0; + pixel_y = 26 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/photobooth, +/turf/open/floor/iron/dark, +/area/station/hallway/primary/central/fore) "pqp" = ( /obj/structure/sign/warning/secure_area/directional/north, /obj/structure/table, @@ -62130,6 +62131,14 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/general, /turf/open/floor/iron, /area/station/engineering/atmos) +"pDb" = ( +/obj/structure/chair/office/light, +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 10 + }, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white, +/area/station/medical/virology) "pDf" = ( /obj/machinery/computer/camera_advanced/xenobio{ dir = 1 @@ -63115,16 +63124,6 @@ /obj/structure/barricade/wooden, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"pOu" = ( -/obj/machinery/power/smes/full, -/obj/machinery/status_display/ai/directional/north, -/obj/structure/cable, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/light/small/directional/north, -/turf/open/floor/plating, -/area/station/ai_monitored/turret_protected/aisat_interior) "pOz" = ( /obj/structure/cable, /obj/machinery/modular_computer/preset/id{ @@ -63339,6 +63338,15 @@ }, /turf/open/floor/iron/white, /area/station/medical/chemistry) +"pQo" = ( +/obj/machinery/modular_computer/preset/cargochat/engineering{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/end{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/engineering/storage_shared) "pQx" = ( /obj/structure/lattice, /obj/structure/window/reinforced/spawner/directional/north, @@ -63904,6 +63912,18 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"pWB" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/firealarm/directional/north, +/obj/machinery/camera/directional/north{ + c_tag = "Service - Service Hall"; + dir = 9; + name = "service camera" + }, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/service) "pWG" = ( /obj/structure/table/wood, /obj/item/radio/intercom/directional/west, @@ -65072,6 +65092,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet/green, /area/station/service/library) +"qlY" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark/telecomms, +/area/station/tcommsat/server) "qmd" = ( /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 8 @@ -65539,6 +65565,13 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"qsv" = ( +/obj/effect/turf_decal/bot, +/obj/structure/table, +/obj/item/paper_bin, +/obj/item/pen, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "qsw" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table/wood, @@ -65986,12 +66019,6 @@ }, /turf/open/floor/iron, /area/station/engineering/main) -"qyK" = ( -/obj/machinery/light/small/directional/west, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/photobooth/security, -/turf/open/floor/iron/dark, -/area/station/security/execution/transfer) "qyX" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -67033,16 +67060,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/security/courtroom) -"qLa" = ( -/obj/machinery/flasher/directional/east{ - id = "hopflash"; - pixel_x = 0; - pixel_y = 26 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/photobooth, -/turf/open/floor/iron/dark, -/area/station/hallway/primary/central/fore) "qLg" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -67591,6 +67608,12 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/grimy, /area/station/service/library) +"qSC" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/service) "qSG" = ( /obj/machinery/portable_atmospherics/canister/anesthetic_mix, /obj/machinery/light/small/blacklight/directional/north, @@ -67714,15 +67737,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"qUL" = ( -/obj/machinery/modular_computer/preset/cargochat/engineering{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/brown/filled/end{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/engineering/storage_shared) "qUM" = ( /obj/structure/sign/nanotrasen, /turf/closed/wall/r_wall, @@ -68509,6 +68523,16 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/engineering/main) +"rgH" = ( +/obj/machinery/power/smes/full, +/obj/machinery/status_display/ai/directional/north, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/north, +/turf/open/floor/plating, +/area/station/ai_monitored/turret_protected/aisat_interior) "rgK" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -68862,6 +68886,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/security/detectives_office) +"rky" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/holopad, +/obj/effect/landmark/start/hangover, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "rkC" = ( /obj/structure/chair/office{ dir = 8 @@ -69268,15 +69298,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/port) -"roh" = ( -/obj/machinery/firealarm/directional/east, -/obj/effect/turf_decal/trimline/purple/filled/corner{ - dir = 8 - }, -/obj/machinery/airalarm/directional/south, -/obj/machinery/photocopier, -/turf/open/floor/iron/white, -/area/station/science/research) "rol" = ( /obj/structure/chair/sofa/bench{ dir = 8 @@ -70698,18 +70719,6 @@ /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/floor/iron, /area/station/engineering/main) -"rIO" = ( -/obj/structure/chair/office/light{ - dir = 8 - }, -/obj/effect/landmark/start/virologist, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/structure/cable, -/obj/effect/turf_decal/tile/neutral/full, -/turf/open/floor/iron/large, -/area/station/medical/virology) "rIP" = ( /obj/structure/lattice/catwalk, /obj/structure/sign/warning/secure_area/directional/east, @@ -72406,16 +72415,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/pharmacy) -"sbZ" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/status_display/evac/directional/north, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/service) "sca" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -72437,6 +72436,20 @@ }, /turf/open/floor/iron, /area/station/maintenance/port/fore) +"scp" = ( +/obj/machinery/light/directional/west, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/effect/turf_decal/bot/left, +/obj/structure/sign/nanotrasen{ + pixel_x = -32 + }, +/obj/machinery/modular_computer/preset/cargochat/science{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/science/research) "scs" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -72451,15 +72464,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/dark, /area/station/science/ordnance/storage) -"scJ" = ( -/obj/machinery/airalarm/directional/north, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Service Hallway"; - name = "Service Fax Machine" - }, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "scR" = ( /obj/machinery/airalarm/directional/south, /turf/open/floor/iron/white, @@ -72766,14 +72770,6 @@ }, /turf/open/floor/iron, /area/station/security/brig) -"sgG" = ( -/obj/structure/table, -/obj/item/clipboard, -/obj/item/stack/package_wrap, -/obj/item/hand_labeler, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "sgI" = ( /obj/docking_port/stationary/escape_pod{ dir = 4 @@ -74667,13 +74663,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/ai_upload) -"sGp" = ( -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/item/kirbyplants/random, -/turf/open/floor/iron, -/area/station/security/office) "sGx" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -75579,6 +75568,11 @@ "sRd" = ( /turf/closed/wall/r_wall, /area/station/security/evidence) +"sRs" = ( +/obj/item/radio/intercom/directional/north, +/obj/machinery/photocopier, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "sRt" = ( /obj/structure/rack, /obj/effect/spawner/random/maintenance, @@ -76129,12 +76123,6 @@ }, /turf/open/floor/iron, /area/station/science/lab) -"sYe" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/service) "sYf" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -76513,6 +76501,19 @@ /obj/effect/turf_decal/tile/red, /turf/open/floor/iron, /area/station/security/execution/transfer) +"tdm" = ( +/obj/machinery/power/smes/full, +/obj/structure/sign/warning/electric_shock/directional/north, +/obj/machinery/camera/directional/north{ + c_tag = "AI Chamber - Fore"; + name = "motion-sensitive ai camera"; + network = list("aichamber") + }, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/turret_protected/ai) "tdt" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -77297,33 +77298,6 @@ /obj/machinery/light/small/dim/directional/north, /turf/open/floor/iron/dark, /area/station/maintenance/department/science) -"tpV" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ - dir = 1 - }, -/obj/machinery/door/window/left/directional/east{ - name = "Medical Delivery"; - req_access = list("medical") - }, -/turf/open/floor/iron/textured, -/area/station/medical/storage) -"tpX" = ( -/obj/machinery/power/smes/full, -/obj/structure/sign/warning/electric_shock/directional/north, -/obj/machinery/camera/directional/north{ - c_tag = "AI Chamber - Fore"; - name = "motion-sensitive ai camera"; - network = list("aichamber") - }, -/obj/structure/cable, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/light/small/directional/north, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/turret_protected/ai) "tpZ" = ( /turf/closed/wall, /area/station/maintenance/starboard/fore) @@ -78607,6 +78581,12 @@ /obj/structure/sign/poster/official/random/directional/west, /turf/open/floor/wood, /area/station/maintenance/port/fore) +"tFu" = ( +/obj/structure/cable, +/obj/machinery/firealarm/directional/east, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/engineering/storage_shared) "tFG" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -80201,6 +80181,14 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) +"tYN" = ( +/obj/machinery/airalarm/directional/west, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/machinery/recharge_station, +/turf/open/floor/iron, +/area/station/science/research) "tYP" = ( /obj/structure/chair/office/light, /obj/structure/cable, @@ -80366,6 +80354,12 @@ }, /turf/open/floor/iron, /area/station/medical/abandoned) +"ubJ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/service) "ubK" = ( /obj/machinery/computer/operating, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -83002,12 +82996,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/secondary/exit) -"uJl" = ( -/obj/effect/turf_decal/bot, -/obj/machinery/holopad, -/obj/effect/landmark/start/hangover, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "uJm" = ( /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, @@ -83323,6 +83311,15 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/cargo/miningoffice) +"uMT" = ( +/obj/machinery/disposal/bin, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/checker, +/area/station/hallway/secondary/service) "uMV" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -84272,13 +84269,6 @@ }, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"uZc" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/security/office) "uZe" = ( /obj/machinery/door/window/brigdoor/left/directional/south{ name = "Coroner's Office"; @@ -85106,13 +85096,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/port/aft) -"vke" = ( -/obj/structure/cable, -/obj/machinery/power/smes/full, -/obj/effect/turf_decal/bot, -/obj/item/radio/intercom/directional/west, -/turf/open/floor/iron, -/area/station/engineering/gravity_generator) "vkg" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -85207,6 +85190,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood/large, /area/station/service/barber) +"vlS" = ( +/obj/structure/cable, +/mob/living/basic/slime, +/turf/open/floor/circuit/green, +/area/station/science/xenobiology) "vlY" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/stripes/line{ @@ -86959,6 +86947,9 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"vHq" = ( +/turf/open/floor/iron, +/area/station/security/office) "vHu" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -88645,13 +88636,6 @@ /obj/item/flashlight/lamp, /turf/open/floor/wood, /area/station/hallway/secondary/service) -"wgz" = ( -/obj/effect/turf_decal/bot, -/obj/structure/table, -/obj/item/paper_bin, -/obj/item/pen, -/turf/open/floor/iron/checker, -/area/station/hallway/secondary/service) "wgC" = ( /obj/machinery/door/poddoor/shutters/radiation/preopen{ id = "engsm"; @@ -88999,17 +88983,6 @@ }, /turf/open/floor/iron/dark, /area/station/command/bridge) -"wkV" = ( -/obj/structure/sign/poster/official/random/directional/south, -/obj/machinery/light/directional/south, -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/station/engineering/storage_shared) "wlc" = ( /obj/structure/table/reinforced, /obj/item/gun/energy/laser/carbine/practice{ @@ -90941,6 +90914,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/science/auxlab/firing_range) +"wGm" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/item/kirbyplants/random, +/turf/open/floor/iron, +/area/station/engineering/storage_shared) "wGs" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -91438,12 +91418,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"wOz" = ( -/obj/structure/chair/office/light, -/obj/effect/landmark/start/virologist, -/obj/effect/turf_decal/trimline/green/filled/warning, -/turf/open/floor/iron/white, -/area/station/medical/virology) "wOP" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 9 @@ -91631,12 +91605,6 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/captain) -"wRJ" = ( -/obj/structure/cable, -/obj/machinery/firealarm/directional/east, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron, -/area/station/engineering/storage_shared) "wRL" = ( /obj/effect/spawner/random/structure/crate, /obj/machinery/light/small/broken/directional/west, @@ -92877,6 +92845,16 @@ /obj/effect/turf_decal/trimline/neutral/warning, /turf/open/floor/iron/dark/textured_half, /area/station/medical/morgue) +"xiu" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/status_display/evac/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/service) "xiB" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -93088,6 +93066,13 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/dark, /area/station/hallway/primary/central/fore) +"xlf" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/obj/effect/landmark/event_spawn, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/service) "xls" = ( /obj/structure/table/reinforced, /obj/item/storage/toolbox/mechanical, @@ -93522,6 +93507,14 @@ }, /turf/open/floor/iron/dark, /area/station/command/bridge) +"xrS" = ( +/obj/structure/sign/warning/secure_area/directional/south, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 6 + }, +/obj/item/kirbyplants/organic/plant10, +/turf/open/floor/iron/white, +/area/station/science/research) "xsb" = ( /obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ @@ -95800,6 +95793,13 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"xUs" = ( +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/item/kirbyplants/random, +/turf/open/floor/iron, +/area/station/security/office) "xUv" = ( /obj/machinery/firealarm/directional/west, /obj/structure/cable, @@ -103565,7 +103565,7 @@ btH btH btH bPC -pOu +rgH bTq jYp vgi @@ -105352,7 +105352,7 @@ alK qPm btH btH -tpX +tdm kXJ bEl xMy @@ -117181,7 +117181,7 @@ xqR qzc kUx kTV -vke +chv dQl oIE fFu @@ -118512,7 +118512,7 @@ pWL jjm rUl rTW -oRq +vlS rTW oVW oUe @@ -120054,7 +120054,7 @@ kSA jjm nkj rTW -oRq +vlS rTW oVW fmi @@ -120517,7 +120517,7 @@ fXF jgZ mrd rDL -qUL +pQo uCa wkj bqP @@ -120774,7 +120774,7 @@ fXF suH ikV gIk -wkV +ekF leE bfq iFn @@ -120815,7 +120815,7 @@ uKY gcr mQO rTW -oRq +vlS rTW iWX csO @@ -121031,7 +121031,7 @@ nmi xvf oQJ xJJ -oBa +wGm uCa aTz ygM @@ -121544,7 +121544,7 @@ wiZ fXF xkz hwe -wRJ +tFu vpV uCa gQk @@ -126730,7 +126730,7 @@ nIa hSf ffb cMn -hkZ +xrS sIX sIX cLR @@ -128272,15 +128272,15 @@ txc pZM ffb dqP -anU +aFp sIX sIX xbJ sIX sIX -aCA -aqU -aJj +mRl +scp +tYN dNN qMB wtS @@ -129304,7 +129304,7 @@ ikZ oRh oHq wNV -roh +eyl dNN uMV sEF @@ -129563,7 +129563,7 @@ dNN dNN dNN dNN -oPF +oLD dCx aJT fDF @@ -131407,7 +131407,7 @@ tgT rZl wjV jpN -mIg +pDb rJG gqm qYo @@ -131910,8 +131910,8 @@ bMV wjP aaa uUx -oDw -rIO +clB +hPH qJA gKl ecC @@ -131921,7 +131921,7 @@ gqm jyT wjV sFR -wOz +lZV fLV gqm qYo @@ -132094,7 +132094,7 @@ fxs lAg kPM pRS -qLa +pqo nLS xld uqZ @@ -132352,7 +132352,7 @@ rgW vze pRS pRS -eIu +hWA iaL pRS iaL @@ -132608,7 +132608,7 @@ sEm dEA nxd pRS -mlM +lZC eGs ykB jpe @@ -133078,7 +133078,7 @@ sid sBG sLz vRB -sgG +gch xMe kVP bSp @@ -133334,8 +133334,8 @@ cnL kfa pPI kVP -sbZ -oXX +xiu +uMT jVP kVP pET @@ -133591,8 +133591,8 @@ vdZ qPp pXt kVP -cVD -uJl +fWB +rky iXO kVP pgN @@ -133848,8 +133848,8 @@ vBt tyK kVP kVP -jgG -wgz +pWB +qsv gMB kVP kVP @@ -133893,7 +133893,7 @@ wmp rgW mGw pRS -paD +kNB lAv nAz jce @@ -134105,11 +134105,11 @@ kVP kVP kVP dUH -cBB -bJi +ubJ +xlf giz kVr -hRU +kix kVP sGS qOT @@ -135134,7 +135134,7 @@ mqV kVP giz giz -sYe +qSC lJJ maV ptC @@ -135391,7 +135391,7 @@ kVP kVP vat kVP -hjH +sRs hUh kVP cAV @@ -135648,7 +135648,7 @@ pOD tWU sSH kVP -scJ +aUZ qPX kVP aVE @@ -136510,9 +136510,9 @@ umA veM veM ako -tpV -cJQ -gPH +nFf +hFQ +fEV uQF ibh cYk @@ -136767,7 +136767,7 @@ oCo fiU jRJ ako -iOp +lcl dNc dNc dNc @@ -137024,7 +137024,7 @@ euF oCo sJG ako -oUf +mtD rjO oOI oOI @@ -137495,7 +137495,7 @@ ilI ilI ilI hup -mVX +qlY cMD ilI ilI @@ -144471,7 +144471,7 @@ lsJ ffP gBi tqy -hYh +msL qMf oci bqS @@ -149040,7 +149040,7 @@ nzR gKp gDP rTG -sGp +xUs ozu dql pWH @@ -149554,8 +149554,8 @@ ieg eIl ieg ieg -uZc -bDx +fes +vHq dql eBE gIV @@ -149800,7 +149800,7 @@ ouc qWZ iCo krO -qyK +guZ lET gBA xtf @@ -149812,7 +149812,7 @@ bdx lpI iIb tXW -cfx +kqI vgK wdC lTt @@ -150069,7 +150069,7 @@ sKp tXJ bkN gCV -lAe +oRf vgK ljX tLx diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index e66eb438644..de038813256 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -1853,6 +1853,16 @@ /obj/structure/extinguisher_cabinet/directional/south, /turf/open/floor/iron/white, /area/station/science/robotics/lab) +"aEK" = ( +/obj/machinery/atmospherics/components/binary/pump/off, +/obj/machinery/airlock_sensor/incinerator_ordmix{ + pixel_x = 24 + }, +/obj/machinery/atmospherics/pipe/layer_manifold/supply/hidden{ + dir = 4 + }, +/turf/open/floor/engine, +/area/station/science/ordnance) "aEM" = ( /obj/structure/sign/departments/cargo, /turf/closed/wall/r_wall, @@ -4336,6 +4346,10 @@ }, /turf/open/floor/iron/dark, /area/station/service/hydroponics) +"bqX" = ( +/obj/machinery/air_sensor/ordnance_burn_chamber, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "bqY" = ( /obj/structure/closet, /obj/effect/spawner/random/maintenance/two, @@ -6204,6 +6218,14 @@ /obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"bPA" = ( +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 9 + }, +/obj/effect/landmark/start/virologist, +/obj/structure/chair/stool/directional/east, +/turf/open/floor/iron/dark, +/area/station/medical/virology) "bPE" = ( /obj/structure/table, /obj/item/radio/intercom/directional/east, @@ -8226,6 +8248,10 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/wood, /area/station/commons/vacant_room/office) +"cuB" = ( +/obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_burn_chamber_input, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "cuJ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -9893,13 +9919,6 @@ initial_gas_mix = "ICEMOON_ATMOS" }, /area/icemoon/underground/explored) -"cSm" = ( -/obj/machinery/mineral/processing_unit/gulag{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/mine/laborcamp) "cSu" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -12647,12 +12666,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply, /turf/open/floor/iron/dark, /area/station/medical/virology) -"dJk" = ( -/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_ordmix{ - dir = 8 - }, -/turf/open/floor/engine, -/area/station/science/ordnance) "dJx" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -14910,6 +14923,10 @@ "evb" = ( /turf/open/floor/iron, /area/station/service/janitor) +"evc" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "evk" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16606,14 +16623,16 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"eYz" = ( +/obj/machinery/mineral/processing_unit/gulag{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/mine/laborcamp) "eYC" = ( /turf/open/floor/iron/smooth, /area/mine/laborcamp/security) -"eYH" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/ai) "eYL" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/closed/wall, @@ -17645,6 +17664,11 @@ }, /turf/open/floor/carpet, /area/station/service/theater) +"fqM" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/ai) "fqQ" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -18366,6 +18390,10 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/medical/medbay/lobby) +"fCS" = ( +/obj/machinery/door/poddoor/incinerator_ordmix, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "fCW" = ( /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron/dark/textured, @@ -19319,10 +19347,6 @@ /obj/structure/sign/warning/electric_shock/directional/east, /turf/open/floor/iron, /area/station/hallway/primary/central) -"fSG" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/closed/wall/r_wall, -/area/station/science/ordnance) "fTb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -20969,10 +20993,6 @@ }, /turf/open/floor/iron, /area/station/security/prison/visit) -"grY" = ( -/obj/structure/gulag_vent/ice, -/turf/open/misc/asteroid/snow/icemoon, -/area/icemoon/underground/explored) "gsk" = ( /obj/structure/reflector/single/anchored{ dir = 5 @@ -22771,10 +22791,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/interrogation) -"gWZ" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_burn_chamber_input, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "gXe" = ( /obj/effect/turf_decal/siding/white{ dir = 4 @@ -24054,13 +24070,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"hrZ" = ( -/obj/structure/chair/office/light{ - dir = 4 - }, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white, -/area/station/medical/virology) "hsh" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, @@ -25146,16 +25155,6 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron, /area/station/service/janitor) -"hKj" = ( -/obj/machinery/atmospherics/components/binary/pump/off, -/obj/machinery/airlock_sensor/incinerator_ordmix{ - pixel_x = 24 - }, -/obj/machinery/atmospherics/pipe/layer_manifold/supply/hidden{ - dir = 4 - }, -/turf/open/floor/engine, -/area/station/science/ordnance) "hKr" = ( /obj/structure/table/glass, /obj/item/book/manual/wiki/infections{ @@ -26040,10 +26039,6 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"iao" = ( -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, -/turf/closed/wall/r_wall, -/area/station/science/ordnance) "iar" = ( /obj/structure/cable, /obj/machinery/door/poddoor/preopen{ @@ -26927,10 +26922,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/chemistry) -"inb" = ( -/obj/machinery/door/poddoor/incinerator_ordmix, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "inh" = ( /obj/structure/stairs/west, /obj/structure/railing, @@ -27488,6 +27479,9 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"iwq" = ( +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "iwx" = ( /obj/machinery/door/airlock/maintenance{ name = "Xenobiology Maintenance" @@ -27661,15 +27655,6 @@ /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"izc" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden{ - dir = 8 - }, -/turf/open/floor/engine, -/area/station/science/ordnance) "izn" = ( /obj/effect/spawner/random/decoration/generic, /turf/open/floor/plating, @@ -27903,6 +27888,10 @@ dir = 4 }, /area/station/science/explab) +"iCe" = ( +/obj/machinery/atmospherics/pipe/smart/simple/dark/visible, +/turf/closed/wall/r_wall, +/area/station/science/ordnance) "iCg" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -32830,9 +32819,6 @@ dir = 4 }, /area/station/maintenance/port/fore) -"keV" = ( -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "keX" = ( /obj/structure/table, /obj/item/stack/cable_coil{ @@ -36520,6 +36506,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/port/fore) +"lgP" = ( +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden{ + dir = 8 + }, +/turf/open/floor/engine, +/area/station/science/ordnance) "lgW" = ( /obj/machinery/meter/monitored/distro_loop, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/visible, @@ -41332,14 +41327,6 @@ /obj/structure/cable, /turf/open/floor/wood/parquet, /area/station/service/bar/atrium) -"mIC" = ( -/obj/machinery/door/airlock/research/glass/incinerator/ordmix_exterior{ - name = "Burn Chamber Exterior Airlock" - }, -/obj/effect/mapping_helpers/airlock/locked, -/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "mIE" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -42191,10 +42178,6 @@ }, /turf/open/floor/plating, /area/station/hallway/secondary/entry) -"mYd" = ( -/obj/machinery/air_sensor/ordnance_burn_chamber, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "mYh" = ( /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) @@ -44390,10 +44373,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/aft/greater) -"nBV" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "nCa" = ( /obj/structure/rack, /obj/item/pickaxe, @@ -45211,14 +45190,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/mine/mechbay) -"nNB" = ( -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 9 - }, -/obj/effect/landmark/start/virologist, -/obj/structure/chair/stool/directional/east, -/turf/open/floor/iron/dark, -/area/station/medical/virology) "nNM" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/mapping_helpers/airlock/abandoned, @@ -46008,6 +45979,10 @@ }, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"ocd" = ( +/obj/machinery/igniter/incinerator_ordmix, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "ocf" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -47731,23 +47706,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/solars/starboard/fore) -"oCs" = ( -/obj/structure/table, -/obj/item/toy/figure/virologist{ - pixel_x = -8; - pixel_y = 7 - }, -/obj/item/radio/headset/headset_med{ - pixel_x = -3; - pixel_y = -2 - }, -/obj/item/book/manual/wiki/infections{ - pixel_x = 10; - pixel_y = 2 - }, -/obj/effect/turf_decal/tile/green/full, -/turf/open/floor/iron/dark/smooth_large, -/area/station/medical/virology) "oCv" = ( /obj/item/chair/plastic{ pixel_y = 10 @@ -56730,6 +56688,14 @@ /obj/effect/mapping_helpers/airlock/access/all/supply/mining, /turf/open/floor/iron/dark/textured_half, /area/mine/mechbay) +"rmG" = ( +/obj/machinery/door/airlock/research/glass/incinerator/ordmix_exterior{ + name = "Burn Chamber Exterior Airlock" + }, +/obj/effect/mapping_helpers/airlock/locked, +/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "rmM" = ( /obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk{ @@ -56873,6 +56839,10 @@ /obj/machinery/newscaster/directional/south, /turf/open/floor/iron, /area/station/science/explab) +"roW" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/closed/wall/r_wall, +/area/station/science/ordnance) "roX" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -57449,6 +57419,12 @@ /obj/item/kirbyplants/random, /turf/open/floor/wood, /area/station/hallway/secondary/service) +"ryX" = ( +/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_ordmix{ + dir = 8 + }, +/turf/open/floor/engine, +/area/station/science/ordnance) "rza" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -60232,6 +60208,17 @@ dir = 8 }, /area/station/service/chapel) +"sqH" = ( +/obj/machinery/door/airlock/research/glass/incinerator/ordmix_interior{ + name = "Burn Chamber Interior Airlock" + }, +/obj/effect/mapping_helpers/airlock/locked, +/obj/machinery/airlock_controller/incinerator_ordmix{ + pixel_x = 24 + }, +/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, +/turf/open/floor/engine, +/area/station/science/ordnance) "sqN" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -60385,6 +60372,10 @@ /obj/structure/sign/warning/secure_area, /turf/closed/wall/r_wall, /area/station/engineering/storage/tech) +"ssu" = ( +/obj/structure/gulag_vent/ice, +/turf/open/misc/asteroid/snow/icemoon, +/area/icemoon/underground/explored) "ssv" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/turf_decal/siding/thinplating_new/corner, @@ -61126,10 +61117,6 @@ /obj/structure/cable/multilayer/multiz, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) -"sDA" = ( -/obj/machinery/igniter/incinerator_ordmix, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "sDQ" = ( /obj/item/radio/intercom/prison/directional/north, /obj/effect/turf_decal/tile/red/half/contrasted{ @@ -63973,6 +63960,13 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, /turf/open/floor/plating, /area/station/commons/storage/mining) +"tAr" = ( +/obj/structure/chair/office/light{ + dir = 4 + }, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white, +/area/station/medical/virology) "tAx" = ( /obj/effect/turf_decal/trimline/blue/filled/warning, /obj/structure/disposalpipe/segment, @@ -66822,6 +66816,23 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"uvz" = ( +/obj/structure/table, +/obj/item/toy/figure/virologist{ + pixel_x = -8; + pixel_y = 7 + }, +/obj/item/radio/headset/headset_med{ + pixel_x = -3; + pixel_y = -2 + }, +/obj/item/book/manual/wiki/infections{ + pixel_x = 10; + pixel_y = 2 + }, +/obj/effect/turf_decal/tile/green/full, +/turf/open/floor/iron/dark/smooth_large, +/area/station/medical/virology) "uvM" = ( /obj/effect/spawner/structure/window/hollow/reinforced/middle, /turf/open/floor/plating, @@ -73904,10 +73915,6 @@ "wHc" = ( /turf/closed/wall/r_wall, /area/station/command/heads_quarters/rd) -"wHd" = ( -/obj/machinery/atmospherics/pipe/smart/simple/dark/visible, -/turf/closed/wall/r_wall, -/area/station/science/ordnance) "wHe" = ( /obj/structure/cable, /turf/open/floor/iron/dark/textured, @@ -74039,6 +74046,10 @@ /obj/effect/landmark/start/depsec/medical, /turf/open/floor/iron/dark/smooth_large, /area/station/security/checkpoint/medical) +"wKh" = ( +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, +/turf/closed/wall/r_wall, +/area/station/science/ordnance) "wKm" = ( /obj/effect/turf_decal/tile/neutral/diagonal_edge, /obj/structure/disposalpipe/segment{ @@ -74374,17 +74385,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"wPC" = ( -/obj/machinery/door/airlock/research/glass/incinerator/ordmix_interior{ - name = "Burn Chamber Interior Airlock" - }, -/obj/effect/mapping_helpers/airlock/locked, -/obj/machinery/airlock_controller/incinerator_ordmix{ - pixel_x = 24 - }, -/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, -/turf/open/floor/engine, -/area/station/science/ordnance) "wPD" = ( /obj/machinery/door/airlock/security/glass{ name = "Evidence Storage" @@ -116641,7 +116641,7 @@ dhq dhq iDt iDt -grY +ssu iDt dLN rbT @@ -116905,7 +116905,7 @@ rbT lLN vRO ggV -cSm +eYz tGP tGP iRp @@ -183834,7 +183834,7 @@ cDb vEJ wGX oQY -hrZ +tAr wsF jUB jUB @@ -184605,7 +184605,7 @@ uCe xKe dRz pwn -oCs +uvz aru rqY tAg @@ -184863,7 +184863,7 @@ lzX dRz jUB cAM -nNB +bPA qkB vqH xDb @@ -193606,8 +193606,8 @@ uIf uIf uIf uIf -fSG -fSG +roW +roW bId gcy jJG @@ -193859,12 +193859,12 @@ thA thA rcY iDt -inb -keV -gWZ -wHd -izc -wHd +fCS +iwq +cuB +iCe +lgP +iCe vcH gnq xEF @@ -194116,12 +194116,12 @@ thA thA rcY iDt -inb -sDA -mYd -mIC -dJk -wPC +fCS +ocd +bqX +rmG +ryX +sqH qSk sbd rEh @@ -194373,12 +194373,12 @@ thA thA rcY iDt -inb -keV -nBV -iao -hKj -iao +fCS +iwq +evc +wKh +aEK +wKh odf sbd jaY @@ -248686,7 +248686,7 @@ mlp lEg cvh uBi -eYH +fqM jIZ oFx iHp diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 2d414269001..d86c0c5d24d 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -945,8 +945,6 @@ /area/station/command/heads_quarters/hos) "atf" = ( /obj/structure/table/glass, -/obj/item/clothing/gloves/latex, -/obj/item/surgical_drapes, /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -4592,6 +4590,14 @@ /obj/machinery/light/floor, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"bEv" = ( +/obj/machinery/door/airlock/research/glass/incinerator/ordmix_exterior{ + name = "Burn Chamber Exterior Airlock" + }, +/obj/effect/mapping_helpers/airlock/locked, +/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "bEA" = ( /obj/structure/cable, /obj/machinery/camera/directional/south{ @@ -5043,12 +5049,6 @@ /area/station/security/execution/education) "bMS" = ( /obj/structure/table/glass, -/obj/item/scalpel{ - pixel_y = 12 - }, -/obj/item/circular_saw, -/obj/item/blood_filter, -/obj/item/bonesetter, /obj/machinery/button/door/directional/south{ id = "main_surgery"; name = "privacy shutters control" @@ -6019,6 +6019,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"cgP" = ( +/obj/machinery/air_sensor/ordnance_burn_chamber, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "cha" = ( /obj/machinery/door/airlock/research/glass{ name = "Ordnance Lab" @@ -7640,6 +7644,12 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/command/heads_quarters/cmo) +"cOT" = ( +/obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_burn_chamber_input{ + dir = 1 + }, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "cOX" = ( /obj/structure/sign/warning/radiation/rad_area/directional/north, /obj/effect/turf_decal/stripes/line{ @@ -8844,10 +8854,6 @@ /obj/effect/turf_decal/bot_white, /turf/open/floor/iron, /area/station/cargo/storage) -"dke" = ( -/obj/machinery/air_sensor/ordnance_burn_chamber, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "dkx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, @@ -9484,12 +9490,10 @@ /area/station/hallway/secondary/exit/departure_lounge) "dyq" = ( /obj/structure/table/glass, -/obj/item/retractor, -/obj/item/hemostat, -/obj/item/cautery, /obj/effect/turf_decal/tile/blue/fourcorners, /obj/machinery/status_display/evac/directional/west, /obj/machinery/digital_clock/directional/south, +/obj/item/surgery_tray/full, /turf/open/floor/iron/white, /area/station/medical/surgery/theatre) "dyr" = ( @@ -9705,6 +9709,14 @@ }, /turf/open/floor/iron, /area/station/engineering/gravity_generator) +"dEF" = ( +/obj/machinery/atmospherics/components/binary/pump/on, +/obj/machinery/light/small/directional/east, +/obj/machinery/atmospherics/pipe/layer_manifold/supply/hidden{ + dir = 4 + }, +/turf/open/floor/engine, +/area/station/science/ordnance) "dEH" = ( /obj/effect/landmark/generic_maintenance_landmark, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -10810,6 +10822,9 @@ }, /turf/open/floor/iron/dark, /area/station/security/execution/education) +"dXU" = ( +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "dYa" = ( /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron, @@ -13278,6 +13293,10 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, /area/station/medical/cryo) +"eRn" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/closed/wall/r_wall, +/area/station/science/ordnance) "eRR" = ( /obj/structure/table, /obj/item/screwdriver{ @@ -14227,8 +14246,6 @@ /area/station/medical/medbay/central) "fiK" = ( /obj/structure/table/glass, -/obj/item/clothing/gloves/latex, -/obj/item/surgical_drapes, /obj/machinery/airalarm/directional/south, /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron/white, @@ -14672,11 +14689,9 @@ /area/station/ai_monitored/aisat/exterior) "fpg" = ( /obj/structure/table/glass, -/obj/item/retractor, -/obj/item/hemostat, -/obj/item/cautery, /obj/effect/turf_decal/tile/blue/fourcorners, /obj/machinery/status_display/evac/directional/west, +/obj/item/surgery_tray/full, /turf/open/floor/iron/white, /area/station/medical/surgery/theatre) "fpj" = ( @@ -14720,9 +14735,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/disposal) -"fpM" = ( -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "fqB" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/cable, @@ -15524,6 +15536,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood, /area/station/command/heads_quarters/qm) +"fIn" = ( +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/white, +/area/station/medical/virology) "fIo" = ( /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -16727,6 +16747,18 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"gil" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1 + }, +/obj/machinery/airlock_sensor/incinerator_ordmix{ + pixel_x = -24 + }, +/obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/engine, +/area/station/science/ordnance) "gip" = ( /obj/structure/table/wood, /obj/machinery/fax{ @@ -20018,10 +20050,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, /area/station/service/chapel) -"hsY" = ( -/obj/machinery/igniter/incinerator_ordmix, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "hsZ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/wood, @@ -20097,12 +20125,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, /area/station/command/heads_quarters/hop) -"htN" = ( -/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_ordmix{ - dir = 8 - }, -/turf/open/floor/engine, -/area/station/science/ordnance) "htO" = ( /obj/structure/chair/office{ dir = 1 @@ -24264,18 +24286,6 @@ "iOr" = ( /turf/closed/wall/r_wall, /area/station/security/prison/garden) -"iOt" = ( -/obj/structure/table/glass, -/obj/machinery/reagentgrinder{ - pixel_y = 8 - }, -/obj/item/toy/figure/virologist{ - pixel_x = -8 - }, -/obj/effect/turf_decal/tile/green/half/contrasted, -/obj/machinery/light/small/directional/south, -/turf/open/floor/iron/white, -/area/station/medical/virology) "iOD" = ( /obj/machinery/atmospherics/components/binary/tank_compressor{ dir = 8 @@ -25985,14 +25995,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/iron, /area/station/cargo/warehouse) -"jrJ" = ( -/obj/machinery/atmospherics/components/binary/pump/on, -/obj/machinery/light/small/directional/east, -/obj/machinery/atmospherics/pipe/layer_manifold/supply/hidden{ - dir = 4 - }, -/turf/open/floor/engine, -/area/station/science/ordnance) "jrL" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -28457,6 +28459,10 @@ /obj/effect/turf_decal/tile/green/half/contrasted, /turf/open/floor/iron/white, /area/station/medical/virology) +"kgC" = ( +/obj/machinery/door/poddoor/incinerator_ordmix, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "kgV" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -39126,6 +39132,12 @@ /obj/machinery/bookbinder, /turf/open/floor/wood, /area/station/service/library) +"nZL" = ( +/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_ordmix{ + dir = 8 + }, +/turf/open/floor/engine, +/area/station/science/ordnance) "nZQ" = ( /obj/machinery/airalarm/directional/north, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -39464,6 +39476,12 @@ /obj/effect/mapping_helpers/airlock/access/all/service/hydroponics, /turf/open/floor/iron, /area/station/service/hydroponics) +"oet" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "oew" = ( /turf/open/floor/iron, /area/station/commons/fitness/recreation) @@ -41350,14 +41368,6 @@ /obj/structure/marker_beacon/olive, /turf/open/space/basic, /area/space/nearstation) -"oPY" = ( -/obj/structure/chair/office/light{ - dir = 8 - }, -/obj/effect/landmark/start/virologist, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/white, -/area/station/medical/virology) "oPZ" = ( /obj/structure/grille, /turf/open/floor/plating, @@ -44763,12 +44773,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"qaW" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "qbr" = ( /obj/structure/bed/medical{ dir = 4 @@ -48563,6 +48567,10 @@ }, /turf/open/floor/iron, /area/station/ai_monitored/command/storage/eva) +"rtj" = ( +/obj/machinery/igniter/incinerator_ordmix, +/turf/open/floor/engine/vacuum, +/area/station/science/ordnance) "rtD" = ( /obj/effect/turf_decal/tile/purple, /obj/machinery/light/directional/east, @@ -49818,6 +49826,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/prison/garden) +"rOS" = ( +/obj/structure/cable, +/obj/structure/chair/office/light, +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/white, +/area/station/medical/virology) "rOY" = ( /obj/structure/mirror/directional/east, /obj/machinery/shower/directional/west, @@ -50751,6 +50769,17 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating/airless, /area/space/nearstation) +"sft" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/flasher/directional/north{ + id = "AI"; + pixel_x = -22 + }, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/turret_protected/ai) "sfu" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/orange/hidden, /turf/open/floor/iron/stairs/left{ @@ -51700,16 +51729,6 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/fore) -"syT" = ( -/obj/structure/cable, -/obj/structure/chair/office/light, -/obj/effect/landmark/start/virologist, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/white, -/area/station/medical/virology) "syV" = ( /obj/effect/turf_decal/arrows/white{ color = "#0000FF"; @@ -53434,10 +53453,6 @@ /obj/structure/bookcase/random/nonfiction, /turf/open/floor/wood, /area/station/service/library) -"tcd" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/closed/wall/r_wall, -/area/station/science/ordnance) "tck" = ( /obj/structure/extinguisher_cabinet/directional/north, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -54101,12 +54116,6 @@ /obj/effect/turf_decal/tile/red, /turf/open/floor/iron, /area/station/hallway/primary/fore) -"tnR" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_burn_chamber_input{ - dir = 1 - }, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "tot" = ( /obj/structure/table/wood, /obj/item/paper_bin{ @@ -55501,12 +55510,6 @@ /area/station/medical/virology) "tOT" = ( /obj/structure/table/glass, -/obj/item/scalpel{ - pixel_y = 12 - }, -/obj/item/circular_saw, -/obj/item/blood_filter, -/obj/item/bonesetter, /obj/machinery/button/door/directional/north{ id = "main_surgery"; name = "privacy shutters control" @@ -55897,17 +55900,6 @@ /obj/structure/table/wood, /turf/open/floor/carpet, /area/station/service/chapel/funeral) -"tVC" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/flasher/directional/north{ - id = "AI"; - pixel_x = -22 - }, -/obj/machinery/light/small/directional/north, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/turret_protected/ai) "tVG" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/machinery/firealarm/directional/north, @@ -58665,6 +58657,18 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/port) +"uTy" = ( +/obj/structure/table/glass, +/obj/machinery/reagentgrinder{ + pixel_y = 8 + }, +/obj/item/toy/figure/virologist{ + pixel_x = -8 + }, +/obj/effect/turf_decal/tile/green/half/contrasted, +/obj/machinery/light/small/directional/south, +/turf/open/floor/iron/white, +/area/station/medical/virology) "uTF" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/security/glass{ @@ -61184,18 +61188,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"vJs" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1 - }, -/obj/machinery/airlock_sensor/incinerator_ordmix{ - pixel_x = -24 - }, -/obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/engine, -/area/station/science/ordnance) "vJy" = ( /obj/structure/rack, /obj/item/stack/sheet/cardboard, @@ -61218,14 +61210,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/port) -"vJN" = ( -/obj/machinery/door/airlock/research/glass/incinerator/ordmix_exterior{ - name = "Burn Chamber Exterior Airlock" - }, -/obj/effect/mapping_helpers/airlock/locked, -/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "vJX" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -61426,10 +61410,6 @@ }, /turf/open/space, /area/space/nearstation) -"vOe" = ( -/obj/machinery/door/poddoor/incinerator_ordmix, -/turf/open/floor/engine/vacuum, -/area/station/science/ordnance) "vOh" = ( /obj/effect/turf_decal/stripes/end, /turf/open/floor/plating/airless, @@ -82761,8 +82741,8 @@ xjH pIU dno uKy -oPY -iOt +fIn +uTy xjH nzQ vol @@ -83539,7 +83519,7 @@ pWX eYE hcR gqV -syT +rOS vUH rUE suP @@ -99736,7 +99716,7 @@ fhi uEo fiS gyQ -tcd +eRn gyQ gyQ gyQ @@ -99993,11 +99973,11 @@ fhi xEU iqx xYZ -vJs +gil xYZ -qaW -fpM -vOe +oet +dXU +kgC lMJ uGg nFa @@ -100250,11 +100230,11 @@ fhi fhi twy nJA -htN -vJN -dke -hsY -vOe +nZL +bEv +cgP +rtj +kgC lMJ uGg nFa @@ -100507,11 +100487,11 @@ jvo aHH iYE dTN -jrJ +dEF dTN -tnR -fpM -vOe +cOT +dXU +kgC lMJ uGg wpn @@ -123304,7 +123284,7 @@ qyc jZC pan mbS -tVC +sft mCL aWO aYz diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 6a1d703aea4..7cf30212586 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -125,6 +125,14 @@ }, /turf/open/floor/iron/checker, /area/mine/laborcamp) +"aQ" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Mining Station Maintenance" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/turf/open/floor/plating, +/area/mine/maintenance/service) "aV" = ( /obj/structure/marker_beacon/teal, /obj/effect/turf_decal/sand/plating/volcanic, @@ -870,10 +878,6 @@ }, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) -"fP" = ( -/obj/structure/gulag_vent, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "fQ" = ( /turf/open/genturf, /area/lavaland/surface/outdoors/unexplored/danger) @@ -2834,12 +2838,6 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/iron/white, /area/mine/laborcamp/production) -"ps" = ( -/obj/structure/cable, -/obj/machinery/power/smes/full, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/mine/maintenance/service) "pu" = ( /obj/item/chair/stool{ pixel_x = -2; @@ -3416,15 +3414,6 @@ dir = 4 }, /area/mine/cafeteria) -"tg" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/airlock/maintenance{ - name = "Mining Station Maintenance" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, -/turf/open/floor/plating, -/area/mine/maintenance/service) "ti" = ( /obj/structure/table, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -3670,14 +3659,6 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white/smooth_corner, /area/mine/medical) -"vc" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Mining Station Maintenance" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/turf/open/floor/plating, -/area/mine/maintenance/service) "vd" = ( /obj/structure/railing/corner{ dir = 1 @@ -4107,16 +4088,6 @@ /obj/effect/turf_decal/sand/plating/volcanic, /turf/open/floor/plating/lavaland_atmos, /area/mine/maintenance/service/disposals) -"xI" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock/maintenance{ - name = "Mining Station Maintenance" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, -/turf/open/floor/plating, -/area/mine/maintenance/service/comms) "xJ" = ( /obj/machinery/vending/coffee, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -4164,6 +4135,10 @@ dir = 1 }, /area/mine/storage/public) +"xX" = ( +/obj/structure/gulag_vent, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "yc" = ( /obj/docking_port/stationary{ dir = 2; @@ -4490,6 +4465,14 @@ /obj/structure/lattice/catwalk, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"Af" = ( +/obj/machinery/mineral/processing_unit/gulag{ + dir = 1; + input_dir = 8; + output_dir = 4 + }, +/turf/open/floor/plating, +/area/mine/laborcamp/production) "Ai" = ( /obj/structure/stone_tile/cracked{ dir = 1 @@ -4957,11 +4940,6 @@ /obj/effect/turf_decal/sand/plating/volcanic, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) -"Ee" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/plating, -/area/mine/maintenance/labor) "Eg" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment, @@ -5083,6 +5061,15 @@ /obj/machinery/power/apc/auto_name/directional/east, /turf/open/floor/plating, /area/mine/maintenance/service) +"EV" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/maintenance{ + name = "Mining Station Maintenance" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, +/turf/open/floor/plating, +/area/mine/maintenance/service) "EX" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -5118,6 +5105,16 @@ "Ff" = ( /turf/open/floor/glass/reinforced, /area/mine/lounge) +"Fk" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/airlock/maintenance{ + name = "Mining Station Maintenance" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, +/turf/open/floor/plating, +/area/mine/maintenance/service/comms) "Fn" = ( /obj/structure/stone_tile/cracked{ dir = 4 @@ -6022,12 +6019,24 @@ /obj/machinery/camera/autoname/directional/north, /turf/open/floor/iron, /area/mine/lounge) +"KK" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/plating, +/area/mine/maintenance/labor) "KL" = ( /obj/effect/turf_decal/tile/bar/opposingcorners{ dir = 1 }, /turf/open/floor/iron/checker, /area/mine/cafeteria) +"KT" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Mining Station Maintenance" + }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, +/turf/open/floor/plating, +/area/mine/maintenance/service) "KV" = ( /obj/structure/table, /obj/machinery/light/directional/east, @@ -6253,14 +6262,6 @@ }, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) -"LT" = ( -/obj/machinery/mineral/processing_unit/gulag{ - dir = 1; - input_dir = 8; - output_dir = 4 - }, -/turf/open/floor/plating, -/area/mine/laborcamp/production) "LY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -7476,13 +7477,6 @@ }, /turf/open/floor/iron/dark/smooth_edge, /area/mine/laborcamp/security) -"TV" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Mining Station Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, -/turf/open/floor/plating, -/area/mine/maintenance/service) "TW" = ( /obj/machinery/door/airlock/maintenance{ name = "Mining Station Storage" @@ -8043,6 +8037,12 @@ dir = 4 }, /area/mine/production) +"Xk" = ( +/obj/structure/cable, +/obj/machinery/power/smes/full, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/mine/maintenance/service) "Xp" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -22573,7 +22573,7 @@ uU uU uU pU -fP +xX pU ff Gf @@ -24377,7 +24377,7 @@ Hd Nb NR Kv -LT +Af ff gm mN @@ -28238,7 +28238,7 @@ Zt Zt Zt Zt -Ee +KK ve RD RD @@ -37975,7 +37975,7 @@ ni rZ ni ON -TV +KT xD xD xD @@ -38485,12 +38485,12 @@ Ue AA gB ON -ps +Xk gq ER -vc +aQ YR -xI +Fk DF Kn xD @@ -39514,7 +39514,7 @@ ON ON ON ON -tg +EV ON ON ON diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 2e62e13527d..e87b973338c 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -800,16 +800,6 @@ /obj/structure/table, /turf/open/floor/iron/dark, /area/station/commons/storage/primary) -"ajz" = ( -/obj/structure/railing/corner, -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/red/filled/corner, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/duct, -/turf/open/floor/iron/dark/textured, -/area/station/commons/fitness) "ajB" = ( /obj/effect/spawner/random/trash/mopbucket, /obj/effect/spawner/random/trash/soap, @@ -7955,6 +7945,12 @@ /obj/structure/sign/poster/official/cleanliness/directional/east, /turf/open/floor/iron/dark/smooth_large, /area/station/hallway/secondary/entry) +"bWZ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/duct, +/obj/machinery/camera/autoname/directional/north, +/turf/open/floor/iron/dark/textured, +/area/station/commons/fitness) "bXd" = ( /obj/effect/turf_decal/trimline/purple/line, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12179,14 +12175,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/secondary/service) -"daa" = ( -/obj/machinery/camera/motion/directional/north{ - c_tag = "Minisat North" - }, -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/aisat/service) "dab" = ( /obj/effect/spawner/random/trash/garbage{ spawn_scatter_radius = 1 @@ -23327,6 +23315,14 @@ }, /turf/open/floor/pod/light, /area/station/maintenance/floor3/starboard/fore) +"gbO" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/turf_decal/tile/green/opposingcorners, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white, +/area/station/medical/virology) "gbR" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/structure/flora/bush/sunny/style_random, @@ -24752,12 +24748,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plastic, /area/station/security/prison/shower) -"gvV" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/duct, -/obj/machinery/camera/autoname/directional/north, -/turf/open/floor/iron/dark/textured, -/area/station/commons/fitness) "gvX" = ( /obj/structure/sign/poster/official/random/directional/east, /turf/open/floor/iron/dark/side{ @@ -27877,6 +27867,12 @@ /obj/item/airlock_painter/decal/tile, /turf/open/floor/iron/dark, /area/station/commons/storage/primary) +"hmg" = ( +/obj/machinery/firealarm/directional/west, +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/aisat_interior) "hmn" = ( /obj/effect/turf_decal/siding/thinplating_new{ dir = 4 @@ -33619,6 +33615,14 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/pod/light, /area/station/maintenance/floor3/starboard) +"iKW" = ( +/obj/machinery/camera/motion/directional/north{ + c_tag = "Minisat North" + }, +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/aisat/service) "iLy" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -44192,6 +44196,13 @@ }, /turf/open/floor/carpet/blue, /area/station/command/meeting_room) +"ltH" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/duct, +/obj/structure/sign/poster/contraband/hacking_guide/directional/north, +/obj/structure/extinguisher_cabinet/directional/west, +/turf/open/floor/iron/dark/textured, +/area/station/commons/fitness) "ltI" = ( /obj/effect/spawner/random/trash/graffiti{ pixel_y = -32 @@ -48598,13 +48609,6 @@ }, /turf/open/floor/plating, /area/station/medical/abandoned) -"mxS" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/duct, -/obj/structure/sign/poster/contraband/hacking_guide/directional/north, -/obj/structure/extinguisher_cabinet/directional/west, -/turf/open/floor/iron/dark/textured, -/area/station/commons/fitness) "mxT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -61919,11 +61923,6 @@ /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron/white, /area/station/science/lobby) -"pUB" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/aisat/service) "pUC" = ( /obj/effect/spawner/random/trash/graffiti, /turf/open/floor/pod/light, @@ -63807,6 +63806,16 @@ }, /turf/open/floor/pod/light, /area/station/maintenance/floor4/port/fore) +"qtA" = ( +/obj/structure/railing/corner, +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/duct, +/turf/open/floor/iron/dark/textured, +/area/station/commons/fitness) "qtH" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/filingcabinet/chestdrawer{ @@ -69135,6 +69144,11 @@ /obj/item/pen, /turf/open/floor/iron/dark, /area/station/security/interrogation) +"rOa" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/aisat/service) "rOb" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -70604,6 +70618,31 @@ dir = 1 }, /area/station/science/genetics) +"sjj" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/button/door/directional/west{ + id = "viro-inner"; + name = "Inner Virology Lockdown"; + pixel_y = -8 + }, +/obj/machinery/button/door/directional/west{ + id = "viro-outer"; + name = "Outer Virology Lockdown"; + pixel_y = 8 + }, +/obj/machinery/button/door/directional/west{ + id = "viro-iso"; + name = "Isolation Bolts"; + normaldoorcontrol = 1; + pixel_x = -36; + specialfunctions = 4 + }, +/obj/effect/turf_decal/tile/green/opposingcorners, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/white, +/area/station/medical/virology) "sjs" = ( /obj/effect/mapping_helpers/airlock/access/any/engineering/ce, /obj/machinery/door/airlock/engineering{ @@ -72945,31 +72984,6 @@ }, /turf/open/floor/pod/dark, /area/station/maintenance/floor3/port/fore) -"sPp" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/machinery/button/door/directional/west{ - id = "viro-inner"; - name = "Inner Virology Lockdown"; - pixel_y = -8 - }, -/obj/machinery/button/door/directional/west{ - id = "viro-outer"; - name = "Outer Virology Lockdown"; - pixel_y = 8 - }, -/obj/machinery/button/door/directional/west{ - id = "viro-iso"; - name = "Isolation Bolts"; - normaldoorcontrol = 1; - pixel_x = -36; - specialfunctions = 4 - }, -/obj/effect/turf_decal/tile/green/opposingcorners, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white, -/area/station/medical/virology) "sPs" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -76630,14 +76644,6 @@ }, /turf/open/floor/pod/dark, /area/station/maintenance/floor3/port/aft) -"tKr" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/effect/turf_decal/tile/green/opposingcorners, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/white, -/area/station/medical/virology) "tKs" = ( /obj/structure/curtain, /obj/structure/fans/tiny{ @@ -79797,12 +79803,6 @@ }, /turf/open/floor/iron/corner, /area/station/maintenance/solars/starboard/fore) -"uDR" = ( -/obj/machinery/firealarm/directional/west, -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/aisat_interior) "uDZ" = ( /obj/machinery/light/directional/north, /obj/machinery/airalarm/directional/north, @@ -195562,7 +195562,7 @@ mqc mRQ dVV xNy -sPp +sjj mcI rPC sJn @@ -196076,7 +196076,7 @@ iOA utl doh gJz -tKr +gbO hwQ piz aWO @@ -196590,7 +196590,7 @@ iOA dfU pZm wJy -tKr +gbO dVV bLm yhv @@ -258010,8 +258010,8 @@ qrd mcU xCX nWe -mxS -ajz +ltH +qtA lGo lNX lNX @@ -259038,7 +259038,7 @@ qrd oeQ xgb nWe -gvV +bWZ hwr oWt wJH @@ -335641,7 +335641,7 @@ aFj aFj sOy rZC -uDR +hmg knY sOy vyR @@ -336147,7 +336147,7 @@ oyh oyh aFj aFj -pUB +rOa kZZ kum kum @@ -336918,7 +336918,7 @@ dkh aFj aFj aFj -daa +iKW kZZ tOV knH diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 456cf46196e..a06d87aceff 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -3403,6 +3403,16 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/iron/grimy, /area/station/ai_monitored/turret_protected/aisat/foyer) +"aus" = ( +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 9 + }, +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/landmark/start/virologist, +/turf/open/floor/iron/dark, +/area/station/medical/virology) "auz" = ( /turf/closed/wall, /area/station/commons/vacant_room) @@ -28959,6 +28969,14 @@ /obj/structure/sign/warning/electric_shock/directional/north, /turf/open/floor/plating, /area/station/science/xenobiology) +"jqM" = ( +/obj/effect/landmark/event_spawn, +/obj/structure/chair/stool/directional/east, +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/white, +/area/station/medical/virology) "jqR" = ( /obj/structure/table, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -33445,16 +33463,6 @@ "kOE" = ( /turf/closed/wall, /area/station/security/detectives_office) -"kOL" = ( -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 9 - }, -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/landmark/start/virologist, -/turf/open/floor/iron/dark, -/area/station/medical/virology) "kPf" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -33966,13 +33974,6 @@ }, /turf/open/space/openspace, /area/station/solars/port) -"kXq" = ( -/obj/structure/cable/multilayer/multiz, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/ai_monitored/turret_protected/ai) "kXr" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -34727,11 +34728,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/construction/engineering) -"llW" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/ai) "lml" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos/pumproom) @@ -42893,6 +42889,11 @@ "oca" = ( /turf/closed/wall, /area/station/construction/mining/aux_base) +"ocl" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/ai) "ocn" = ( /obj/structure/table/wood, /obj/machinery/reagentgrinder, @@ -65311,6 +65312,13 @@ }, /turf/open/floor/plating, /area/station/construction/mining/aux_base) +"vTD" = ( +/obj/structure/cable/multilayer/multiz, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/ai_monitored/turret_protected/ai) "vTE" = ( /obj/machinery/camera{ dir = 9; @@ -67094,14 +67102,6 @@ }, /turf/open/floor/iron/freezer, /area/station/medical/coldroom) -"wDt" = ( -/obj/effect/landmark/event_spawn, -/obj/structure/chair/stool/directional/east, -/obj/effect/landmark/start/virologist, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/white, -/area/station/medical/virology) "wDv" = ( /obj/structure/rack, /obj/item/controller{ @@ -172639,7 +172639,7 @@ bWk svF xrG kow -wDt +jqM jqY jqY jqY @@ -173147,7 +173147,7 @@ whz aaa aaa ugt -kOL +aus vrJ aPS tMb @@ -185801,7 +185801,7 @@ jLx ffe mgi pIQ -llW +ocl xZx rSB dVM @@ -186314,7 +186314,7 @@ mYB njC aoh iUO -kXq +vTD lxi njC mEb diff --git a/_maps/shuttles/pirate_medieval.dmm b/_maps/shuttles/pirate_medieval.dmm new file mode 100644 index 00000000000..03441b8a652 --- /dev/null +++ b/_maps/shuttles/pirate_medieval.dmm @@ -0,0 +1,535 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"b" = ( +/obj/structure/table/wood, +/obj/item/stack/sheet/mineral/wood/fifty{ + pixel_y = 4 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"c" = ( +/obj/structure/fake_stairs/wood/directional/east, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"d" = ( +/obj/structure/fake_stairs/wood/directional/east, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/obj/structure/mineral_door/gold, +/turf/open/floor/stone, +/area/shuttle/pirate) +"e" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/trash/botanical_waste, +/obj/effect/spawner/random/trash/garbage, +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval, +/turf/open/floor/plating, +/area/shuttle/pirate) +"f" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/plating, +/area/shuttle/pirate) +"g" = ( +/obj/structure/fans/tiny, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/mineral_door/iron, +/turf/open/floor/plating, +/area/shuttle/pirate) +"h" = ( +/obj/structure/table/wood, +/obj/item/spear/military{ + pixel_y = 8; + pixel_x = -7 + }, +/obj/item/spear/military{ + pixel_y = 1; + pixel_x = -6 + }, +/obj/item/spear/military{ + pixel_y = -2; + pixel_x = 1 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"j" = ( +/obj/item/flashlight/lantern{ + light_on = 1 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"k" = ( +/obj/structure/table/wood, +/obj/item/restraints/legcuffs/bola/tactical, +/obj/item/restraints/legcuffs/bola/tactical, +/obj/item/restraints/legcuffs/bola/tactical, +/obj/item/restraints/legcuffs/bola, +/obj/item/restraints/legcuffs/bola, +/obj/item/restraints/legcuffs/bola, +/turf/open/floor/stone, +/area/shuttle/pirate) +"l" = ( +/obj/structure/fans/tiny, +/obj/structure/mineral_door/iron, +/turf/open/floor/stone, +/area/shuttle/pirate) +"m" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/arrows{ + dir = 8 + }, +/obj/effect/spawner/random/trash/cigbutt, +/obj/effect/spawner/random/trash/botanical_waste, +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plating, +/area/shuttle/pirate) +"n" = ( +/obj/effect/decal/cleanable/vomit/old, +/turf/open/floor/stone, +/area/shuttle/pirate) +"o" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/arrows{ + dir = 4 + }, +/obj/effect/spawner/random/trash/mess, +/obj/effect/spawner/random/trash/garbage, +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plating, +/area/shuttle/pirate) +"p" = ( +/turf/closed/wall/mineral/wood, +/area/shuttle/pirate) +"q" = ( +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval/warlord, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"r" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/trash/garbage, +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval, +/turf/open/floor/plating, +/area/shuttle/pirate) +"s" = ( +/obj/structure/fans/tiny, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/docking_port/mobile/pirate{ + launch_status = 0; + movement_force = list("KNOCKDOWN"=0,"THROW"=0); + name = "Pirate Ship"; + port_direction = 2 + }, +/obj/docking_port/stationary{ + dwidth = 11; + height = 16; + shuttle_id = "pirate_home"; + name = "Deep Space"; + width = 17 + }, +/obj/structure/mineral_door/iron, +/turf/open/floor/plating, +/area/shuttle/pirate) +"u" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/blood/gibs/limb, +/obj/effect/decal/cleanable/blood/gibs/body, +/obj/item/food/meat/slab/human/mutant/zombie, +/obj/item/kitchen/fork, +/turf/open/floor/stone, +/area/shuttle/pirate) +"v" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/plating, +/area/shuttle/pirate) +"w" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"x" = ( +/obj/structure/fake_stairs/wood/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/obj/structure/mineral_door/gold, +/turf/open/floor/stone, +/area/shuttle/pirate) +"y" = ( +/obj/machinery/shuttle_scrambler, +/turf/open/floor/stone, +/area/shuttle/pirate) +"z" = ( +/obj/structure/fans/tiny, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/mineral_door/iron, +/turf/open/floor/plating, +/area/shuttle/pirate) +"A" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/reagent_containers/cup/glass/bottle/vodka, +/turf/open/floor/plating, +/area/shuttle/pirate) +"C" = ( +/obj/machinery/airalarm/directional/west, +/obj/effect/mapping_helpers/airalarm/all_access, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/stone, +/area/shuttle/pirate) +"D" = ( +/obj/machinery/piratepad, +/turf/open/floor/stone, +/area/shuttle/pirate) +"E" = ( +/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, +/obj/structure/barricade/wooden/crude, +/turf/open/floor/stone, +/area/shuttle/pirate) +"F" = ( +/turf/open/floor/stone, +/area/shuttle/pirate) +"G" = ( +/obj/machinery/computer/piratepad_control, +/turf/open/floor/stone, +/area/shuttle/pirate) +"H" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/chair/wood/wings, +/turf/open/floor/stone, +/area/shuttle/pirate) +"I" = ( +/obj/structure/fake_stairs/wood/directional/west, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"J" = ( +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/item/food/burger/human, +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/glass/bottle/rum{ + pixel_y = 15; + pixel_x = -4 + }, +/obj/item/reagent_containers/cup/glass/bottle/rum{ + pixel_y = 8; + pixel_x = 8 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"K" = ( +/obj/structure/table/wood, +/obj/item/stack/medical/poultice{ + pixel_y = 6; + pixel_x = -3 + }, +/obj/item/stack/medical/poultice{ + pixel_y = -3; + pixel_x = 5 + }, +/obj/item/storage/medkit/fire, +/turf/open/floor/stone, +/area/shuttle/pirate) +"L" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"M" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/effect/spawner/random/trash/graffiti, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/plating, +/area/shuttle/pirate) +"N" = ( +/obj/machinery/computer/shuttle/pirate/drop_pod, +/turf/open/floor/stone, +/area/shuttle/pirate) +"O" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/fermenting_barrel/thermite, +/obj/item/reagent_containers/cup/beaker/large, +/obj/item/reagent_containers/cup/beaker/large, +/obj/item/reagent_containers/cup/beaker/large, +/turf/open/floor/stone, +/area/shuttle/pirate) +"P" = ( +/obj/effect/decal/cleanable/glass, +/turf/open/floor/stone, +/area/shuttle/pirate) +"Q" = ( +/obj/structure/closet/cabinet, +/obj/item/claymore, +/obj/item/shield/kite, +/obj/item/shield/kite, +/obj/item/shield/kite, +/turf/open/floor/stone, +/area/shuttle/pirate) +"R" = ( +/obj/machinery/atmospherics/components/tank/air{ + dir = 1 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"S" = ( +/obj/structure/frame/computer{ + anchored = 1 + }, +/obj/item/assault_pod/medieval, +/turf/open/floor/stone, +/area/shuttle/pirate) +"T" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"U" = ( +/obj/machinery/loot_locator, +/turf/open/floor/stone, +/area/shuttle/pirate) +"V" = ( +/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, +/obj/structure/barricade/wooden/crude, +/turf/open/floor/plating, +/area/shuttle/pirate) +"W" = ( +/obj/structure/table/wood, +/obj/item/radio/intercom{ + pixel_y = 5 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"X" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/obj/structure/table/wood, +/obj/item/bodypart/head/skeleton{ + pixel_x = -6 + }, +/obj/item/bodypart/head/skeleton{ + pixel_y = -2; + pixel_x = 5 + }, +/obj/item/bodypart/head/skeleton{ + pixel_x = 1; + pixel_y = 8 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) +"Y" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/stone, +/area/shuttle/pirate) +"Z" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/flashlight/lantern{ + light_on = 1 + }, +/turf/open/floor/stone, +/area/shuttle/pirate) + +(1,1,1) = {" +a +a +p +p +l +p +p +p +a +"} +(2,1,1) = {" +a +a +g +f +o +r +A +s +a +"} +(3,1,1) = {" +a +a +a +a +I +a +a +a +a +"} +(4,1,1) = {" +p +p +p +p +x +p +E +p +a +"} +(5,1,1) = {" +a +E +R +X +T +C +Q +p +p +"} +(6,1,1) = {" +p +p +W +F +T +j +Y +h +E +"} +(7,1,1) = {" +a +E +N +Y +T +Y +F +k +p +"} +(8,1,1) = {" +V +V +S +P +q +L +F +F +l +"} +(9,1,1) = {" +a +E +y +F +w +n +H +b +p +"} +(10,1,1) = {" +p +p +U +F +w +Z +u +K +E +"} +(11,1,1) = {" +a +E +G +D +T +O +J +p +p +"} +(12,1,1) = {" +p +p +p +p +d +p +E +p +a +"} +(13,1,1) = {" +a +a +a +a +c +a +a +a +a +"} +(14,1,1) = {" +a +a +z +M +m +e +v +z +a +"} +(15,1,1) = {" +a +a +p +p +l +p +p +p +a +"} diff --git a/code/__DEFINES/ai/ai.dm b/code/__DEFINES/ai/ai.dm index 24272a08d71..b8323c1c4e8 100644 --- a/code/__DEFINES/ai/ai.dm +++ b/code/__DEFINES/ai/ai.dm @@ -26,6 +26,16 @@ ///Flags for ai_behavior new() #define AI_CONTROLLER_INCOMPATIBLE (1<<0) +//Return flags for ai_behavior/perform() +///Update this behavior's cooldown +#define AI_BEHAVIOR_DELAY (1<<0) +///Finish the behavior successfully +#define AI_BEHAVIOR_SUCCEEDED (1<<1) +///Finish the behavior unsuccessfully +#define AI_BEHAVIOR_FAILED (1<<2) + +#define AI_BEHAVIOR_INSTANT (NONE) + ///Does this task require movement from the AI before it can be performed? #define AI_BEHAVIOR_REQUIRE_MOVEMENT (1<<0) ///Does this require the current_movement_target to be adjacent and in reach? diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 38d2ae92d9d..08993ad56de 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -19,8 +19,8 @@ ///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume) #define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf" -///from base of [/datum/controller/subsystem/materials/proc/InitializeMaterial]: (/datum/material) -#define COMSIG_MATERIALS_INIT_MAT "SSmaterials_init_mat" +///from base of [/datum/system/materials/proc/InitializeMaterial]: (/datum/material) +#define COMSIG_MATERIALS_INIT_MAT "DSmaterials_init_mat" ///from base of [/datum/component/multiple_lives/proc/respawn]: (mob/respawned_mob, gibbed, lives_left) #define COMSIG_ON_MULTIPLE_LIVES_RESPAWN "on_multiple_lives_respawn" diff --git a/code/__DEFINES/devices.dm b/code/__DEFINES/devices.dm index 8f98f040dbc..afd41570b5b 100644 --- a/code/__DEFINES/devices.dm +++ b/code/__DEFINES/devices.dm @@ -8,8 +8,8 @@ #define INSPECTOR_PRINT_SOUND_MODE_FAFAFOGGY 4 #define BANANIUM_CLOWN_INSPECTOR_PRINT_SOUND_MODE_LAST 4 #define CLOWN_INSPECTOR_PRINT_SOUND_MODE_LAST 4 -#define INSPECTOR_ENERGY_USAGE_HONK (15 KILO JOULES) -#define INSPECTOR_ENERGY_USAGE_NORMAL (5 KILO JOULES) +#define INSPECTOR_ENERGY_USAGE_HONK (0.015 * STANDARD_CELL_CHARGE) +#define INSPECTOR_ENERGY_USAGE_NORMAL (0.005 * STANDARD_CELL_CHARGE) #define INSPECTOR_TIME_MODE_SLOW 1 #define INSPECTOR_TIME_MODE_FAST 2 #define INSPECTOR_TIME_MODE_HONK 3 diff --git a/code/__DEFINES/lights.dm b/code/__DEFINES/lights.dm index 8830f919472..48d210fe031 100644 --- a/code/__DEFINES/lights.dm +++ b/code/__DEFINES/lights.dm @@ -1,5 +1,5 @@ ///How much power emergency lights will consume per tick -#define LIGHT_EMERGENCY_POWER_USE (0.1 KILO WATTS) +#define LIGHT_EMERGENCY_POWER_USE (0.0001 * STANDARD_CELL_RATE) // status values shared between lighting fixtures and items #define LIGHT_OK 0 #define LIGHT_EMPTY 1 diff --git a/code/__DEFINES/melee.dm b/code/__DEFINES/melee.dm index 9bef3e32d0d..7544b0176dc 100644 --- a/code/__DEFINES/melee.dm +++ b/code/__DEFINES/melee.dm @@ -1,6 +1,7 @@ //Martial arts defines #define MARTIALART_BOXING "boxing" +#define MARTIALART_EVIL_BOXING "evil boxing" #define MARTIALART_CQC "CQC" #define MARTIALART_KRAVMAGA "krav maga" #define MARTIALART_MUSHPUNCH "mushroom punch" diff --git a/code/__DEFINES/power.dm b/code/__DEFINES/power.dm index 0eda3669a71..b9752eac351 100644 --- a/code/__DEFINES/power.dm +++ b/code/__DEFINES/power.dm @@ -19,8 +19,12 @@ ///The joule is the standard unit of energy for this codebase. You can use this with other defines to clarify that it will not be multiplied by time. #define JOULES * JOULE -///The amount of energy, in joules, a standard powercell has. -#define STANDARD_CELL_CHARGE (1 MEGA JOULES) // 1 MJ. +///The capacity of a standard power cell +#define STANDARD_CELL_VALUE (1 MEGA) + ///The amount of energy, in joules, a standard powercell has. + #define STANDARD_CELL_CHARGE (STANDARD_CELL_VALUE JOULES) // 1 MJ. + ///The amount of power, in watts, a standard powercell can give. + #define STANDARD_CELL_RATE (STANDARD_CELL_VALUE WATTS) // 1 MW. GLOBAL_VAR_INIT(CHARGELEVEL, 0.01) // Cap for how fast cells charge, as a percentage per second (.01 means cellcharge is capped to 1% per second) diff --git a/code/__DEFINES/pronouns.dm b/code/__DEFINES/pronouns.dm new file mode 100644 index 00000000000..c0515426e35 --- /dev/null +++ b/code/__DEFINES/pronouns.dm @@ -0,0 +1,40 @@ +/// she, he, they, it "%PRONOUN_they" = "p_they" +/// She, He, They, It "%PRONOUN_They" = "p_They" +/// her, his, their, its "%PRONOUN_their" = "p_their" +/// Her, His, Their, Its "%PRONOUN_Their" = "p_Their" +/// hers, his, theirs, its "%PRONOUN_theirs" = "p_theirs" +/// Hers, His, Theirs, Its "%PRONOUN_Theirs" = "p_Theirs" +/// her, him, them, it "%PRONOUN_them" = "p_them" +/// Her, Him, Them, It "%PRONOUN_Them" = "p_Them" +/// has, have "%PRONOUN_have" = "p_have" +/// is, are "%PRONOUN_are" = "p_are" +/// was, were "%PRONOUN_were" = "p_were" +/// does, do "%PRONOUN_do" = "p_do" +/// she has, he has, they have, it has "%PRONOUN_theyve" = "p_theyve" +/// She has, He has, They have, It has "%PRONOUN_Theyve" = "p_Theyve" +/// she is, he is, they are, it is "%PRONOUN_theyre" = "p_theyre" +/// She is, He is, They are, It is "%PRONOUN_Theyre" = "p_Theyre" +/// s, null (she looks, they look) "%PRONOUN_s" = "p_s" +/// es, null (she goes, they go) "%PRONOUN_es" = "p_es" + +/// A list for all the pronoun procs, if you need to iterate or search through it or something. +#define ALL_PRONOUNS list( \ + "%PRONOUN_they" = TYPE_PROC_REF(/datum, p_they), \ + "%PRONOUN_They" = TYPE_PROC_REF(/datum, p_They), \ + "%PRONOUN_their" = TYPE_PROC_REF(/datum, p_their), \ + "%PRONOUN_Their" = TYPE_PROC_REF(/datum, p_Their), \ + "%PRONOUN_theirs" = TYPE_PROC_REF(/datum, p_theirs), \ + "%PRONOUN_Theirs" = TYPE_PROC_REF(/datum, p_Theirs), \ + "%PRONOUN_them" = TYPE_PROC_REF(/datum, p_them), \ + "%PRONOUN_Them" = TYPE_PROC_REF(/datum, p_Them), \ + "%PRONOUN_have" = TYPE_PROC_REF(/datum, p_have), \ + "%PRONOUN_are" = TYPE_PROC_REF(/datum, p_are), \ + "%PRONOUN_were" = TYPE_PROC_REF(/datum, p_were), \ + "%PRONOUN_do" = TYPE_PROC_REF(/datum, p_do), \ + "%PRONOUN_theyve" = TYPE_PROC_REF(/datum, p_theyve), \ + "%PRONOUN_Theyve" = TYPE_PROC_REF(/datum, p_Theyve), \ + "%PRONOUN_theyre" = TYPE_PROC_REF(/datum, p_theyre), \ + "%PRONOUN_Theyre" = TYPE_PROC_REF(/datum, p_Theyre), \ + "%PRONOUN_s" = TYPE_PROC_REF(/datum, p_s), \ + "%PRONOUN_es" = TYPE_PROC_REF(/datum, p_es) \ +) diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index a24a929391f..3f84955fe98 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -2,7 +2,7 @@ #define CHANNEL_LOBBYMUSIC 1024 #define CHANNEL_ADMIN 1023 #define CHANNEL_VOX 1022 -#define CHANNEL_JUKEBOX 1011 // SKYRAT EDIT - JUKEBOX - ORIGINAL: #define CHANNEL_JUKEBOX 1021 +#define CHANNEL_JUKEBOX 1021 #define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats #define CHANNEL_BOSS_MUSIC 1019 #define CHANNEL_AMBIENCE 1018 @@ -10,6 +10,11 @@ #define CHANNEL_TRAITOR 1016 #define CHANNEL_CHARGED_SPELL 1015 #define CHANNEL_ELEVATOR 1014 +//THIS SHOULD ALWAYS BE THE LOWEST ONE! +//KEEP IT UPDATED +#define CHANNEL_HIGHEST_AVAILABLE 1013 + +#define MAX_INSTRUMENT_CHANNELS (128 * 6) // SKYRAT EDIT START - JUKEBOX #define CHANNEL_JUKEBOX_START 1006 @@ -28,13 +33,6 @@ ///The default exponent of sound falloff #define SOUND_FALLOFF_EXPONENT 6 -//THIS SHOULD ALWAYS BE THE LOWEST ONE! -//KEEP IT UPDATED - -#define CHANNEL_HIGHEST_AVAILABLE 1005 //SKYRAT EDIT CHANGE - JUKEBOX > ORIGINAL VALUE 1015 - -#define MAX_INSTRUMENT_CHANNELS (128 * 6) - #define SOUND_MINIMUM_PRESSURE 10 #define INTERACTION_SOUND_RANGE_MODIFIER -3 diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 99230559f7e..132ae196239 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -2,7 +2,7 @@ #define TOOL_CROWBAR "crowbar" #define TOOL_MULTITOOL "multitool" #define TOOL_SCREWDRIVER "screwdriver" -#define TOOL_WIRECUTTER "wirecutter" +#define TOOL_WIRECUTTER "cutters" #define TOOL_WRENCH "wrench" #define TOOL_WELDER "welder" #define TOOL_ANALYZER "analyzer" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 6a83f33083a..f2cb9069fb6 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -520,6 +520,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Prevents you from twohanding weapons. #define TRAIT_NO_TWOHANDING "no_twohanding" +/// Improves boxing damage against boxers and athletics experience gain +#define TRAIT_STRENGTH "strength" + +/// Increases the duration of having exercised +#define TRAIT_STIMMED "stimmed" + +/// Indicates that the target is able to be boxed at a boxer's full power. +#define TRAIT_BOXING_READY "boxing_ready" + /// Halves the time of tying a tie. #define TRAIT_FAST_TYING "fast_tying" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 56bcbf3c90d..278510bd23f 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -137,6 +137,7 @@ #define LOCKED_HELMET_TRAIT "locked-helmet" #define NINJA_SUIT_TRAIT "ninja-suit" #define SLEEPING_CARP_TRAIT "sleeping_carp" +#define BOXING_TRAIT "boxing" #define TIMESTOP_TRAIT "timestop" #define LIFECANDLE_TRAIT "lifecandle" #define VENTCRAWLING_TRAIT "ventcrawling" diff --git a/code/__HELPERS/construction.dm b/code/__HELPERS/construction.dm index f7b0ece13f8..cf38f690c26 100644 --- a/code/__HELPERS/construction.dm +++ b/code/__HELPERS/construction.dm @@ -2,7 +2,7 @@ #define OPTIMAL_COST(cost)(max(1, round(cost))) /// Wrapper for fetching material references. Exists exclusively so that people don't need to wrap everything in a list every time. -#define GET_MATERIAL_REF(arguments...) SSmaterials._GetMaterialRef(list(##arguments)) +#define GET_MATERIAL_REF(arguments...) DSmaterials._GetMaterialRef(list(##arguments)) // Wrapper to convert material name into its source name #define MATERIAL_SOURCE(mat) "[mat.name]_material" diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index d16b91ee4c8..30626bc0a55 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -165,8 +165,8 @@ GLOB.crafting_recipes += recipe var/list/material_stack_recipes = list( - SSmaterials.base_stack_recipes, - SSmaterials.rigid_stack_recipes, + DSmaterials.base_stack_recipes, + DSmaterials.rigid_stack_recipes, ) for(var/list/recipe_list in material_stack_recipes) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 1b93f024285..a6b23e08b49 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -251,23 +251,23 @@ GLOBAL_LIST_EMPTY(species_list) * * Checks that `user` does not move, change hands, get stunned, etc. for the * given `delay`. Returns `TRUE` on success or `FALSE` on failure. - * + * * @param {mob} user - The mob performing the action. - * + * * @param {number} delay - The time in deciseconds. Use the SECONDS define for readability. `1 SECONDS` is 10 deciseconds. - * + * * @param {atom} target - The target of the action. This is where the progressbar will display. - * + * * @param {flag} timed_action_flags - Flags to control the behavior of the timed action. - * + * * @param {boolean} progress - Whether to display a progress bar / cogbar. - * + * * @param {datum/callback} extra_checks - Additional checks to perform before the action is executed. - * + * * @param {string} interaction_key - The assoc key under which the do_after is capped, with max_interact_count being the cap. Interaction key will default to target if not set. - * + * * @param {number} max_interact_count - The maximum amount of interactions allowed. - * + * * @param {boolean} hidden - By default, any action 1 second or longer shows a cog over the user while it is in progress. If hidden is set to TRUE, the cog will not be shown. */ /proc/do_after(mob/user, delay, atom/target, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks, interaction_key, max_interact_count = 1, hidden = FALSE) @@ -288,7 +288,7 @@ GLOBAL_LIST_EMPTY(species_list) var/atom/target_loc = target?.loc var/drifting = FALSE - if(SSmove_manager.processing_on(user, SSspacedrift)) + if(DSmove_manager.processing_on(user, SSspacedrift)) drifting = TRUE var/holding = user.get_active_held_item() @@ -317,7 +317,7 @@ GLOBAL_LIST_EMPTY(species_list) if(!QDELETED(progbar)) progbar.update(world.time - starttime) - if(drifting && !SSmove_manager.processing_on(user, SSspacedrift)) + if(drifting && !DSmove_manager.processing_on(user, SSspacedrift)) drifting = FALSE user_loc = user.loc @@ -337,7 +337,7 @@ GLOBAL_LIST_EMPTY(species_list) if(!QDELETED(progbar)) progbar.end_progress() - + cog?.remove() if(interaction_key) diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index d675b252796..380a8707fbe 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -107,7 +107,7 @@ message.title = title message.content = text - SScommunications.send_message(message) + DScommunications.send_message(message) /** * Sends a minor annoucement to players. diff --git a/code/__HELPERS/pronouns.dm b/code/__HELPERS/pronouns.dm index df84c1cdcf4..fe2357d6ce4 100644 --- a/code/__HELPERS/pronouns.dm +++ b/code/__HELPERS/pronouns.dm @@ -1,5 +1,8 @@ +#define GET_TARGET_PRONOUN(target, pronoun, gender) call(target, ALL_PRONOUNS[pronoun])(gender) + //pronoun procs, for getting pronouns without using the text macros that only work in certain positions //datums don't have gender, but most of their subtypes do! + /datum/proc/p_they(temp_gender) return "it" @@ -69,6 +72,26 @@ else return "s" +/// A proc to replace pronouns in a string with the appropriate pronouns for a target atom. +/// Uses associative list access from a __DEFINE list, since associative access is slightly +/// faster +/datum/proc/REPLACE_PRONOUNS(target_string, atom/targeted_atom, targeted_gender = null) + /// If someone specifies targeted_gender we choose that, + /// otherwise we go off the gender of our object + var/gender + if(targeted_gender) + if(!istext(targeted_gender) || !(targeted_gender in list(MALE, FEMALE, PLURAL, NEUTER))) + stack_trace("REPLACE_PRONOUNS called with improper parameters.") + return + gender = targeted_gender + else + gender = targeted_atom.gender + var/regex/pronoun_regex = regex("%PRONOUN(_(they|They|their|Their|theirs|Theirs|them|Them|have|are|were|do|theyve|Theyve|theyre|Theyre|s|es))") + while(pronoun_regex.Find(target_string)) + target_string = pronoun_regex.Replace(target_string, GET_TARGET_PRONOUN(targeted_atom, pronoun_regex.match, gender)) + return target_string + + //like clients, which do have gender. /client/p_they(temp_gender) if(!temp_gender) diff --git a/code/__HELPERS/view.dm b/code/__HELPERS/view.dm index dc25dcc0249..30e8bc8f9f9 100644 --- a/code/__HELPERS/view.dm +++ b/code/__HELPERS/view.dm @@ -20,8 +20,23 @@ view_info[2] *= world.icon_size return view_info -/proc/in_view_range(mob/user, atom/A) - var/list/view_range = getviewsize(user.client.view) - var/turf/source = get_turf(user) - var/turf/target = get_turf(A) - return ISINRANGE(target.x, source.x - view_range[1], source.x + view_range[1]) && ISINRANGE(target.y, source.y - view_range[1], source.y + view_range[1]) +/** +* Frustrated with bugs in can_see(), this instead uses viewers for a much more effective approach. +* ### Things to note: +* - Src/source must be a mob. `viewers()` returns mobs. +* - Adjacent objects are always considered visible. +*/ + +/// The default tile-distance between two atoms for one to consider the other as visible. +#define DEFAULT_SIGHT_DISTANCE 7 + +/// Basic check to see if the src object can see the target object. +#define CAN_I_SEE(target) ((src in viewers(DEFAULT_SIGHT_DISTANCE, target)) || in_range(target, src)) + + +/// Checks the visibility between two other objects. +#define CAN_THEY_SEE(target, source) ((source in viewers(DEFAULT_SIGHT_DISTANCE, target)) || in_range(target, source)) + + +/// Further checks distance between source and target. +#define CAN_SEE_RANGED(target, source, dist) ((source in viewers(dist, target)) || in_range(target, source)) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index e0f07ab2835..d298d24e3a0 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -343,6 +343,19 @@ DEFINE_BITFIELD(vis_flags, list( "VIS_UNDERLAY" = VIS_UNDERLAY, )) +// I am so sorry. Required because vis_flags is both undefinable and unreadable on mutable_appearance +// But we need to display them anyway. See /mutable_appearance/appearance_mirror +DEFINE_BITFIELD(_vis_flags, list( + "VIS_HIDE" = VIS_HIDE, + "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, + "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, + "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, + "VIS_INHERIT_ID" = VIS_INHERIT_ID, + "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, + "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, + "VIS_UNDERLAY" = VIS_UNDERLAY, +)) + DEFINE_BITFIELD(zap_flags, list( "ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES, "ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE, diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index f67ed4f6d07..9e3c2ed7ee0 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -498,6 +498,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_XRAY_VISION" = TRAIT_XRAY_VISION, "TRAIT_DISCO_DANCER" = TRAIT_DISCO_DANCER, "TRAIT_MAFIAINITIATE" = TRAIT_MAFIAINITIATE, + "TRAIT_STRENGTH" = TRAIT_STRENGTH, + "TRAIT_STIMMED" = TRAIT_STIMMED, + "TRAIT_BOXING_READY" = TRAIT_BOXING_READY, ), /obj/item = list( "TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING, diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 0a6e54a46e0..ae5cc36b8ad 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -55,7 +55,7 @@ ShiftClickOn(A) return if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt) - A.ai_click_alt(src) + ai_base_click_alt(A) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) @@ -121,6 +121,24 @@ target.AICtrlClick(src) +/// Reimplementation of base_click_alt for AI +/mob/living/silicon/ai/proc/ai_base_click_alt(atom/target) + // If for some reason we can't alt click + if(SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, target) & COMSIG_MOB_CANCEL_CLICKON) + return + + if(!isturf(target) && can_perform_action(target, (target.interaction_flags_click | SILENT_ADJACENCY))) + // Signal intercept + if(SEND_SIGNAL(target, COMSIG_CLICK_ALT, src) & CLICK_ACTION_ANY) + return + + // AI alt click interaction succeeds + if(target.ai_click_alt(src) & CLICK_ACTION_ANY) + return + + client.loot_panel.open(get_turf(target)) + + /* The following criminally helpful code is just the previous code cleaned up; I have no idea why it was in atoms.dm instead of respective files. @@ -132,6 +150,7 @@ return /atom/proc/ai_click_alt(mob/living/silicon/ai/user) + SHOULD_CALL_PARENT(FALSE) return /atom/proc/AIShiftClick(mob/living/silicon/ai/user) @@ -149,12 +168,13 @@ /obj/machinery/door/airlock/ai_click_alt(mob/living/silicon/ai/user) if(obj_flags & EMAGGED) - return + return NONE if(!secondsElectrified) shock_perm(user) else shock_restore(user) + return CLICK_ACTION_SUCCESS /obj/machinery/door/airlock/AIShiftClick(mob/living/silicon/ai/user) // Opens and closes doors! if(obj_flags & EMAGGED) @@ -218,10 +238,10 @@ /// Toggle APC equipment settings /obj/machinery/power/apc/ai_click_alt(mob/living/silicon/ai/user) if(!can_use(user, loud = TRUE)) - return + return NONE if(!is_operational || failure_timer) - return + return CLICK_ACTION_BLOCKING equipment = equipment ? APC_CHANNEL_OFF : APC_CHANNEL_ON if (user) @@ -231,6 +251,7 @@ user.log_message("turned [enabled_or_disabled] the [src] equipment settings", LOG_GAME) update_appearance() update() + return CLICK_ACTION_SUCCESS /obj/machinery/power/apc/attack_ai_secondary(mob/living/silicon/user, list/modifiers) if(!can_use(user, loud = TRUE)) @@ -242,8 +263,9 @@ /* AI Turrets */ /obj/machinery/turretid/ai_click_alt(mob/living/silicon/ai/user) //toggles lethal on turrets if(ailock) - return + return CLICK_ACTION_BLOCKING toggle_lethal(user) + return CLICK_ACTION_SUCCESS /obj/machinery/turretid/AICtrlClick(mob/living/silicon/ai/user) //turns off/on Turrets if(ailock) @@ -256,6 +278,7 @@ balloon_alert(user, "disrupted all active calls") add_hiddenprint(user) hangup_all_calls() + return CLICK_ACTION_SUCCESS // // Override TurfAdjacent for AltClicking diff --git a/code/_onclick/click_alt.dm b/code/_onclick/click_alt.dm index 16c8e843995..11419a60816 100644 --- a/code/_onclick/click_alt.dm +++ b/code/_onclick/click_alt.dm @@ -6,32 +6,36 @@ /mob/proc/base_click_alt(atom/target) SHOULD_NOT_OVERRIDE(TRUE) - var/turf/tile = isturf(target) ? target : get_turf(target) - - if(isobserver(src) || isrevenant(src)) - open_lootpanel(tile) + // Check if they've hooked in to prevent src from alt clicking anything + if(SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, target) & COMSIG_MOB_CANCEL_CLICKON) return + // Is it visible (and we're not wearing it (our clothes are invisible))? + if(!(src in viewers(7, target)) && !CanReach(target)) + return + + var/turf/tile = get_turf(target) + + // Ghosties just see loot + if(isobserver(src) || isrevenant(src)) + client.loot_panel.open(tile) + return + + // Turfs don't have a click_alt currently, so this saves some time. if(!isturf(target) && can_perform_action(target, (target.interaction_flags_click | SILENT_ADJACENCY))) + // If it has a signal handler that returns a click action, done. if(SEND_SIGNAL(target, COMSIG_CLICK_ALT, src) & CLICK_ACTION_ANY) return + // If it has a custom click_alt that returns success/block, done. if(target.click_alt(src) & CLICK_ACTION_ANY) return - open_lootpanel(tile) - - -/// Helper for opening the lootpanel -/mob/proc/open_lootpanel(turf/target) + // No alt clicking to view turf from beneath if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING)) return - var/datum/lootpanel/panel = client?.loot_panel - if(isnull(panel)) - return - - panel.open(target) + client.loot_panel.open(tile) /** diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index a1ca5ebf85a..d5ba848fc8d 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -387,7 +387,7 @@ glasses.add_mob_blood(src) update_worn_glasses() - if(!attacking_item.get_sharpness() && !HAS_TRAIT(src, TRAIT_HEAD_INJURY_BLOCKED)) + if(!attacking_item.get_sharpness() && !HAS_TRAIT(src, TRAIT_HEAD_INJURY_BLOCKED) && attacking_item.damtype == BRUTE) if(prob(damage_done)) adjustOrganLoss(ORGAN_SLOT_BRAIN, 20) if(stat == CONSCIOUS) @@ -417,7 +417,7 @@ w_uniform.add_mob_blood(src) update_worn_undersuit() - if(stat == CONSCIOUS && !attacking_item.get_sharpness() && !HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)) + if(stat == CONSCIOUS && !attacking_item.get_sharpness() && !HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) && attacking_item.damtype == BRUTE) if(prob(damage_done)) visible_message( span_danger("[src] is knocked down!"), diff --git a/code/controllers/master.dm b/code/controllers/master.dm index d7996890f98..5686de234bf 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -138,7 +138,7 @@ GLOBAL_REAL(Master, /datum/controller/master) ss.Shutdown() log_world("Shutdown complete") -ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "View the current states of the Subsystem Controllers.", ADMIN_CATEGORY_SERVER) +ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "View the current states of the Subsystem Controllers.", ADMIN_CATEGORY_DEBUG) Master.ui_interact(user.mob) /datum/controller/master/ui_status(mob/user, datum/ui_state/state) diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index 29451ea10ed..736b55d7c99 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -317,7 +317,7 @@ SUBSYSTEM_DEF(dynamic) SSticker.news_report = SSshuttle.emergency?.is_hijacked() ? SHUTTLE_HIJACK : STATION_EVACUATED /datum/controller/subsystem/dynamic/proc/send_intercept() - if(SScommunications.block_command_report) //If we don't want the report to be printed just yet, we put it off until it's ready + if(DScommunications.block_command_report) //If we don't want the report to be printed just yet, we put it off until it's ready addtimer(CALLBACK(src, PROC_REF(send_intercept)), 10 SECONDS) return @@ -349,10 +349,10 @@ SUBSYSTEM_DEF(dynamic) if(trait_list_strings.len > 0) . += "
Identified shift divergencies:
" + trait_list_strings.Join() - if(length(SScommunications.command_report_footnotes)) + if(length(DScommunications.command_report_footnotes)) var/footnote_pile = "" - for(var/datum/command_footnote/footnote in SScommunications.command_report_footnotes) + for(var/datum/command_footnote/footnote in DScommunications.command_report_footnotes) footnote_pile += "[footnote.message]
" footnote_pile += "[footnote.signature]
" footnote_pile += "
" diff --git a/code/controllers/subsystem/movement/cliff_falling.dm b/code/controllers/subsystem/movement/cliff_falling.dm index 80e2f236eb7..65089f0ea1b 100644 --- a/code/controllers/subsystem/movement/cliff_falling.dm +++ b/code/controllers/subsystem/movement/cliff_falling.dm @@ -10,7 +10,7 @@ MOVEMENT_SUBSYSTEM_DEF(cliff_falling) /datum/controller/subsystem/movement/cliff_falling/proc/start_falling(atom/movable/faller, turf/open/cliff/cliff) // Make them move - var/mover = SSmove_manager.move(moving = faller, direction = cliff.fall_direction, delay = cliff.fall_speed, subsystem = src, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_OUTSIDE_CONTROL | MOVEMENT_LOOP_NO_DIR_UPDATE) + var/mover = DSmove_manager.move(moving = faller, direction = cliff.fall_direction, delay = cliff.fall_speed, subsystem = src, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_OUTSIDE_CONTROL | MOVEMENT_LOOP_NO_DIR_UPDATE) cliff_grinders[faller] = mover diff --git a/code/controllers/subsystem/movement/movement_types.dm b/code/controllers/subsystem/movement/movement_types.dm index ebb12c84e4b..3567e881b14 100644 --- a/code/controllers/subsystem/movement/movement_types.dm +++ b/code/controllers/subsystem/movement/movement_types.dm @@ -162,7 +162,7 @@ status &= ~MOVELOOP_STATUS_PAUSED ///Removes the atom from some movement subsystem. Defaults to SSmovement -/datum/controller/subsystem/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement) +/datum/system/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement) var/datum/movement_packet/our_info = moving.move_packet if(!our_info) return FALSE @@ -183,7 +183,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/move, priority, flags, extra_info, delay, timeout, direction) ///Replacement for walk() @@ -224,7 +224,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/force_move_dir(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/force_move_dir(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/move/force, priority, flags, extra_info, delay, timeout, direction) /datum/move_loop/move/force @@ -281,7 +281,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/force_move(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/force_move(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/force_move, priority, flags, extra_info, delay, timeout, chasing) ///Used for force-move loops @@ -315,7 +315,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/jps_move(moving, +/datum/system/move_manager/proc/jps_move(moving, chasing, delay, timeout, @@ -493,7 +493,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_to(moving, chasing, min_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_to(moving, chasing, min_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/dist_bound/move_to, priority, flags, extra_info, delay, timeout, chasing, min_dist) ///Wrapper around walk_to() @@ -527,7 +527,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_away(moving, chasing, max_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_away(moving, chasing, max_dist, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/dist_bound/move_away, priority, flags, extra_info, delay, timeout, chasing, max_dist) ///Wrapper around walk_away() @@ -562,7 +562,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_towards(moving, chasing, delay, home, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_towards(moving, chasing, delay, home, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/move_towards, priority, flags, extra_info, delay, timeout, chasing, home) /** @@ -581,7 +581,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/home_onto(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/home_onto(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) return move_towards(moving, chasing, delay, TRUE, timeout, subsystem, priority, flags, extra_info) ///Used as a alternative to walk_towards @@ -717,7 +717,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_towards_legacy(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_towards_legacy(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/has_target/move_towards_budget, priority, flags, extra_info, delay, timeout, chasing) ///The actual implementation of walk_towards() @@ -743,7 +743,7 @@ * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm */ -/datum/controller/subsystem/move_manager/proc/freeze(moving, halted_turf, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/freeze(moving, halted_turf, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/freeze, priority, flags, extra_info, delay, timeout, halted_turf) /// As close as you can get to a "do-nothing" move loop, the pure intention of this is to absolutely resist all and any automated movement until the move loop times out. @@ -767,7 +767,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info) if(!directions) directions = GLOB.alldirs return add_to_loop(moving, subsystem, /datum/move_loop/move_rand, priority, flags, extra_info, delay, timeout, directions) @@ -819,7 +819,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_to_rand(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_to_rand(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/move_to_rand, priority, flags, extra_info, delay, timeout) ///Wrapper around step_rand @@ -845,7 +845,7 @@ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm * **/ -/datum/controller/subsystem/move_manager/proc/move_disposals(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) +/datum/system/move_manager/proc/move_disposals(moving, delay, timeout, subsystem, priority, flags, datum/extra_info) return add_to_loop(moving, subsystem, /datum/move_loop/disposal_holder, priority, flags, extra_info, delay, timeout) /// Disposal holders need to move through a chain of pipes diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 7b1394ada16..a35798ce627 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -190,6 +190,7 @@ SUBSYSTEM_DEF(statpanels) list("World Time:", "[world.time]"), list("Globals:", GLOB.stat_entry(), text_ref(GLOB)), list("[config]:", config.stat_entry(), text_ref(config)), + list("Datasystem Manager:", "Edit", text_ref(SysMgr)), list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), list("Master Controller:", Master.stat_entry(), text_ref(Master)), list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)), diff --git a/code/datums/actions/mobs/charge.dm b/code/datums/actions/mobs/charge.dm index 3cca055a541..07c6330c71a 100644 --- a/code/datums/actions/mobs/charge.dm +++ b/code/datums/actions/mobs/charge.dm @@ -44,7 +44,7 @@ if(charger in charging) // Stop any existing charging, this'll clean things up properly - SSmove_manager.stop_looping(charger) + DSmove_manager.stop_looping(charger) charging += charger actively_moving = FALSE @@ -60,7 +60,7 @@ var/time_to_hit = min(get_dist(charger, target), charge_distance) * charge_speed - var/datum/move_loop/new_loop = SSmove_manager.home_onto(charger, target, delay = charge_speed, timeout = time_to_hit, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/new_loop = DSmove_manager.home_onto(charger, target, delay = charge_speed, timeout = time_to_hit, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) if(!new_loop) return RegisterSignal(new_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move), override = TRUE) @@ -96,7 +96,7 @@ /datum/action/cooldown/mob_cooldown/charge/update_status_on_signal(mob/source, new_stat, old_stat) . = ..() if(new_stat == DEAD) - SSmove_manager.stop_looping(source) //This will cause the loop to qdel, triggering an end to our charging + DSmove_manager.stop_looping(source) //This will cause the loop to qdel, triggering an end to our charging /datum/action/cooldown/mob_cooldown/charge/proc/do_charge_indicator(atom/charger, atom/charge_target) var/turf/target_turf = get_turf(charge_target) diff --git a/code/datums/actions/mobs/charge_apc.dm b/code/datums/actions/mobs/charge_apc.dm index 47436beab76..8086ba72207 100644 --- a/code/datums/actions/mobs/charge_apc.dm +++ b/code/datums/actions/mobs/charge_apc.dm @@ -1,5 +1,5 @@ ///how much charge are we giving off to an APC? -#define CHARGE_AMOUNT (80 KILO JOULES) +#define CHARGE_AMOUNT (0.08 * STANDARD_CELL_CHARGE) /datum/action/cooldown/mob_cooldown/charge_apc name = "Charge APCs" diff --git a/code/datums/ai/_ai_behavior.dm b/code/datums/ai/_ai_behavior.dm index 233b57b1577..eb8f7370dc2 100644 --- a/code/datums/ai/_ai_behavior.dm +++ b/code/datums/ai/_ai_behavior.dm @@ -19,8 +19,8 @@ return TRUE ///Called by the AI controller when this action is performed +///Returns a set of flags defined in [code/__DEFINES/ai/ai.dm] /datum/ai_behavior/proc/perform(seconds_per_tick, datum/ai_controller/controller, ...) - controller.behavior_cooldowns[src] = world.time + get_cooldown(controller) return ///Called when the action is finished. This needs the same args as perform besides the default ones diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index 806009398ee..c5717ceb044 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -279,7 +279,7 @@ multiple modular subtrees with behaviors /datum/ai_controller/process(seconds_per_tick) if(!able_to_run()) - SSmove_manager.stop_looping(pawn) //stop moving + DSmove_manager.stop_looping(pawn) //stop moving return //this should remove them from processing in the future through event-based stuff. if(!LAZYLEN(current_behaviors) && idle_behavior) @@ -359,14 +359,12 @@ multiple modular subtrees with behaviors break SEND_SIGNAL(src, COMSIG_AI_CONTROLLER_PICKED_BEHAVIORS, current_behaviors, planned_behaviors) - for(var/datum/ai_behavior/current_behavior as anything in current_behaviors) - if(LAZYACCESS(planned_behaviors, current_behavior)) - continue + for(var/datum/ai_behavior/forgotten_behavior as anything in current_behaviors - planned_behaviors) var/list/arguments = list(src, FALSE) var/list/stored_arguments = behavior_args[type] if(stored_arguments) arguments += stored_arguments - current_behavior.finish_action(arglist(arguments)) + forgotten_behavior.finish_action(arglist(arguments)) ///This proc handles changing ai status, and starts/stops processing if required. /datum/ai_controller/proc/set_ai_status(new_ai_status) @@ -381,10 +379,7 @@ multiple modular subtrees with behaviors switch(ai_status) if(AI_STATUS_ON) START_PROCESSING(SSai_behaviors, src) - if(AI_STATUS_OFF) - STOP_PROCESSING(SSai_behaviors, src) - CancelActions() - if(AI_STATUS_IDLE) + if(AI_STATUS_OFF, AI_STATUS_IDLE) STOP_PROCESSING(SSai_behaviors, src) CancelActions() @@ -392,7 +387,7 @@ multiple modular subtrees with behaviors paused_until = world.time + time /datum/ai_controller/proc/modify_cooldown(datum/ai_behavior/behavior, new_cooldown) - behavior_cooldowns[behavior.type] = new_cooldown + behavior_cooldowns[behavior] = new_cooldown ///Call this to add a behavior to the stack. /datum/ai_controller/proc/queue_behavior(behavior_type, ...) @@ -422,13 +417,23 @@ multiple modular subtrees with behaviors var/list/stored_arguments = behavior_args[behavior.type] if(stored_arguments) arguments += stored_arguments - behavior.perform(arglist(arguments)) + + var/process_flags = behavior.perform(arglist(arguments)) + if(process_flags & AI_BEHAVIOR_DELAY) + behavior_cooldowns[behavior] = world.time + behavior.get_cooldown(src) + if(process_flags & AI_BEHAVIOR_FAILED) + arguments[1] = src + arguments[2] = FALSE + behavior.finish_action(arglist(arguments)) + else if (process_flags & AI_BEHAVIOR_SUCCEEDED) + arguments[1] = src + arguments[2] = TRUE + behavior.finish_action(arglist(arguments)) /datum/ai_controller/proc/CancelActions() if(!LAZYLEN(current_behaviors)) return - for(var/i in current_behaviors) - var/datum/ai_behavior/current_behavior = i + for(var/datum/ai_behavior/current_behavior as anything in current_behaviors) var/list/arguments = list(src, FALSE) var/list/stored_arguments = behavior_args[current_behavior.type] if(stored_arguments) diff --git a/code/datums/ai/_item_behaviors.dm b/code/datums/ai/_item_behaviors.dm index 6cfb539f7a0..c9f3441fdd6 100644 --- a/code/datums/ai/_item_behaviors.dm +++ b/code/datums/ai/_item_behaviors.dm @@ -2,14 +2,14 @@ /datum/ai_behavior/item_escape_grasp /datum/ai_behavior/item_escape_grasp/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/obj/item/item_pawn = controller.pawn var/mob/item_holder = item_pawn.loc if(!istype(item_holder)) - finish_action(controller, FALSE) //We're no longer being held. abort abort!! + //We're no longer being held. abort abort!! + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED item_pawn.visible_message(span_warning("[item_pawn] slips out of the hands of [item_holder]!")) item_holder.dropItemToGround(item_pawn, TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///This behavior is for obj/items, it is used to move closer to a target and throw themselves towards them. @@ -30,7 +30,6 @@ set_movement_target(controller, target) /datum/ai_behavior/item_move_close_and_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, throw_count_key) - . = ..() var/obj/item/item_pawn = controller.pawn var/atom/throw_target = controller.blackboard[target_key] @@ -39,7 +38,8 @@ playsound(item_pawn.loc, attack_sound, 100, TRUE) controller.add_blackboard_key(throw_count_key, 1) if(controller.blackboard[throw_count_key] >= max_attempts) - finish_action(controller, TRUE, target_key, throw_count_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/item_move_close_and_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, throw_count_key) . = ..() diff --git a/code/datums/ai/babies/babies_behaviors.dm b/code/datums/ai/babies/babies_behaviors.dm index 8cc03d72f6b..ad57d309a2c 100644 --- a/code/datums/ai/babies/babies_behaviors.dm +++ b/code/datums/ai/babies/babies_behaviors.dm @@ -8,7 +8,6 @@ var/max_children = 3 /datum/ai_behavior/find_partner/perform(seconds_per_tick, datum/ai_controller/controller, target_key, partner_types_key, child_types_key) - . = ..() max_children = controller.blackboard[BB_MAX_CHILDREN] || max_children var/mob/pawn_mob = controller.pawn var/list/partner_types = controller.blackboard[partner_types_key] @@ -18,12 +17,10 @@ var/children = 0 for(var/mob/living/other in oview(range, pawn_mob)) if(!pawn_mob.faction_check_atom(other)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(children >= max_children) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(other.stat != CONSCIOUS) //Check if it's conscious FIRST. continue @@ -40,10 +37,9 @@ if(other.gender != living_pawn.gender && !(other.flags_1 & HOLOGRAM_1)) //Better safe than sorry ;_; controller.set_blackboard_key(target_key, other) - finish_action(controller, TRUE) - - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /** * Reproduce. @@ -59,15 +55,13 @@ set_movement_target(controller, target) /datum/ai_behavior/make_babies/perform(seconds_per_tick, datum/ai_controller/controller, target_key, child_types_key) - . = ..() var/mob/target = controller.blackboard[target_key] if(QDELETED(target) || target.stat != CONSCIOUS) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/living_pawn = controller.pawn living_pawn.set_combat_mode(FALSE) living_pawn.melee_attack(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/make_babies/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 144de535d5a..883c157a96b 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -21,17 +21,15 @@ if (isliving(controller.pawn)) var/mob/living/pawn = controller.pawn if (world.time < pawn.next_move) - return + return AI_BEHAVIOR_INSTANT - . = ..() var/mob/living/basic/basic_mob = controller.pawn //targeting strategy will kill the action if not real anymore var/atom/target = controller.blackboard[target_key] var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if(!targeting_strategy.can_attack(basic_mob, target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! @@ -43,7 +41,8 @@ basic_mob.melee_attack(target) if(terminate_after_action) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() @@ -82,22 +81,21 @@ var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if(!targeting_strategy.can_attack(basic_mob, target, chase_range)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/atom/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! var/atom/final_target = hiding_target ? hiding_target : target if(!can_see(basic_mob, final_target, required_distance)) - return + return AI_BEHAVIOR_INSTANT if(avoid_friendly_fire && check_friendly_in_path(basic_mob, target, targeting_strategy)) adjust_position(basic_mob, target) - return ..() + return AI_BEHAVIOR_DELAY controller.set_blackboard_key(hiding_location_key, hiding_target) basic_mob.RangedAttack(final_target) - return ..() //only start the cooldown when the shot is shot + return AI_BEHAVIOR_DELAY //only start the cooldown when the shot is shot /datum/ai_behavior/basic_ranged_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm index e1fd8bed640..865b028e156 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/befriend_target.dm @@ -2,19 +2,17 @@ /datum/ai_behavior/befriend_target /datum/ai_behavior/befriend_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, befriend_message) - . = ..() var/mob/living/living_pawn = controller.pawn var/mob/living/living_target = controller.blackboard[target_key] if(QDELETED(living_target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.befriend(living_target) var/befriend_text = controller.blackboard[befriend_message] if(befriend_text) to_chat(living_target, span_nicegreen("[living_pawn] [befriend_text]")) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/befriend_target/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm index c8c18072a4a..5046baa7e0f 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/climb_tree.dm @@ -22,13 +22,12 @@ set_movement_target(controller, target) /datum/ai_behavior/climb_tree/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/structure/flora/target_tree = controller.blackboard[target_key] var/mob/living/basic/living_pawn = controller.pawn if(QDELETED(living_pawn)) // pawn can be null at this point return SEND_SIGNAL(living_pawn, COMSIG_LIVING_CLIMB_TREE, target_tree) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/climb_tree/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm index 9e4ccef4936..07b4845f027 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm @@ -3,16 +3,13 @@ var/look_range = 7 /datum/ai_behavior/find_mom/perform(seconds_per_tick, datum/ai_controller/controller, mom_key, ignore_mom_key, found_mom) - . = ..() - var/mob/living_pawn = controller.pawn var/list/mom_types = controller.blackboard[mom_key] var/list/all_moms = list() var/list/ignore_types = controller.blackboard[ignore_mom_key] if(!length(mom_types)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/mob/mother in oview(look_range, living_pawn)) if(!is_type_in_list(mother, mom_types)) @@ -23,6 +20,5 @@ if(length(all_moms)) controller.set_blackboard_key(found_mom, pick(all_moms)) - finish_action(controller, TRUE) - return - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm index e81c9f95751..1b65eaa507c 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm @@ -11,16 +11,13 @@ return isitem(target) && isturf(target.loc) && !target.anchored /datum/ai_behavior/pick_up_item/perform(seconds_per_tick, datum/ai_controller/controller, target_key, storage_key) - . = ..() var/obj/item/target = controller.blackboard[target_key] if(QDELETED(target) || !isturf(target.loc)) // Someone picked it up or it got deleted - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(!controller.pawn.Adjacent(target)) // It teleported - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED pickup_item(controller, target, storage_key) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/pick_up_item/finish_action(datum/ai_controller/controller, success, target_key, storage_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm index 9bfc3f85d24..900b122dcb3 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/pull_target.dm @@ -9,15 +9,12 @@ set_movement_target(controller, target) /datum/ai_behavior/pull_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/atom/movable/target = controller.blackboard[target_key] if(QDELETED(target) || target.anchored || target.pulledby) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/our_mob = controller.pawn our_mob.start_pulling(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/pull_target/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm index 172a31d4793..f23707e72b8 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm @@ -18,18 +18,16 @@ return ..() /datum/ai_behavior/run_away_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) - . = ..() if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) - return + return AI_BEHAVIOR_DELAY var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] if (QDELETED(target) || !can_see(controller.pawn, target, run_distance)) - finish_action(controller, succeeded = TRUE, target_key = target_key, hiding_location_key = hiding_location_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED if (get_dist(controller.pawn, controller.current_movement_target) > required_distance) - return // Still heading over + return AI_BEHAVIOR_DELAY // Still heading over if (plot_path_away_from(controller, target)) - return - finish_action(controller, succeeded = FALSE, target_key = target_key, hiding_location_key = hiding_location_key) + return AI_BEHAVIOR_DELAY + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/run_away_from_target/proc/plot_path_away_from(datum/ai_controller/controller, atom/target) var/turf/target_destination = get_turf(controller.pawn) @@ -71,7 +69,7 @@ /datum/ai_behavior/run_away_from_target/run_and_shoot/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, succeeded = FALSE, target_key = target_key, hiding_location_key = hiding_location_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn living_pawn.RangedAttack(target) return ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm index 207df442457..6bf6dbb7fdb 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/set_travel_destination.dm @@ -1,13 +1,10 @@ /datum/ai_behavior/set_travel_destination /datum/ai_behavior/set_travel_destination/perform(seconds_per_tick, datum/ai_controller/controller, target_key, location_key) - . = ..() var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(location_key, target) - - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm index f941b2eb95d..7cb3a7b9f14 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm @@ -47,8 +47,7 @@ // We actually only wanted the movement so if we've arrived we're done /datum/ai_behavior/step_towards_turf/perform(seconds_per_tick, datum/ai_controller/controller, area_key, turf_key) - . = ..() - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /** * # Step towards turf in area diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm index df066ac0418..4ce1f877b18 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm @@ -11,10 +11,9 @@ return cooldown_for.blackboard[BB_STATIONARY_COOLDOWN] /datum/ai_behavior/stop_and_stare/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/movable/target = controller.blackboard[target_key] if(!ismovable(target) || !isturf(target.loc)) // just to make sure that nothing funky happened between setup and perform - return + return AI_BEHAVIOR_DELAY var/mob/pawn_mob = controller.pawn var/turf/pawn_turf = get_turf(pawn_mob) @@ -25,3 +24,4 @@ if(controller.blackboard[BB_STATIONARY_MOVE_TO_TARGET]) addtimer(CALLBACK(src, PROC_REF(set_movement_target), controller, target, initial(controller.ai_movement)), (controller.blackboard[BB_STATIONARY_SECONDS] + 1 SECONDS)) + return AI_BEHAVIOR_DELAY diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm index ba167b34f29..2d2ad013aa2 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm @@ -8,12 +8,13 @@ var/datum/action/cooldown/ability = get_ability_to_use(controller, ability_key) var/mob/living/target = controller.blackboard[target_key] if(QDELETED(ability) || QDELETED(target)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/pawn = controller.pawn pawn.face_atom(target) var/result = ability.Trigger(target = target) - finish_action(controller, result, ability_key, target_key) + if(result) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED /datum/ai_behavior/targeted_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm index b54bfe82f90..f0ee4bb9bba 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm @@ -26,8 +26,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ var/atom/current_target = controller.blackboard[target_key] if (targeting_strategy.can_attack(living_mob, current_target, vision_range)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/aggro_range = controller.blackboard[aggro_range_key] || vision_range @@ -45,8 +44,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ if(!potential_targets.len) failed_to_find_anyone(controller, target_key, targeting_strategy_key, hiding_location_key) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/list/filtered_targets = list() @@ -57,8 +55,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ if(!filtered_targets.len) failed_to_find_anyone(controller, target_key, targeting_strategy_key, hiding_location_key) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/atom/target = pick_final_target(controller, filtered_targets) controller.set_blackboard_key(target_key, target) @@ -68,7 +65,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. controller.set_blackboard_key(hiding_location_key, potential_hiding_location) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_potential_targets/proc/failed_to_find_anyone(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/aggro_range = controller.blackboard[aggro_range_key] || vision_range @@ -149,7 +146,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ var/datum/proximity_monitor/field = controller.blackboard[BB_FIND_TARGETS_FIELD(type)] qdel(field) // autoclears so it's fine controller.CancelActions() // On retarget cancel any further queued actions so that they will setup again with new target - controller.modify_cooldown(controller, get_cooldown(controller)) + controller.modify_cooldown(src, get_cooldown(controller)) /// Returns the desired final target from the filtered list of targets /datum/ai_behavior/find_potential_targets/proc/pick_final_target(datum/ai_controller/controller, list/filtered_targets) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm index 643bb9ced5a..c734d961b5e 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm @@ -3,8 +3,6 @@ /datum/ai_behavior/tipped_reaction /datum/ai_behavior/tipped_reaction/perform(seconds_per_tick, datum/ai_controller/controller, tipper_key, reacting_key) - . = ..() - var/mob/living/carbon/tipper = controller.blackboard[tipper_key] // visible part of the visible message @@ -28,7 +26,7 @@ seen_message = "[controller.pawn] seems resigned to its fate." self_message = "You resign yourself to your fate." controller.pawn.visible_message(span_notice("[seen_message]"), span_notice("[self_message]")) - finish_action(controller, TRUE, tipper_key, reacting_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/tipped_reaction/finish_action(datum/ai_controller/controller, succeeded, tipper_key, reacting_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm index 6eb7c36dadd..808fe6b8873 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm @@ -19,8 +19,7 @@ set_movement_target(controller, target, new_movement_type) /datum/ai_behavior/travel_towards/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/travel_towards/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -48,5 +47,4 @@ set_movement_target(controller, target_atom) /datum/ai_behavior/travel_towards_atom/perform(seconds_per_tick, datum/ai_controller/controller, atom/target_atom) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm index 655b335d3b6..34e651f8e52 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/unbuckle_mob.dm @@ -1,14 +1,11 @@ /datum/ai_behavior/unbuckle_mob /datum/ai_behavior/unbuckle_mob/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - var/mob/living/living_pawn = controller.pawn var/atom/movable/buckled_to = living_pawn.buckled if(isnull(buckled_to)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED buckled_to.unbuckle_mob(living_pawn) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm index 889b474ad03..aca89d83281 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm @@ -17,26 +17,23 @@ return istype(target) && isliving(controller.pawn) // only mobs can vent crawl in the current framework /datum/ai_behavior/crawl_through_vents/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent = controller.blackboard[target_key] || controller.blackboard[BB_ENTRY_VENT_TARGET] var/mob/living/cached_pawn = controller.pawn if(HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING) || !controller.blackboard[BB_CURRENTLY_TARGETING_VENT] || !is_vent_valid(entry_vent)) - return + return AI_BEHAVIOR_DELAY if(!cached_pawn.can_enter_vent(entry_vent, provide_feedback = FALSE)) // we're an AI we scoff at feedback - finish_action(controller, FALSE, target_key) // "never enter a hole you can't get out of" - return + // "never enter a hole you can't get out of" + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/vent_we_exit_out_of = calculate_exit_vent(controller, target_key) if(isnull(vent_we_exit_out_of)) // don't get into the vents if we can't get out of them, that's SILLY. - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_CURRENTLY_TARGETING_VENT, FALSE) // must be done here because we have a do_after sleep in handle_ventcrawl unfortunately and double dipping could lead to erroneous suicide pill calls. cached_pawn.handle_ventcrawl(entry_vent) if(!HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING)) //something failed and we ARE NOT IN THE VENT even though the earlier check said we were good to go! odd. - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_EXIT_VENT_TARGET, vent_we_exit_out_of) @@ -50,7 +47,8 @@ var/upper_vent_time_limit = controller.blackboard[BB_UPPER_VENT_TIME_LIMIT] // the most amount of time we spend in the vents addtimer(CALLBACK(src, PROC_REF(exit_the_vents), controller), rand(lower_vent_time_limit, upper_vent_time_limit)) - controller.set_blackboard_key(BB_GIVE_UP_ON_VENT_PATHING_TIMER_ID, addtimer(CALLBACK(src, PROC_REF(suicide_pill), controller), controller.blackboard[BB_TIME_TO_GIVE_UP_ON_VENT_PATHING], TIMER_STOPPABLE)) + controller.set_blackboard_key(BB_GIVE_UP_ON_VENT_PATHING_TIMER_ID, addtimer(CALLBACK(src, PROC_REF(delayed_suicide_pill), controller, target_key), controller.blackboard[BB_TIME_TO_GIVE_UP_ON_VENT_PATHING], TIMER_STOPPABLE)) + return AI_BEHAVIOR_DELAY /// Figure out an exit vent that we should head towards. If we don't have one, default to the entry vent. If they're all kaput, we die. /datum/ai_behavior/crawl_through_vents/proc/calculate_exit_vent(datum/ai_controller/controller, target_key) @@ -83,8 +81,8 @@ var/mob/living/living_pawn = controller.pawn if(!HAS_TRAIT(living_pawn, TRAIT_MOVE_VENTCRAWLING) && isturf(get_turf(living_pawn))) // we're out of the vents, so no need to do an exit - finish_action(controller, TRUE, target_key) // assume that we got yeeted out somehow and call this so we can halt the suicide pill timer. - return + // assume that we got yeeted out somehow and return this so we can halt the suicide pill timer. + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED living_pawn.forceMove(exit_vent) if(!living_pawn.can_enter_vent(exit_vent, provide_feedback = FALSE)) @@ -92,8 +90,7 @@ emergency_vent = calculate_exit_vent(controller) if(isnull(emergency_vent)) // it's joever. we cooked too hard. - suicide_pill(controller, target_key) - return + return suicide_pill(controller) | AI_BEHAVIOR_DELAY controller.set_blackboard_key(BB_EXIT_VENT_TARGET, emergency_vent) // assign and go again addtimer(CALLBACK(src, PROC_REF(exit_the_vents), controller), (rand(controller.blackboard[BB_LOWER_VENT_TIME_LIMIT], controller.blackboard[BB_UPPER_VENT_TIME_LIMIT]) / 2)) // we're in danger mode, so scurry out at half the time it would normally take. @@ -102,32 +99,34 @@ living_pawn.handle_ventcrawl(exit_vent) if(HAS_TRAIT(living_pawn, TRAIT_MOVE_VENTCRAWLING)) // how'd we fail? what the fuck stack_trace("We failed to exit the vents, even though we should have been fine? This is very weird.") - suicide_pill() // all of the prior checks say we should have definitely made it through, but we didn't. dammit. - return + return suicide_pill(controller) | AI_BEHAVIOR_DELAY // all of the prior checks say we should have definitely made it through, but we didn't. dammit. - finish_action(controller, TRUE, target_key) // we did it! we went into the vents and out of the vents. poggers. + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED // we did it! we went into the vents and out of the vents. poggers. /// Incredibly stripped down version of the overarching `can_enter_vent` proc on `/mob, just meant for rapid rechecking of a vent. Will be TRUE if not blocked, FALSE otherwise. /datum/ai_behavior/crawl_through_vents/proc/is_vent_valid(obj/machinery/atmospherics/components/unary/vent_pump/checkable) return !QDELETED(checkable) && !checkable.welded +/// Wraps a delayed defeat, so we gotta handle the return value properly ya feel? +/datum/ai_behavior/crawl_through_vents/proc/delayed_suicide_pill(datum/ai_controller/controller, target_key) + if(suicide_pill(controller) & AI_BEHAVIOR_FAILED) + finish_action(controller, FALSE, target_key) + /// Aw fuck, we may have been bested somehow. Regardless of what we do, we can't exit through a vent! Let's end our misery and prevent useless endless calculations. -/datum/ai_behavior/crawl_through_vents/proc/suicide_pill(datum/ai_controller/controller, target_key) +/datum/ai_behavior/crawl_through_vents/proc/suicide_pill(datum/ai_controller/controller) var/mob/living/living_pawn = controller.pawn if(istype(living_pawn)) - finish_action(controller, FALSE, target_key) - if(isnull(living_pawn.client)) // only call death if we don't have a client because maybe their natural intelligence can pick up where our AI calculations have failed living_pawn.death(TRUE) // call gibbed as true because we are never coming back it is so fucking joever - return + return AI_BEHAVIOR_FAILED if(QDELETED(living_pawn)) // we got deleted by some other means, just presume the action is a wash and get outta here - return + return NONE qdel(living_pawn) // failover, we really should've been caught in the istype() but lets just bow out of existing at this point - + return NONE /datum/ai_behavior/crawl_through_vents/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm index f5dba58416d..51826676e9e 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm @@ -1,7 +1,6 @@ /datum/ai_behavior/write_on_paper /datum/ai_behavior/write_on_paper/perform(seconds_per_tick, datum/ai_controller/controller, found_paper, list_of_writings) - . = ..() var/mob/living/wizard = controller.pawn var/list/writing_list = controller.blackboard[list_of_writings] var/obj/item/paper/target = controller.blackboard[found_paper] @@ -9,7 +8,7 @@ target.add_raw_text(pick(writing_list)) target.update_appearance() wizard.dropItemToGround(target) - finish_action(controller, TRUE, found_paper) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/write_on_paper/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm index 41169004354..8effc7a0fa7 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm @@ -27,7 +27,6 @@ /datum/ai_behavior/basic_melee_attack/opportunistic/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/atom/movable/atom_pawn = controller.pawn if(!atom_pawn.CanReach(controller.blackboard[target_key])) - finish_action(controller, TRUE, target_key) // Don't clear target - return FALSE + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED . = ..() - finish_action(controller, TRUE, target_key) // Try doing something else + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm index 7059bec93fe..bc8efdeb4ff 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm @@ -27,13 +27,11 @@ var/can_attack_dense_objects = FALSE /datum/ai_behavior/attack_obstructions/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/basic_mob = controller.pawn var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/turf/next_step = get_step_towards(basic_mob, target) var/dir_to_next_step = get_dir(basic_mob, next_step) @@ -48,8 +46,8 @@ for (var/direction in dirs_to_move) if (attack_in_direction(controller, basic_mob, direction)) - return - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/attack_obstructions/proc/attack_in_direction(datum/ai_controller/controller, mob/living/basic/basic_mob, direction) var/turf/next_step = get_step(basic_mob, direction) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm b/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm index 59ff88b4879..44d7cb4fe48 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/call_reinforcements.dm @@ -36,8 +36,6 @@ var/reinforcements_range = 15 /datum/ai_behavior/call_reinforcements/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - var/mob/pawn_mob = controller.pawn for(var/mob/other_mob in oview(reinforcements_range, pawn_mob)) if(pawn_mob.faction_check_atom(other_mob) && !isnull(other_mob.ai_controller)) @@ -46,5 +44,6 @@ other_mob.ai_controller.set_blackboard_key(BB_BASIC_MOB_REINFORCEMENT_TARGET, pawn_mob) controller.set_blackboard_key(BB_BASIC_MOB_REINFORCEMENTS_COOLDOWN, world.time + REINFORCEMENTS_COOLDOWN) + return AI_BEHAVIOR_DELAY #undef REINFORCEMENTS_COOLDOWN diff --git a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm index 4d5319bca86..a4fc49facc0 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm @@ -14,29 +14,25 @@ action_cooldown = 1 SECONDS /datum/ai_behavior/capricious_retaliate/perform(seconds_per_tick, datum/ai_controller/controller, targeting_strategy_key, ignore_faction) - . = ..() var/atom/pawn = controller.pawn if (controller.blackboard_key_exists(BB_BASIC_MOB_RETALIATE_LIST)) var/deaggro_chance = controller.blackboard[BB_RANDOM_DEAGGRO_CHANCE] || 10 if (!SPT_PROB(deaggro_chance, seconds_per_tick)) - finish_action(controller, TRUE, ignore_faction) // "true" here means "don't clear our ignoring factions status" - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED pawn.visible_message(span_notice("[pawn] calms down.")) // We can blackboard key this if anyone else actually wants to customise it controller.clear_blackboard_key(BB_BASIC_MOB_RETALIATE_LIST) - finish_action(controller, FALSE, ignore_faction) controller.CancelActions() // Otherwise they will try and get one last kick in - return + return AI_BEHAVIOR_DELAY var/aggro_chance = controller.blackboard[BB_RANDOM_AGGRO_CHANCE] || 0.5 if (!SPT_PROB(aggro_chance, seconds_per_tick)) - finish_action(controller, FALSE, ignore_faction) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/aggro_range = controller.blackboard[BB_AGGRO_RANGE] || 9 var/list/potential_targets = hearers(aggro_range, get_turf(pawn)) - pawn if (!length(potential_targets)) - failed_targeting(controller, pawn, ignore_faction) - return + failed_targeting(pawn) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/targeting_strategy/target_helper = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) @@ -49,16 +45,15 @@ final_target = test_target if (isnull(final_target)) - failed_targeting(controller, pawn, ignore_faction) - return + failed_targeting(pawn) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, final_target) pawn.visible_message(span_warning("[pawn] glares grumpily at [final_target]!")) - finish_action(controller, TRUE, ignore_faction) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// Called if we try but fail to target something -/datum/ai_behavior/capricious_retaliate/proc/failed_targeting(datum/ai_controller/controller, atom/pawn, ignore_faction) - finish_action(controller, FALSE, ignore_faction) +/datum/ai_behavior/capricious_retaliate/proc/failed_targeting(atom/pawn) pawn.visible_message(span_notice("[pawn] grumbles.")) // We're pissed off but with no outlet to vent our frustration upon /datum/ai_behavior/capricious_retaliate/finish_action(datum/ai_controller/controller, succeeded, ignore_faction) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm index 2a85e9e902b..549abbc75ec 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm @@ -60,8 +60,7 @@ return FALSE /datum/ai_behavior/step_away/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/step_away/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -83,8 +82,8 @@ /datum/ai_behavior/pursue_to_range/perform(seconds_per_tick, datum/ai_controller/controller, target_key, range) var/atom/current_target = controller.blackboard[target_key] if (!QDELETED(current_target) && get_dist(controller.pawn, current_target) > range) - return - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_INSTANT + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED ///instead of taking a single step, we cover the entire distance /datum/ai_behavior/cover_minimum_distance @@ -112,5 +111,4 @@ set_movement_target(controller, target = chosen_turf) /datum/ai_behavior/cover_minimum_distance/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm b/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm index 3c03702b699..dc3f6ddcf90 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/mine_walls.dm @@ -21,19 +21,16 @@ set_movement_target(controller, target) /datum/ai_behavior/mine_wall/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/turf/closed/mineral/target = controller.blackboard[target_key] var/is_gibtonite_turf = istype(target, /turf/closed/mineral/gibtonite) if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.melee_attack(target) if(is_gibtonite_turf) living_pawn.manual_emote("sighs...") //accept whats about to happen to us - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/mine_wall/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -42,17 +39,15 @@ /datum/ai_behavior/find_mineral_wall /datum/ai_behavior/find_mineral_wall/perform(seconds_per_tick, datum/ai_controller/controller, found_wall_key) - . = ..() var/mob/living_pawn = controller.pawn for(var/turf/closed/mineral/potential_wall in oview(9, living_pawn)) if(!check_if_mineable(controller, potential_wall)) //check if its surrounded by walls continue controller.set_blackboard_key(found_wall_key, potential_wall) //closest wall first! - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/find_mineral_wall/proc/check_if_mineable(datum/ai_controller/controller, turf/target_wall) var/mob/living/source = controller.pawn diff --git a/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm b/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm index c98878e0fd7..bcf5c829025 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/move_to_cardinal.dm @@ -51,19 +51,17 @@ /datum/ai_behavior/move_to_cardinal/perform(seconds_per_tick, datum/ai_controller/controller, target_key) var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) - finish_action(controller = controller, succeeded = FALSE, target_key = target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED if (!(get_dir(controller.pawn, target) in GLOB.cardinals)) target_nearest_cardinal(controller, target) - return + return AI_BEHAVIOR_INSTANT var/distance_to_target = get_dist(controller.pawn, target) if (distance_to_target < minimum_distance) target_nearest_cardinal(controller, target) - return + return AI_BEHAVIOR_INSTANT if (distance_to_target > maximum_distance) - return - finish_action(controller = controller, succeeded = TRUE, target_key = target_key) - return + return AI_BEHAVIOR_INSTANT + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/move_to_cardinal/finish_action(datum/ai_controller/controller, succeeded, target_key) if (!succeeded) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm index 95a125eea5c..3640a2052b5 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm @@ -26,16 +26,13 @@ return !QDELETED(target) /datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range) - . = ..() var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if(!targeting_strategy.can_attack(controller.pawn, target)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/hiding_target = targeting_strategy.find_hidden_mobs(controller.pawn, target) controller.set_blackboard_key(hiding_location_key, hiding_target) @@ -44,9 +41,8 @@ var/distance = get_dist(controller.pawn, target) if (distance > max_range || distance < min_range) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/gunman = controller.pawn gunman.RangedAttack(target) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm b/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm index 6f2f5cdc203..c0c0da96584 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/run_emote.dm @@ -15,8 +15,7 @@ /datum/ai_behavior/run_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote_key) var/mob/living/living_pawn = controller.pawn if (!isliving(living_pawn)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/list/emote_list = controller.blackboard[emote_key] var/emote @@ -26,8 +25,7 @@ emote = emote_list if(isnull(emote)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED living_pawn.emote(emote) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED 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 93499cf673c..5d9841a5247 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 @@ -16,7 +16,9 @@ /datum/ai_behavior/sleep_after_targetless_time/perform(seconds_per_tick, datum/ai_controller/controller, target_key) var/atom/target = controller.blackboard[target_key] - finish_action(controller, succeeded = QDELETED(target), seconds_per_tick = seconds_per_tick) + if(QDELETED(target)) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED /datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, seconds_per_tick) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm index 55ec7387613..d327b1047cf 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -39,6 +39,7 @@ var/mob/living/living_mob = controller.pawn var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if(!targeting_strategy) + . = AI_BEHAVIOR_DELAY CRASH("No target datum was supplied in the blackboard for [controller.pawn]") var/list/shitlist = controller.blackboard[shitlist_key] @@ -48,8 +49,7 @@ controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, TRUE) if (!QDELETED(existing_target) && (locate(existing_target) in shitlist) && targeting_strategy.can_attack(living_mob, existing_target, vision_range)) - finish_action(controller, succeeded = TRUE, check_faction = check_faction) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/list/enemies_list = list() for(var/mob/living/potential_target as anything in shitlist) @@ -59,8 +59,7 @@ if(!length(enemies_list)) controller.clear_blackboard_key(target_key) - finish_action(controller, succeeded = FALSE, check_faction = check_faction) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/atom/new_target = pick_final_target(controller, enemies_list) controller.set_blackboard_key(target_key, new_target) @@ -70,7 +69,7 @@ if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. controller.set_blackboard_key(hiding_location_key, potential_hiding_location) - finish_action(controller, succeeded = TRUE, check_faction = check_faction) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// Returns the desired final target from the filtered list of enemies /datum/ai_behavior/target_from_retaliate_list/proc/pick_final_target(datum/ai_controller/controller, list/enemies_list) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm index dadba992e9f..25f0e4a4249 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm @@ -34,7 +34,7 @@ /datum/ai_behavior/find_furthest_turf_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, set_key, range) var/mob/living/living_target = controller.blackboard[target_key] if(QDELETED(living_target)) - return + return AI_BEHAVIOR_INSTANT var/distance = 0 var/turf/chosen_turf @@ -49,8 +49,7 @@ break //we have already found the max distance if(isnull(chosen_turf)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED controller.set_blackboard_key(set_key, chosen_turf) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm index a59a901d57d..4c794a73d8a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm @@ -27,7 +27,7 @@ /datum/ai_behavior/use_mob_ability/perform(seconds_per_tick, datum/ai_controller/controller, ability_key) var/datum/action/using_action = controller.blackboard[ability_key] if (QDELETED(using_action)) - finish_action(controller, FALSE, ability_key) - return - var/result = using_action.Trigger() - finish_action(controller, result, ability_key) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED + if(using_action.Trigger()) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED diff --git a/code/datums/ai/basic_mobs/pet_commands/fetch.dm b/code/datums/ai/basic_mobs/pet_commands/fetch.dm index a9147eaf681..87606fa0c65 100644 --- a/code/datums/ai/basic_mobs/pet_commands/fetch.dm +++ b/code/datums/ai/basic_mobs/pet_commands/fetch.dm @@ -14,19 +14,15 @@ set_movement_target(controller, fetch_thing) /datum/ai_behavior/fetch_seek/perform(seconds_per_tick, datum/ai_controller/controller, target_key, delivery_key) - . = ..() var/obj/item/fetch_thing = controller.blackboard[target_key] // It stopped existing if (QDELETED(fetch_thing)) - finish_action(controller, FALSE, target_key, delivery_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED // We can't pick this up if (fetch_thing.anchored) - finish_action(controller, FALSE, target_key, delivery_key) - return - - finish_action(controller, TRUE, target_key, delivery_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/fetch_seek/finish_action(datum/ai_controller/controller, success, target_key, delivery_key) . = ..() @@ -53,14 +49,13 @@ set_movement_target(controller, return_target) /datum/ai_behavior/deliver_fetched_item/perform(seconds_per_tick, datum/ai_controller/controller, delivery_key, storage_key) - . = ..() var/mob/living/return_target = controller.blackboard[delivery_key] if(QDELETED(return_target)) - finish_action(controller, FALSE, delivery_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED - deliver_item(controller, return_target, storage_key) - finish_action(controller, TRUE, delivery_key) + if(!deliver_item(controller, return_target, storage_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/deliver_fetched_item/finish_action(datum/ai_controller/controller, success, delivery_key) . = ..() @@ -68,13 +63,13 @@ controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) /// Actually deliver the fetched item to the target, if we still have it +/// Returns TRUE if we succeeded, FALSE if we failed /datum/ai_behavior/deliver_fetched_item/proc/deliver_item(datum/ai_controller/controller, return_target, storage_key) var/mob/pawn = controller.pawn var/obj/item/carried_item = controller.blackboard[storage_key] if(QDELETED(carried_item) || carried_item.loc != pawn) pawn.visible_message(span_notice("[pawn] looks around as if [pawn.p_they()] [pawn.p_have()] lost something.")) - finish_action(controller, FALSE) - return + return FALSE pawn.visible_message(span_notice("[pawn] delivers [carried_item] to [return_target].")) carried_item.forceMove(get_turf(return_target)) @@ -99,26 +94,26 @@ set_movement_target(controller, snack) /datum/ai_behavior/eat_fetched_snack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, delivery_key) - . = ..() var/obj/item/snack = controller.blackboard[target_key] var/is_living_loc = isliving(snack.loc) if(QDELETED(snack) || (!isturf(snack.loc) && !is_living_loc)) - finish_action(controller, FALSE) // Where did it go? - return + // Where did it go? + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/basic_pawn = controller.pawn if(is_living_loc) if(SPT_PROB(10, seconds_per_tick)) basic_pawn.manual_emote("Stares at [snack.loc]'s [snack.name] intently.") - return + return AI_BEHAVIOR_DELAY if(!basic_pawn.Adjacent(snack)) - return + return AI_BEHAVIOR_DELAY basic_pawn.melee_attack(snack) // snack attack! if(QDELETED(snack)) // we ate it! - finish_action(controller, TRUE, target_key, delivery_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/eat_fetched_snack/finish_action(datum/ai_controller/controller, succeeded, target_key, delivery_key) . = ..() @@ -143,7 +138,6 @@ return /datum/ai_behavior/forget_failed_fetches/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() COOLDOWN_START(src, reset_ignore_cooldown, cooldown_duration) controller.clear_blackboard_key(BB_FETCH_IGNORE_LIST) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm b/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm index 397021818aa..38a6939c901 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm @@ -10,8 +10,7 @@ set_movement_target(controller, target) /datum/ai_behavior/pet_follow_friend/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + return AI_BEHAVIOR_DELAY diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm b/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm index c7153b0c12f..3c8c06b0099 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm @@ -13,11 +13,11 @@ var/datum/action/cooldown/mob_cooldown/ability = controller.blackboard[ability_key] var/mob/living/target = controller.blackboard[target_key] if (QDELETED(ability) || QDELETED(target)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/pawn = controller.pawn if(QDELETED(pawn) || ability.InterceptClickOn(pawn, null, target)) - finish_action(controller, TRUE, ability_key, target_key) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT /datum/ai_behavior/pet_use_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() diff --git a/code/datums/ai/basic_mobs/pet_commands/play_dead.dm b/code/datums/ai/basic_mobs/pet_commands/play_dead.dm index c4b99cf6f42..5a7a0943026 100644 --- a/code/datums/ai/basic_mobs/pet_commands/play_dead.dm +++ b/code/datums/ai/basic_mobs/pet_commands/play_dead.dm @@ -11,9 +11,9 @@ basic_pawn.look_dead() /datum/ai_behavior/play_dead/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() if(SPT_PROB(10, seconds_per_tick)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/play_dead/finish_action(datum/ai_controller/controller, succeeded) . = ..() diff --git a/code/datums/ai/dog/dog_behaviors.dm b/code/datums/ai/dog/dog_behaviors.dm index eed116330fb..00a2f789e12 100644 --- a/code/datums/ai/dog/dog_behaviors.dm +++ b/code/datums/ai/dog/dog_behaviors.dm @@ -11,23 +11,21 @@ controller.behavior_cooldowns[src] = world.time + get_cooldown(controller) var/mob/living/living_pawn = controller.pawn if(!(isturf(living_pawn.loc) || HAS_TRAIT(living_pawn, TRAIT_AI_BAGATTACK))) // Void puppies can attack from inside bags - finish_action(controller, FALSE, target_key, targeting_strategy_key, hiding_location_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED // Unfortunately going to repeat this check in parent call but what can you do var/atom/target = controller.blackboard[target_key] var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) if (!targeting_strategy.can_attack(living_pawn, target)) - finish_action(controller, FALSE, target_key, targeting_strategy_key, hiding_location_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED if (!living_pawn.Adjacent(target)) growl_at(living_pawn, target, seconds_per_tick) - return + return AI_BEHAVIOR_INSTANT if(!controller.blackboard[BB_DOG_HARASS_HARM]) paw_harmlessly(living_pawn, target, seconds_per_tick) - return + return AI_BEHAVIOR_INSTANT // Give Ian some teeth var/old_melee_lower = living_pawn.melee_damage_lower @@ -39,6 +37,7 @@ living_pawn.melee_damage_lower = old_melee_lower living_pawn.melee_damage_upper = old_melee_upper + return AI_BEHAVIOR_DELAY /// Swat at someone we don't like but won't hurt /datum/ai_behavior/basic_melee_attack/dog/proc/paw_harmlessly(mob/living/living_pawn, atom/target, seconds_per_tick) diff --git a/code/datums/ai/dog/dog_subtrees.dm b/code/datums/ai/dog/dog_subtrees.dm index 62f63da54bd..74c075adad3 100644 --- a/code/datums/ai/dog/dog_subtrees.dm +++ b/code/datums/ai/dog/dog_subtrees.dm @@ -35,5 +35,4 @@ controller.clear_blackboard_key(target_key) /datum/ai_behavior/find_hated_dog_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index fbddc33075c..41f256c9ba7 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -7,19 +7,15 @@ action_cooldown = 2 SECONDS /datum/ai_behavior/find_and_set/perform(seconds_per_tick, datum/ai_controller/controller, set_key, locate_path, search_range) - . = ..() if (controller.blackboard_key_exists(set_key)) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED if(QDELETED(controller.pawn)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/find_this_thing = search_tactic(controller, locate_path, search_range) if(isnull(find_this_thing)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(set_key, find_this_thing) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_and_set/proc/search_tactic(datum/ai_controller/controller, locate_path, search_range) return locate(locate_path) in oview(search_range, controller.pawn) diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index b70375ef393..1c0e1f65adf 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -1,28 +1,25 @@ /datum/ai_behavior/resist/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn living_pawn.ai_controller.set_blackboard_key(BB_RESISTING, TRUE) living_pawn.execute_resist() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/battle_screech ///List of possible screeches the behavior has var/list/screeches /datum/ai_behavior/battle_screech/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn INVOKE_ASYNC(living_pawn, TYPE_PROC_REF(/mob, emote), pick(screeches)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///Moves to target then finishes /datum/ai_behavior/move_to_target behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT /datum/ai_behavior/move_to_target/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/break_spine @@ -42,12 +39,10 @@ var/mob/living/big_guy = controller.pawn //he was molded by the darkness if(QDELETED(batman) || get_dist(batman, big_guy) >= give_up_distance) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED if(batman.stat != CONSCIOUS) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED big_guy.start_pulling(batman) big_guy.face_atom(batman) @@ -63,7 +58,7 @@ else batman.adjustBruteLoss(150) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/break_spine/finish_action(datum/ai_controller/controller, succeeded, target_key) if(succeeded) @@ -80,14 +75,12 @@ /datum/ai_behavior/use_in_hand/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held = pawn.get_active_held_item() if(!held) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED pawn.activate_hand() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// Use the currently held item, or unarmed, on a weakref to an object in the world /datum/ai_behavior/use_on_object @@ -102,13 +95,11 @@ set_movement_target(controller, target) /datum/ai_behavior/use_on_object/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand()) var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED pawn.set_combat_mode(FALSE) if(held_item) @@ -116,7 +107,7 @@ else pawn.UnarmedAttack(target, TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/give behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH @@ -127,37 +118,34 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/give/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_active_held_item() var/atom/target = controller.blackboard[target_key] if(!held_item) //if held_item is null, we pretend that action was succesful - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED if(!target || !isliving(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_target = target - - if(!try_to_give_item(controller, living_target, held_item)) - return + var/perform_flags = try_to_give_item(controller, living_target, held_item) + if(perform_flags & AI_BEHAVIOR_FAILED) + return perform_flags controller.PauseAi(1.5 SECONDS) living_target.visible_message( span_info("[pawn] starts trying to give [held_item] to [living_target]!"), span_warning("[pawn] tries to give you [held_item]!") ) if(!do_after(pawn, 1 SECONDS, living_target)) - return + return AI_BEHAVIOR_DELAY | perform_flags - try_to_give_item(controller, living_target, held_item, actually_give = TRUE) + perform_flags |= try_to_give_item(controller, living_target, held_item, actually_give = TRUE) + return AI_BEHAVIOR_DELAY | perform_flags /datum/ai_behavior/give/proc/try_to_give_item(datum/ai_controller/controller, mob/living/target, obj/item/held_item, actually_give) if(QDELETED(held_item) || QDELETED(target)) - finish_action(controller, FALSE) - return FALSE + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/has_left_pocket = target.can_equip(held_item, ITEM_SLOT_LPOCKET) var/has_right_pocket = target.can_equip(held_item, ITEM_SLOT_RPOCKET) @@ -169,17 +157,16 @@ break if(!has_left_pocket && !has_right_pocket && !has_valid_hand) - finish_action(controller, FALSE) - return FALSE + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(!actually_give) - return TRUE + return AI_BEHAVIOR_DELAY if(!has_valid_hand || prob(50)) target.equip_to_slot_if_possible(held_item, (!has_left_pocket ? ITEM_SLOT_RPOCKET : (prob(50) ? ITEM_SLOT_LPOCKET : ITEM_SLOT_RPOCKET))) else target.put_in_hands(held_item) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/consume @@ -191,21 +178,20 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/consume/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hunger_timer_key) - . = ..() var/mob/living/living_pawn = controller.pawn var/obj/item/target = controller.blackboard[target_key] if(QDELETED(target)) - return + return AI_BEHAVIOR_DELAY if(!(target in living_pawn.held_items)) if(!living_pawn.get_empty_held_indexes() || !living_pawn.put_in_hands(target)) - finish_action(controller, FALSE, target, hunger_timer_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED target.melee_attack_chain(living_pawn, living_pawn) if(QDELETED(target) || prob(10)) // Even if we don't finish it all we can randomly decide to be done - finish_action(controller, TRUE, null, hunger_timer_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY /datum/ai_behavior/consume/finish_action(datum/ai_controller/controller, succeeded, target_key, hunger_timer_key) . = ..() @@ -218,36 +204,34 @@ /datum/ai_behavior/drop_item /datum/ai_behavior/drop_item/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn var/obj/item/best_held = GetBestWeapon(controller, null, living_pawn.held_items) for(var/obj/item/held as anything in living_pawn.held_items) if(!held || held == best_held) continue living_pawn.dropItemToGround(held) + return AI_BEHAVIOR_DELAY /// This behavior involves attacking a target. /datum/ai_behavior/attack behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM | AI_BEHAVIOR_REQUIRE_REACH /datum/ai_behavior/attack/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !isturf(living_pawn.loc)) - return + return AI_BEHAVIOR_DELAY var/atom/movable/attack_target = controller.blackboard[BB_ATTACK_TARGET] if(!attack_target || !can_see(living_pawn, attack_target, length = controller.blackboard[BB_VISION_RANGE])) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_target = attack_target if(istype(living_target) && (living_target.stat == DEAD)) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED set_movement_target(controller, living_target) attack(controller, living_target) + return AI_BEHAVIOR_DELAY /datum/ai_behavior/attack/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -265,22 +249,20 @@ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM /datum/ai_behavior/follow/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !isturf(living_pawn.loc)) - return + return AI_BEHAVIOR_DELAY var/atom/movable/follow_target = controller.blackboard[BB_FOLLOW_TARGET] if(!follow_target || get_dist(living_pawn, follow_target) > controller.blackboard[BB_VISION_RANGE]) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_target = follow_target if(istype(living_target) && (living_target.stat == DEAD)) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED set_movement_target(controller, living_target) + return AI_BEHAVIOR_DELAY /datum/ai_behavior/follow/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -291,11 +273,11 @@ /datum/ai_behavior/perform_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote, speech_sound) var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn)) - return + return AI_BEHAVIOR_INSTANT living_pawn.manual_emote(emote) if(speech_sound) // Only audible emotes will pass in a sound playsound(living_pawn, speech_sound, 80, vary = TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/perform_speech @@ -304,29 +286,26 @@ var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn)) - return + return AI_BEHAVIOR_INSTANT living_pawn.say(speech, forced = "AI Controller") if(speech_sound) playsound(living_pawn, speech_sound, 80, vary = TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/perform_speech_radio /datum/ai_behavior/perform_speech_radio/perform(seconds_per_tick, datum/ai_controller/controller, speech, obj/item/radio/speech_radio, list/try_channels = list(RADIO_CHANNEL_COMMON)) var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn) || !istype(speech_radio) || QDELETED(speech_radio) || !length(try_channels)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED speech_radio.talk_into(living_pawn, speech, pick(try_channels)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED //song behaviors /datum/ai_behavior/setup_instrument /datum/ai_behavior/setup_instrument/perform(seconds_per_tick, datum/ai_controller/controller, song_instrument_key, song_lines_key) - . = ..() - var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key] var/datum/song/song = song_instrument.song var/song_lines = controller.blackboard[song_lines_key] @@ -336,24 +315,20 @@ song.ParseSong(new_song = song_lines) song.repeat = 10 song.volume = song.max_volume - 10 - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/play_instrument /datum/ai_behavior/play_instrument/perform(seconds_per_tick, datum/ai_controller/controller, song_instrument_key) - . = ..() - var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key] var/datum/song/song = song_instrument.song song.start_playing(controller.pawn) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_nearby /datum/ai_behavior/find_nearby/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/list/possible_targets = list() for(var/atom/thing in view(2, controller.pawn)) if(!thing.mouse_opacity) @@ -366,6 +341,6 @@ continue possible_targets += thing if(!possible_targets.len) - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, pick(possible_targets)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index 07fc84997a6..609138c1132 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -52,18 +52,14 @@ /datum/ai_behavior/find_hunt_target /datum/ai_behavior/find_hunt_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range) - . = ..() - var/mob/living/living_mob = controller.pawn for(var/atom/possible_dinner as anything in typecache_filter_list(range(hunt_range, living_mob), types_to_hunt)) if(!valid_dinner(living_mob, possible_dinner, hunt_range, controller, seconds_per_tick)) continue controller.set_blackboard_key(hunting_target_key, possible_dinner) - finish_action(controller, TRUE, hunting_target_key) - return - - finish_action(controller, FALSE, hunting_target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/find_hunt_target/proc/valid_dinner(mob/living/source, atom/dinner, radius, datum/ai_controller/controller, seconds_per_tick) if(isliving(dinner)) @@ -90,15 +86,13 @@ set_movement_target(controller, hunt_target) /datum/ai_behavior/hunt_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) - . = ..() var/mob/living/hunter = controller.pawn var/atom/hunted = controller.blackboard[hunting_target_key] if(QDELETED(hunted)) - finish_action(controller, FALSE, hunting_target_key) - else - target_caught(hunter, hunted) - finish_action(controller, TRUE, hunting_target_key, hunting_cooldown_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + target_caught(hunter, hunted) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/hunt_target/proc/target_caught(mob/living/hunter, atom/hunted) if(isliving(hunted)) // Are we hunting a living mob? @@ -153,7 +147,7 @@ /datum/ai_behavior/hunt_target/use_ability_on_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) var/datum/action/cooldown/ability = controller.blackboard[ability_key] if(!ability?.IsAvailable()) - finish_action(controller, FALSE, hunting_target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED return ..() /datum/ai_behavior/hunt_target/use_ability_on_target/target_caught(mob/living/hunter, atom/hunted) diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index d16110cd702..10a23acdabe 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -12,55 +12,51 @@ controller.clear_blackboard_key(BB_MONKEY_PICKUPTARGET) +/// Equips an item on the monkey +/// Returns TRUE if it works out, FALSE otherwise /datum/ai_behavior/monkey_equip/proc/equip_item(datum/ai_controller/controller) var/mob/living/living_pawn = controller.pawn var/obj/item/target = controller.blackboard[BB_MONKEY_PICKUPTARGET] var/best_force = controller.blackboard[BB_MONKEY_BEST_FORCE_FOUND] - if(!isturf(living_pawn.loc)) - finish_action(controller, FALSE) - return + return FALSE if(!target) - finish_action(controller, FALSE) - return + return FALSE if(target.anchored) //Can't pick it up, so stop trying. - finish_action(controller, FALSE) - return + return FALSE // Strong weapon else if(target.force > best_force) living_pawn.drop_all_held_items() living_pawn.put_in_hands(target) controller.set_blackboard_key(BB_MONKEY_BEST_FORCE_FOUND, target.force) - finish_action(controller, TRUE) - return + return TRUE else if(target.slot_flags) //Clothing == top priority living_pawn.dropItemToGround(target, TRUE) living_pawn.update_icons() if(!living_pawn.equip_to_appropriate_slot(target)) - finish_action(controller, FALSE) - return //Already wearing something, in the future this should probably replace the current item but the code didn't actually do that, and I dont want to support it right now. - finish_action(controller, TRUE) - return + return FALSE //Already wearing something, in the future this should probably replace the current item but the code didn't actually do that, and I dont want to support it right now. + return TRUE // EVERYTHING ELSE else if(living_pawn.get_empty_held_indexes()) living_pawn.put_in_hands(target) - finish_action(controller, TRUE) - return + return TRUE - finish_action(controller, FALSE) + return FALSE /datum/ai_behavior/monkey_equip/ground required_distance = 0 /datum/ai_behavior/monkey_equip/ground/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() - equip_item(controller) + if(equip_item(controller)) + return . | AI_BEHAVIOR_SUCCEEDED + return . | AI_BEHAVIOR_FAILED /datum/ai_behavior/monkey_equip/pickpocket @@ -110,13 +106,10 @@ /datum/ai_behavior/monkey_flee /datum/ai_behavior/monkey_flee/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - var/mob/living/living_pawn = controller.pawn - if(living_pawn.health >= MONKEY_FLEE_HEALTH) - finish_action(controller, TRUE) //we're back in bussiness - return + if(living_pawn.health >= MONKEY_FLEE_HEALTH) //we're back in bussiness + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/mob/living/target = null @@ -127,9 +120,9 @@ break if(target) - SSmove_manager.move_away(living_pawn, target, max_dist=MONKEY_ENEMY_VISION, delay=5) - else - finish_action(controller, TRUE) + DSmove_manager.move_away(living_pawn, target, max_dist=MONKEY_ENEMY_VISION, delay=5) + return AI_BEHAVIOR_DELAY + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/monkey_attack_mob behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM //performs to increase frustration @@ -139,29 +132,28 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/monkey_attack_mob/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/mob/living/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn - if(!target || target.stat != CONSCIOUS) - finish_action(controller, TRUE) //Target == owned - return + if(!target || target.stat != CONSCIOUS) //Target == owned + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED - if(isturf(target.loc) && !IS_DEAD_OR_INCAP(living_pawn)) // Check if they're a valid target - // check if target has a weapon - var/obj/item/W - for(var/obj/item/I in target.held_items) - if(!(I.item_flags & ABSTRACT)) - W = I - break - - // if the target has a weapon, chance to disarm them - if(W && SPT_PROB(MONKEY_ATTACK_DISARM_PROB, seconds_per_tick)) - monkey_attack(controller, target, seconds_per_tick, TRUE) - else - monkey_attack(controller, target, seconds_per_tick, FALSE) + if(!isturf(target.loc) || IS_DEAD_OR_INCAP(living_pawn)) // Check if they're a valid target + return AI_BEHAVIOR_DELAY + // check if target has a weapon + var/obj/item/W + for(var/obj/item/I in target.held_items) + if(!(I.item_flags & ABSTRACT)) + W = I + break + // if the target has a weapon, chance to disarm them + var/perform_flags = NONE + if(W && SPT_PROB(MONKEY_ATTACK_DISARM_PROB, seconds_per_tick)) + perform_flags = monkey_attack(controller, target, seconds_per_tick, TRUE) + else + perform_flags = monkey_attack(controller, target, seconds_per_tick, FALSE) + return AI_BEHAVIOR_DELAY | perform_flags /datum/ai_behavior/monkey_attack_mob/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -169,14 +161,14 @@ controller.clear_blackboard_key(target_key) if(QDELETED(living_pawn)) // pawn can be null at this point return - SSmove_manager.stop_looping(living_pawn) + DSmove_manager.stop_looping(living_pawn) /// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little /datum/ai_behavior/monkey_attack_mob/proc/monkey_attack(datum/ai_controller/controller, mob/living/target, seconds_per_tick, disarm) var/mob/living/living_pawn = controller.pawn if(living_pawn.next_move > world.time) - return + return NONE living_pawn.changeNext_move(CLICK_CD_MELEE) //We play fair @@ -215,7 +207,7 @@ // no de-aggro if(controller.blackboard[BB_MONKEY_AGGRESSIVE]) - return + return NONE // we've queued up a monkey attack on a mob which isn't already an enemy, so give them 1 threat to start // note they might immediately reduce threat and drop from the list. @@ -238,7 +230,8 @@ if(controller.blackboard[BB_MONKEY_ENEMIES][target] <= 0) controller.remove_thing_from_blackboard_key(BB_MONKEY_ENEMIES, target) if(controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] == target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_SUCCEEDED + return NONE /datum/ai_behavior/disposal_mob behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM //performs to increase frustration @@ -254,10 +247,8 @@ controller.clear_blackboard_key(disposal_target_key) //No target disposal /datum/ai_behavior/disposal_mob/perform(seconds_per_tick, datum/ai_controller/controller, attack_target_key, disposal_target_key) - . = ..() - if(controller.blackboard[BB_MONKEY_DISPOSING]) //We are disposing, don't do ANYTHING!!!! - return + return AI_BEHAVIOR_DELAY var/mob/living/target = controller.blackboard[attack_target_key] var/mob/living/living_pawn = controller.pawn @@ -265,25 +256,24 @@ set_movement_target(controller, target) if(!target) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(target.pulledby != living_pawn && !HAS_AI_CONTROLLER_TYPE(target.pulledby, /datum/ai_controller/monkey)) //Dont steal from my fellow monkeys. if(living_pawn.Adjacent(target) && isturf(target.loc)) target.grabbedby(living_pawn) - return //Do the rest next turn + return AI_BEHAVIOR_DELAY //Do the rest next turn var/obj/machinery/disposal/disposal = controller.blackboard[disposal_target_key] set_movement_target(controller, disposal) if(!disposal) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(living_pawn.Adjacent(disposal)) INVOKE_ASYNC(src, PROC_REF(try_disposal_mob), controller, attack_target_key, disposal_target_key) //put him in! - else //This means we might be getting pissed! - return + return AI_BEHAVIOR_DELAY + //This means we might be getting pissed! + return AI_BEHAVIOR_DELAY /datum/ai_behavior/disposal_mob/proc/try_disposal_mob(datum/ai_controller/controller, attack_target_key, disposal_target_key) var/mob/living/living_pawn = controller.pawn @@ -298,8 +288,6 @@ /datum/ai_behavior/recruit_monkeys/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() - controller.set_blackboard_key(BB_MONKEY_RECRUIT_COOLDOWN, world.time + MONKEY_RECRUIT_COOLDOWN) var/mob/living/living_pawn = controller.pawn @@ -313,7 +301,7 @@ // Other monkeys now also hate the guy we're currently targeting nearby_monkey.ai_controller.add_blackboard_key_assoc(BB_MONKEY_ENEMIES, controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET], MONKEY_RECRUIT_HATED_AMOUNT) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/monkey_set_combat_target/perform(seconds_per_tick, datum/ai_controller/controller, set_key, enemies_key) var/list/enemies = controller.blackboard[enemies_key] @@ -330,8 +318,7 @@ valids[possible_enemy] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1) if(!length(valids)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED controller.set_blackboard_key(set_key, pick_weight(valids)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/monkey/monkey_controller.dm b/code/datums/ai/monkey/monkey_controller.dm index 215f0a96302..693427ba4bd 100644 --- a/code/datums/ai/monkey/monkey_controller.dm +++ b/code/datums/ai/monkey/monkey_controller.dm @@ -45,7 +45,7 @@ have ways of interacting with a specific mob and control it. /datum/ai_controller/monkey/New(atom/new_pawn) var/static/list/control_examine = list( - ORGAN_SLOT_EYES = span_monkey("eyes have a primal look in them."), + ORGAN_SLOT_EYES = span_monkey("%PRONOUN_They stare%PRONOUN_s around with wild, primal eyes."), ) AddElement(/datum/element/ai_control_examine, control_examine) return ..() diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm index 3f455b2acd0..a0a75bb227c 100644 --- a/code/datums/ai/movement/_ai_movement.dm +++ b/code/datums/ai/movement/_ai_movement.dm @@ -17,7 +17,7 @@ moving_controllers -= controller // We got deleted as we finished an action if(!QDELETED(controller.pawn)) - SSmove_manager.stop_looping(controller.pawn, SSai_movement) + DSmove_manager.stop_looping(controller.pawn, SSai_movement) /datum/ai_movement/proc/increment_pathing_failures(datum/ai_controller/controller) controller.consecutive_pathing_attempts++ diff --git a/code/datums/ai/movement/ai_movement_basic_avoidance.dm b/code/datums/ai/movement/ai_movement_basic_avoidance.dm index 6b48f1b5e9e..bcfe6833a8d 100644 --- a/code/datums/ai/movement/ai_movement_basic_avoidance.dm +++ b/code/datums/ai/movement/ai_movement_basic_avoidance.dm @@ -9,7 +9,7 @@ var/atom/movable/moving = controller.pawn var/min_dist = controller.blackboard[BB_CURRENT_MIN_MOVE_DISTANCE] var/delay = controller.movement_delay - var/datum/move_loop/loop = SSmove_manager.move_to(moving, current_movement_target, min_dist, delay, flags = move_flags, subsystem = SSai_movement, extra_info = controller) + var/datum/move_loop/loop = DSmove_manager.move_to(moving, current_movement_target, min_dist, delay, flags = move_flags, subsystem = SSai_movement, extra_info = controller) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) diff --git a/code/datums/ai/movement/ai_movement_complete_stop.dm b/code/datums/ai/movement/ai_movement_complete_stop.dm index dcae93f1ba0..31309256a67 100644 --- a/code/datums/ai/movement/ai_movement_complete_stop.dm +++ b/code/datums/ai/movement/ai_movement_complete_stop.dm @@ -8,8 +8,8 @@ var/stopping_time = controller.blackboard[BB_STATIONARY_SECONDS] var/delay_time = (stopping_time * 0.5) // no real reason to fire any more often than this really // assume that the current_movement_target is our location - var/datum/move_loop/loop = SSmove_manager.freeze(moving, current_movement_target, delay = delay_time, timeout = stopping_time, subsystem = SSai_movement, extra_info = controller) + var/datum/move_loop/loop = DSmove_manager.freeze(moving, current_movement_target, delay = delay_time, timeout = stopping_time, subsystem = SSai_movement, extra_info = controller) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) /datum/ai_movement/complete_stop/allowed_to_move(datum/move_loop/source) - return FALSE + return FALSE diff --git a/code/datums/ai/movement/ai_movement_dumb.dm b/code/datums/ai/movement/ai_movement_dumb.dm index 06ac4bdd10c..a64a7539eec 100644 --- a/code/datums/ai/movement/ai_movement_dumb.dm +++ b/code/datums/ai/movement/ai_movement_dumb.dm @@ -7,7 +7,7 @@ . = ..() var/atom/movable/moving = controller.pawn var/delay = controller.movement_delay - var/datum/move_loop/loop = SSmove_manager.move_towards_legacy(moving, current_movement_target, delay, subsystem = SSai_movement, extra_info = controller) + var/datum/move_loop/loop = DSmove_manager.move_towards_legacy(moving, current_movement_target, delay, subsystem = SSai_movement, extra_info = controller) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) diff --git a/code/datums/ai/movement/ai_movement_jps.dm b/code/datums/ai/movement/ai_movement_jps.dm index 825feefabfa..ac16b0aaa23 100644 --- a/code/datums/ai/movement/ai_movement_jps.dm +++ b/code/datums/ai/movement/ai_movement_jps.dm @@ -12,7 +12,7 @@ var/atom/movable/moving = controller.pawn var/delay = controller.movement_delay - var/datum/move_loop/has_target/jps/loop = SSmove_manager.jps_move(moving, + var/datum/move_loop/has_target/jps/loop = DSmove_manager.jps_move(moving, current_movement_target, delay, repath_delay = 0.5 SECONDS, diff --git a/code/datums/ai/objects/mod.dm b/code/datums/ai/objects/mod.dm index 67d8121a4e1..edad77aa4c4 100644 --- a/code/datums/ai/objects/mod.dm +++ b/code/datums/ai/objects/mod.dm @@ -34,12 +34,11 @@ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT|AI_BEHAVIOR_MOVE_AND_PERFORM /datum/ai_behavior/mod_attach/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() if(!controller.pawn.Adjacent(controller.blackboard[BB_MOD_TARGET])) - return + return AI_BEHAVIOR_DELAY var/obj/item/implant/mod/implant = controller.blackboard[BB_MOD_IMPLANT] implant.module.attach(controller.blackboard[BB_MOD_TARGET]) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/mod_attach/finish_action(datum/ai_controller/controller, succeeded) . = ..() diff --git a/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm b/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm index b4e5609531c..d6310bfc9f3 100644 --- a/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm +++ b/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm @@ -10,15 +10,15 @@ set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/vendor_crush/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() if(controller.blackboard[BB_VENDING_BUSY_TILTING]) - return + return AI_BEHAVIOR_DELAY controller.ai_movement.stop_moving_towards(controller) controller.set_blackboard_key(BB_VENDING_BUSY_TILTING, TRUE) var/turf/target_turf = get_turf(controller.blackboard[BB_VENDING_CURRENT_TARGET]) new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(target_turf) addtimer(CALLBACK(src, PROC_REF(tiltonmob), controller, target_turf), time_to_tilt) + return AI_BEHAVIOR_DELAY /datum/ai_behavior/vendor_crush/proc/tiltonmob(datum/ai_controller/controller, turf/target_turf) var/obj/machinery/vending/vendor_pawn = controller.pawn @@ -40,10 +40,9 @@ var/succes_tilt_cooldown = 5 SECONDS /datum/ai_behavior/vendor_rise_up/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/obj/machinery/vending/vendor_pawn = controller.pawn vendor_pawn.visible_message(span_warning("[vendor_pawn] untilts itself!")) if(controller.blackboard[BB_VENDING_LAST_HIT_SUCCESFUL]) controller.set_blackboard_key(BB_VENDING_TILT_COOLDOWN, world.time + succes_tilt_cooldown) vendor_pawn.untilt() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/robot_customer/robot_customer_behaviors.dm b/code/datums/ai/robot_customer/robot_customer_behaviors.dm index 35fd26d76f6..7aa0f34f520 100644 --- a/code/datums/ai/robot_customer/robot_customer_behaviors.dm +++ b/code/datums/ai/robot_customer/robot_customer_behaviors.dm @@ -2,7 +2,6 @@ action_cooldown = 8 SECONDS /datum/ai_behavior/find_seat/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] @@ -28,22 +27,20 @@ customer_pawn.say(pick(customer_data.found_seat_lines)) controller.set_blackboard_key(BB_CUSTOMER_MY_SEAT, found_seat) attending_venue.linked_seats[found_seat] = customer_pawn - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED // SPT_PROB 1.5 is about a 60% chance that the tourist will have vocalised at least once every minute. if(!controller.blackboard[BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE] || SPT_PROB(1.5, seconds_per_tick)) customer_pawn.say(pick(customer_data.cant_find_seat_lines)) controller.set_blackboard_key(BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE, TRUE) - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/order_food behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT required_distance = 0 /datum/ai_behavior/order_food/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/obj/structure/holosign/robot_seat/seat_marker = controller.blackboard[BB_CUSTOMER_MY_SEAT] @@ -55,23 +52,19 @@ var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] controller.set_blackboard_key(BB_CUSTOMER_CURRENT_ORDER, attending_venue.order_food(customer_pawn, customer_data)) - - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/wait_for_food behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM required_distance = 0 /datum/ai_behavior/wait_for_food/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() if(controller.blackboard[BB_CUSTOMER_EATING]) - finish_action(controller, TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED controller.add_blackboard_key(BB_CUSTOMER_PATIENCE, seconds_per_tick * -1 SECONDS) // Convert seconds_per_tick to a SECONDS equivalent. if(controller.blackboard[BB_CUSTOMER_PATIENCE] < 0 || controller.blackboard[BB_CUSTOMER_LEAVING]) // Check if we're leaving because sometthing mightve forced us to - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED // SPT_PROB 1.5 is about a 40% chance that the tourist will have vocalised at least once every minute. if(SPT_PROB(0.85, seconds_per_tick)) @@ -95,6 +88,7 @@ customer.eat_order(I, attending_venue) break + return AI_BEHAVIOR_DELAY /datum/ai_behavior/wait_for_food/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -121,6 +115,5 @@ set_movement_target(controller, attending_venue.restaurant_portal) /datum/ai_behavior/leave_venue/perform(seconds_per_tick, datum/ai_controller/controller, venue_key) - . = ..() qdel(controller.pawn) //save the world, my final message, goodbye. - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index 5b8666413e3..1bf011e0fab 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -491,6 +491,7 @@ owner.ai_controller = new /datum/ai_controller/monkey(owner) owner.ai_controller.continue_processing_when_client = TRUE + owner.ai_controller.can_idle = FALSE owner.ai_controller.set_ai_status(AI_STATUS_OFF) /datum/brain_trauma/special/primal_instincts/on_lose(silent) @@ -514,7 +515,7 @@ owner.grant_language(/datum/language/monkey, UNDERSTOOD_LANGUAGE, TRAUMA_TRAIT) owner.ai_controller.set_blackboard_key(BB_MONKEY_AGGRESSIVE, prob(75)) if(owner.ai_controller.ai_status == AI_STATUS_OFF) - owner.ai_controller.set_ai_status(AI_STATUS_IDLE) + owner.ai_controller.set_ai_status(AI_STATUS_ON) owner.log_message("became controlled by monkey instincts ([owner.ai_controller.blackboard[BB_MONKEY_AGGRESSIVE] ? "aggressive" : "docile"])", LOG_ATTACK, color = "orange") to_chat(owner, span_warning("You feel the urge to act on your primal instincts...")) // extend original timer if we roll the effect while it's already ongoing diff --git a/code/datums/components/conveyor_movement.dm b/code/datums/components/conveyor_movement.dm index d8affca3649..61a0066ff4a 100644 --- a/code/datums/components/conveyor_movement.dm +++ b/code/datums/components/conveyor_movement.dm @@ -15,7 +15,7 @@ if(!start_delay) start_delay = speed var/atom/movable/moving_parent = parent - var/datum/move_loop/loop = SSmove_manager.move(moving_parent, direction, delay = start_delay, subsystem = SSconveyors, flags=MOVEMENT_LOOP_IGNORE_PRIORITY|MOVEMENT_LOOP_OUTSIDE_CONTROL) + var/datum/move_loop/loop = DSmove_manager.move(moving_parent, direction, delay = start_delay, subsystem = SSconveyors, flags=MOVEMENT_LOOP_IGNORE_PRIORITY|MOVEMENT_LOOP_OUTSIDE_CONTROL) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(should_move)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(loop_ended)) diff --git a/code/datums/components/crafting/_recipes.dm b/code/datums/components/crafting/_recipes.dm index 4254804974e..09121339d30 100644 --- a/code/datums/components/crafting/_recipes.dm +++ b/code/datums/components/crafting/_recipes.dm @@ -41,6 +41,8 @@ var/result_amount /// Whether we should delete the contents of the crafted storage item (Only works with storage items, used for ammo boxes, donut boxes, internals boxes, etc) var/delete_contents = TRUE + /// Allows you to craft so that you don't have to click the craft button many times. + var/mass_craftable = FALSE /datum/crafting_recipe/New() if(!name && result) diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm index a6a905ccdb4..6fc560a293f 100644 --- a/code/datums/components/crafting/crafting.dm +++ b/code/datums/components/crafting/crafting.dm @@ -458,28 +458,39 @@ return data +/datum/component/personal_crafting/proc/make_action(datum/crafting_recipe/recipe, mob/user) + var/atom/movable/result = construct_item(user, recipe) + if(istext(result)) //We failed to make an item and got a fail message + to_chat(user, span_warning("Construction failed[result]")) + return FALSE + if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine + user.put_in_hands(result) + else if(!istype(result, /obj/effect/spawner)) + result.forceMove(user.drop_location()) + to_chat(user, span_notice("[recipe.name] crafted.")) + user.investigate_log("crafted [recipe]", INVESTIGATE_CRAFTING) + recipe.on_craft_completion(user, result) + return TRUE + + /datum/component/personal_crafting/ui_act(action, params) . = ..() if(.) return switch(action) - if("make") + if("make", "make_mass") var/mob/user = usr var/datum/crafting_recipe/crafting_recipe = locate(params["recipe"]) in (mode ? GLOB.cooking_recipes : GLOB.crafting_recipes) busy = TRUE ui_interact(user) - var/atom/movable/result = construct_item(user, crafting_recipe) - if(!istext(result)) //We made an item and didn't get a fail message - if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine - user.put_in_hands(result) - else - if(!istype(result, /obj/effect/spawner)) - result.forceMove(user.drop_location()) - to_chat(user, span_notice("[crafting_recipe.name] crafted.")) - user.investigate_log("crafted [crafting_recipe]", INVESTIGATE_CRAFTING) - crafting_recipe.on_craft_completion(user, result) + if(action == "make_mass") + var/crafted_items = 0 + while(make_action(crafting_recipe, user)) + crafted_items++ + if(crafted_items) + to_chat(user, span_notice("You made [crafted_items] item\s.")) else - to_chat(user, span_warning("Construction failed[result]")) + make_action(crafting_recipe, user) busy = FALSE if("toggle_recipes") display_craftable_only = !display_craftable_only @@ -549,6 +560,7 @@ // Crafting if(recipe.non_craftable) data["non_craftable"] = recipe.non_craftable + data["mass_craftable"] = recipe.mass_craftable if(recipe.steps) data["steps"] = recipe.steps diff --git a/code/datums/components/crafting/entertainment.dm b/code/datums/components/crafting/entertainment.dm index dae810c220a..84b2ef163bb 100644 --- a/code/datums/components/crafting/entertainment.dm +++ b/code/datums/components/crafting/entertainment.dm @@ -112,6 +112,7 @@ /obj/item/spear/explosive, /obj/item/spear/bonespear, /obj/item/spear/bamboospear, + /obj/item/spear/military, ) result = /obj/structure/headpike category = CAT_ENTERTAINMENT @@ -144,6 +145,20 @@ result = /obj/structure/headpike/bamboo category = CAT_ENTERTAINMENT +/datum/crafting_recipe/headpikemilitary + name = "Spike Head (Military)" + time = 6.5 SECONDS + reqs = list( + /obj/item/spear/military = 1, + /obj/item/bodypart/head = 1, + ) + parts = list( + /obj/item/bodypart/head = 1, + /obj/item/spear/military = 1, + ) + result = /obj/structure/headpike/military + category = CAT_ENTERTAINMENT + /datum/crafting_recipe/guillotine name = "Guillotine" result = /obj/structure/guillotine diff --git a/code/datums/components/drift.dm b/code/datums/components/drift.dm index 6b91a83534f..f8ad46e3ec3 100644 --- a/code/datums/components/drift.dm +++ b/code/datums/components/drift.dm @@ -23,7 +23,7 @@ if(instant) flags |= MOVEMENT_LOOP_START_FAST var/atom/movable/movable_parent = parent - drifting_loop = SSmove_manager.move(moving = parent, direction = direction, delay = movable_parent.inertia_move_delay, subsystem = SSspacedrift, priority = MOVEMENT_SPACE_PRIORITY, flags = flags) + drifting_loop = DSmove_manager.move(moving = parent, direction = direction, delay = movable_parent.inertia_move_delay, subsystem = SSspacedrift, priority = MOVEMENT_SPACE_PRIORITY, flags = flags) if(!drifting_loop) //Really want to qdel here but can't return COMPONENT_INCOMPATIBLE diff --git a/code/datums/components/explodable.dm b/code/datums/components/explodable.dm index 956d562bfb6..439b1563521 100644 --- a/code/datums/components/explodable.dm +++ b/code/datums/components/explodable.dm @@ -122,13 +122,7 @@ if(!istype(wearer)) return FALSE - // Maybe switch this over if we have a get_all_clothing or similar proc for carbon mobs. - // get_all_worn_items is a lie, they include pockets. - var/list/worn_items = list() - worn_items += list(wearer.head, wearer.wear_mask, wearer.gloves, wearer.shoes, wearer.glasses, wearer.ears) - if(ishuman(wearer)) - var/mob/living/carbon/human/human_wearer = wearer - worn_items += list(human_wearer.wear_suit, human_wearer.w_uniform) + var/list/worn_items = wearer.get_equipped_items() if(!(item in worn_items)) return FALSE diff --git a/code/datums/components/force_move.dm b/code/datums/components/force_move.dm index b8c36818621..6c1c1e38e5f 100644 --- a/code/datums/components/force_move.dm +++ b/code/datums/components/force_move.dm @@ -9,7 +9,7 @@ var/mob/mob_parent = parent var/dist = get_dist(mob_parent, target) - var/datum/move_loop/loop = SSmove_manager.move_towards(mob_parent, target, delay = 1, timeout = dist) + var/datum/move_loop/loop = DSmove_manager.move_towards(mob_parent, target, delay = 1, timeout = dist) RegisterSignal(mob_parent, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE, PROC_REF(stop_move)) RegisterSignal(mob_parent, COMSIG_ATOM_PRE_PRESSURE_PUSH, PROC_REF(stop_pressure)) if(spin) diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index 33b713e8a57..1faa04ceacc 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -249,7 +249,7 @@ if(get_dist(shooter, target) <= 0) target = get_step(shooter, shooter.dir) //Shoot in the direction faced if the mouse is on the same tile as we are. target_loc = target - else if(!in_view_range(shooter, target)) + else if(!CAN_THEY_SEE(target, shooter)) stop_autofiring() //Elvis has left the building. return FALSE shooter.face_atom(target) diff --git a/code/datums/components/material/remote_materials.dm b/code/datums/components/material/remote_materials.dm index 568b018e58b..695a02bcb96 100644 --- a/code/datums/components/material/remote_materials.dm +++ b/code/datums/components/material/remote_materials.dm @@ -86,7 +86,7 @@ handles linking back and forth. mat_container = parent.AddComponent( \ /datum/component/material_container, \ - SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ local_size, \ mat_container_flags, \ container_signals = mat_container_signals, \ diff --git a/code/datums/components/plumbing/splitter.dm b/code/datums/components/plumbing/splitter.dm index 4dd68a9e578..5ade1dfebc3 100644 --- a/code/datums/components/plumbing/splitter.dm +++ b/code/datums/components/plumbing/splitter.dm @@ -43,5 +43,6 @@ if(EAST) if(amount >= S.transfer_side) amount = S.transfer_side + S.use_energy(S.active_power_usage) return ..() diff --git a/code/datums/components/ranged_mob_full_auto.dm b/code/datums/components/ranged_mob_full_auto.dm index a33b705d548..ff3bfcfe60f 100644 --- a/code/datums/components/ranged_mob_full_auto.dm +++ b/code/datums/components/ranged_mob_full_auto.dm @@ -56,7 +56,7 @@ if (get_dist(living_parent, target) <= 0) set_target(get_step(living_parent, living_parent.dir)) // Shoot in the direction faced if the mouse is on the same tile as we are. target_loc = target - else if (!in_view_range(living_parent, target)) + else if (!CAN_THEY_SEE(target, living_parent)) stop_firing() return FALSE // Can't see shit diff --git a/code/datums/components/shuttle_cling.dm b/code/datums/components/shuttle_cling.dm index 6702b9d601d..724060c9cbe 100644 --- a/code/datums/components/shuttle_cling.dm +++ b/code/datums/components/shuttle_cling.dm @@ -51,7 +51,7 @@ update_state(parent) //otherwise we'll get moved 1 tile before we can correct ourselves, which isnt super bad but just looks jank /datum/component/shuttle_cling/proc/initialize_loop() - hyperloop = SSmove_manager.move(moving = parent, direction = direction, delay = not_clinging_move_delay, subsystem = SShyperspace_drift, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_NO_DIR_UPDATE|MOVEMENT_LOOP_OUTSIDE_CONTROL) + hyperloop = DSmove_manager.move(moving = parent, direction = direction, delay = not_clinging_move_delay, subsystem = SShyperspace_drift, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_NO_DIR_UPDATE|MOVEMENT_LOOP_OUTSIDE_CONTROL) update_state() /datum/component/shuttle_cling/proc/clear_loop() diff --git a/code/datums/components/surgery_initiator.dm b/code/datums/components/surgery_initiator.dm index 24bde4b4672..c609d7216e0 100644 --- a/code/datums/components/surgery_initiator.dm +++ b/code/datums/components/surgery_initiator.dm @@ -135,8 +135,11 @@ required_tool_type = TOOL_SCREWDRIVER if(iscyborg(user)) - close_tool = locate(/obj/item/cautery) in user.held_items - if(!close_tool) + var/has_cautery = FALSE + for(var/obj/item/borg/cyborg_omnitool/medical/omnitool in user.held_items) + if(omnitool.tool_behaviour == TOOL_CAUTERY) + has_cautery = TRUE + if(!has_cautery) patient.balloon_alert(user, "need a cautery in an inactive slot to stop the surgery!") return else if(!close_tool || close_tool.tool_behaviour != required_tool_type) diff --git a/code/datums/elements/ai_control_examine.dm b/code/datums/elements/ai_control_examine.dm index b470ac44b49..279fc80dc81 100644 --- a/code/datums/elements/ai_control_examine.dm +++ b/code/datums/elements/ai_control_examine.dm @@ -46,7 +46,7 @@ if(noticable_organ_examines[possibly_noticable.slot]) make_organ_noticable(possibly_noticable.slot, possibly_noticable) -/datum/element/ai_control_examine/proc/make_organ_noticable(organ_slot, obj/item/organ/noticable_organ) +/datum/element/ai_control_examine/proc/make_organ_noticable(organ_slot, obj/item/organ/noticable_organ, mob/living/carbon/human/human_pawn) var/examine_text = noticable_organ_examines[organ_slot] var/body_zone = organ_slot != ORGAN_SLOT_BRAIN ? noticable_organ.zone : null noticable_organ.AddElement(/datum/element/noticable_organ/ai_control, examine_text, body_zone) diff --git a/code/datums/elements/noticable_organ.dm b/code/datums/elements/noticable_organ.dm index 1a6a895e535..a6247d18bb5 100644 --- a/code/datums/elements/noticable_organ.dm +++ b/code/datums/elements/noticable_organ.dm @@ -6,15 +6,13 @@ /datum/element/noticable_organ element_flags = ELEMENT_BESPOKE argument_hash_start_idx = 2 - /// whether we wrap the examine text in a notice span. - var/add_span = TRUE - /// "[they]|[their] [desc here]", shows on examining someone with an infused organ. - /// Uses a possessive pronoun (His/Her/Their) if a body zone is given, or a singular pronoun (He/She/They) otherwise. + + ///Shows on examining someone with an infused organ. var/infused_desc - /// Which body zone has to be exposed. If none is set, this is always noticable, and the description pronoun becomes singular instead of possesive. + /// Which body zone has to be exposed. If none is set, this is always noticable. var/body_zone -/datum/element/noticable_organ/Attach(datum/target, infused_desc, body_zone) +/datum/element/noticable_organ/Attach(obj/item/organ/target, infused_desc, body_zone) . = ..() if(!isorgan(target)) @@ -23,8 +21,10 @@ src.infused_desc = infused_desc src.body_zone = body_zone - RegisterSignal(target, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_implanted)) + RegisterSignal(target, COMSIG_ORGAN_IMPLANTED, PROC_REF(enable_description)) RegisterSignal(target, COMSIG_ORGAN_REMOVED, PROC_REF(on_removed)) + if(target.owner) + enable_description(target, target.owner) /datum/element/noticable_organ/Detach(obj/item/organ/target) UnregisterSignal(target, list(COMSIG_ORGAN_IMPLANTED, COMSIG_ORGAN_REMOVED)) @@ -38,7 +38,7 @@ return FALSE return TRUE -/datum/element/noticable_organ/proc/on_implanted(obj/item/organ/target, mob/living/carbon/receiver) +/datum/element/noticable_organ/proc/enable_description(obj/item/organ/target, mob/living/carbon/receiver) SIGNAL_HANDLER RegisterSignal(receiver, COMSIG_ATOM_EXAMINE, PROC_REF(on_receiver_examine)) @@ -53,16 +53,17 @@ if(!should_show_text(examined)) return - var/examine_text = replacetext(replacetext("[body_zone ? examined.p_Their() : examined.p_They()] [infused_desc]", "%PRONOUN_ES", examined.p_es()), "%PRONOUN_S", examined.p_s()) - if(add_span) - examine_text = span_notice(examine_text) + + var/examine_text = REPLACE_PRONOUNS(infused_desc, examined) + + examine_list += examine_text /** * Subtype of noticable organs for AI control, that will make a few more ai status checks before forking over the examine. */ /datum/element/noticable_organ/ai_control - add_span = FALSE + /datum/element/noticable_organ/ai_control/should_show_text(mob/living/carbon/examined) . = ..() diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index ec111fb3cf0..8e20dfbef9c 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -1,87 +1,271 @@ +#define LEFT_RIGHT_COMBO "DH" +#define RIGHT_LEFT_COMBO "HD" +#define LEFT_LEFT_COMBO "HH" +#define RIGHT_RIGHT_COMBO "DD" + /datum/martial_art/boxing name = "Boxing" id = MARTIALART_BOXING pacifist_style = TRUE + ///Boolean on whether we are sportsmanlike in our tussling; TRUE means we have restrictions + var/honorable_boxer = TRUE + /// List of traits applied to users of this martial art. + var/list/boxing_traits = list(TRAIT_BOXING_READY) + /// Balloon alert cooldown for warning our boxer to alternate their blows to get more damage + COOLDOWN_DECLARE(warning_cooldown) /datum/martial_art/boxing/teach(mob/living/new_holder, make_temporary) if(!ishuman(new_holder)) return FALSE + new_holder.add_traits(boxing_traits, BOXING_TRAIT) + RegisterSignal(new_holder, COMSIG_LIVING_CHECK_BLOCK, PROC_REF(check_block)) return ..() -/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/attacker, mob/living/defender) - attacker.balloon_alert(attacker, "can't disarm while boxing!") - return MARTIAL_ATTACK_FAIL +/datum/martial_art/boxing/on_remove(mob/living/remove_from) + remove_from.remove_traits(boxing_traits, BOXING_TRAIT) + UnregisterSignal(remove_from, list(COMSIG_LIVING_CHECK_BLOCK)) + return ..() -/datum/martial_art/boxing/grab_act(mob/living/carbon/human/attacker, mob/living/defender) - attacker.balloon_alert(attacker, "can't grab while boxing!") - return MARTIAL_ATTACK_FAIL +///Unlike most instances of this proc, this is actually called in _proc/tussle() +///Returns a multiplier on our skill damage bonus. +/datum/martial_art/boxing/proc/check_streak(mob/living/attacker, mob/living/defender) + var/combo_multiplier = 1 + + if(findtext(streak, LEFT_LEFT_COMBO) || findtext(streak, RIGHT_RIGHT_COMBO)) + reset_streak() + if(COOLDOWN_FINISHED(src, warning_cooldown)) + COOLDOWN_START(src, warning_cooldown, 2 SECONDS) + attacker.balloon_alert(attacker, "weak combo, alternate your hits!") + return combo_multiplier * 0.5 + + if(findtext(streak, LEFT_RIGHT_COMBO) || findtext(streak, RIGHT_LEFT_COMBO)) + reset_streak() + return combo_multiplier * 1.5 + + return combo_multiplier + +/datum/martial_art/boxing/disarm_act(mob/living/attacker, mob/living/defender) + if(honor_check(defender)) + add_to_streak("D", defender) + tussle(attacker, defender, "right hook", "right hooked") + return MARTIAL_ATTACK_SUCCESS + +/datum/martial_art/boxing/grab_act(mob/living/attacker, mob/living/defender) + if(honorable_boxer) + attacker.balloon_alert(attacker, "no grabbing while boxing!") + return MARTIAL_ATTACK_FAIL + return MARTIAL_ATTACK_INVALID //UNLESS YOU'RE EVIL + +/datum/martial_art/boxing/harm_act(mob/living/attacker, mob/living/defender) + if(honor_check(defender)) + add_to_streak("H", defender) + tussle(attacker, defender, "left hook", "left hooked") + return MARTIAL_ATTACK_SUCCESS + +// Our only boxing move, which occurs on literally all attacks; the tussle. However, quite a lot morphs the results of this proc. Combos, unlike most martial arts attacks, are checked in this proc rather than our standard unarmed procs +/datum/martial_art/boxing/proc/tussle(mob/living/attacker, mob/living/defender, atk_verb = "blind jab", atk_verbed = "blind jabbed") + + if(honorable_boxer) //Being a good sport, you never hit someone on the ground or already knocked down. It shows you're the better person. + if(defender.body_position == LYING_DOWN && defender.getStaminaLoss() >= 100 || defender.IsUnconscious()) //If they're in stamcrit or unconscious, don't bloody punch them + attacker.balloon_alert(attacker, "unsportsmanlike behaviour!") + return FALSE -/datum/martial_art/boxing/harm_act(mob/living/carbon/human/attacker, mob/living/defender) var/obj/item/bodypart/arm/active_arm = attacker.get_active_hand() + + //The values between which damage is rolled for punches + var/lower_force = active_arm.unarmed_damage_low + var/upper_force = active_arm.unarmed_damage_high + + //Determines knockout potential and armor penetration (if that matters) + var/base_unarmed_effectiveness = active_arm.unarmed_effectiveness + + //Determines attack sound based on attacker arm + var/attack_sound = active_arm.unarmed_attack_sound + + // Out athletics skill is added as a damage bonus + var/athletics_skill = attacker.mind?.get_skill_level(/datum/skill/athletics) + + // If true, grants experience for punching; we only gain experience if we punch another boxer. + var/grant_experience = FALSE + + // What type of damage does our kind of boxing do? Defaults to STAMINA, unless you're performing EVIL BOXING + var/damage_type = honorable_boxer ? STAMINA : attacker.get_attack_type() + attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH) - var/damage = rand(5, 8) + active_arm.unarmed_damage_low - var/atk_verb = pick("left hook", "right hook", "straight punch") - if(damage <= 0) - playsound(defender, active_arm.unarmed_miss_sound, 25, TRUE, -1) - defender.visible_message( - span_warning("[attacker]'s [atk_verb] misses [defender]!"), - span_danger("You avoid [attacker]'s [atk_verb]!"), - span_hear("You hear a swoosh!"), - COMBAT_MESSAGE_RANGE, - attacker, - ) - to_chat(attacker, span_warning("Your [atk_verb] misses [defender]!")) - log_combat(attacker, defender, "attempted to hit", atk_verb) - return MARTIAL_ATTACK_FAIL + //Determines damage dealt on a punch. Against a boxing defender, we apply our skill bonus. + var/damage = rand(lower_force, upper_force) - if(defender.check_block(attacker, damage, "[attacker]'s [atk_verb]", UNARMED_ATTACK)) - return MARTIAL_ATTACK_FAIL + if(honor_check(defender)) + var/strength_bonus = HAS_TRAIT(attacker, TRAIT_STRENGTH) ? 2 : 0 //Investing into genetic strength improvements makes you a better boxer + damage += round(athletics_skill * check_streak(attacker, defender) + strength_bonus) + grant_experience = TRUE + + var/current_atk_verb = atk_verb + var/current_atk_verbed = atk_verbed + + if(is_detective_job(attacker.mind?.assigned_role)) //In short: discombobulate + current_atk_verb = "discombobulate" + current_atk_verbed = "discombulated" + + // Similar to a normal punch, should we have a value of 0 for our lower force, we simply miss outright. + if(!lower_force) + playsound(defender.loc, active_arm.unarmed_miss_sound, 25, TRUE, -1) + defender.visible_message(span_warning("[attacker]'s [current_atk_verb] misses [defender]!"), \ + span_danger("You avoid [attacker]'s [current_atk_verb]!"), span_hear("You hear a swoosh!"), COMBAT_MESSAGE_RANGE, attacker) + to_chat(attacker, span_warning("Your [current_atk_verb] misses [defender]!")) + log_combat(attacker, defender, "attempted to hit", current_atk_verb) + return FALSE + + if(defender.check_block(attacker, damage, "[attacker]'s [current_atk_verb]", UNARMED_ATTACK)) + return FALSE var/obj/item/bodypart/affecting = defender.get_bodypart(defender.get_random_valid_zone(attacker.zone_selected)) - var/armor_block = defender.run_armor_check(affecting, MELEE) + var/armor_block = defender.run_armor_check(affecting, MELEE, armour_penetration = base_unarmed_effectiveness) + + playsound(defender, attack_sound, 25, TRUE, -1) - playsound(defender, active_arm.unarmed_attack_sound, 25, TRUE, -1) defender.visible_message( - span_danger("[attacker] [atk_verb]ed [defender]!"), - span_userdanger("You're [atk_verb]ed by [attacker]!"), + span_danger("[attacker] [current_atk_verbed] [defender]!"), + span_userdanger("You're [current_atk_verbed] by [attacker]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker, ) - to_chat(attacker, span_danger("You [atk_verb]ed [defender]!")) - defender.apply_damage(damage, STAMINA, affecting, armor_block) + + to_chat(attacker, span_danger("You [current_atk_verbed] [defender]!")) + + defender.apply_damage(damage, damage_type, affecting, armor_block) + log_combat(attacker, defender, "punched (boxing) ") - if(defender.getStaminaLoss() > 50 && istype(defender.mind?.martial_art, /datum/martial_art/boxing)) - var/knockout_prob = defender.getStaminaLoss() + rand(-15, 15) - if(defender.stat != DEAD && prob(knockout_prob)) - defender.visible_message( - span_danger("[attacker] knocks [defender] out with a haymaker!"), - span_userdanger("You're knocked unconscious by [attacker]!"), - span_hear("You hear a sickening sound of flesh hitting flesh!"), - COMBAT_MESSAGE_RANGE, - attacker, - ) - to_chat(attacker, span_danger("You knock [defender] out with a haymaker!")) - defender.apply_effect(20 SECONDS, EFFECT_KNOCKDOWN, armor_block) - defender.SetSleeping(10 SECONDS) - log_combat(attacker, defender, "knocked out (boxing) ") - return MARTIAL_ATTACK_SUCCESS + + if(grant_experience) + skill_experience_adjustment(attacker, (damage/lower_force)) + + if(defender.stat == DEAD || !honor_check(defender)) //early returning here so we don't worry about knockout probs + return TRUE + + //Determine our attackers athletics level as a knockout probability bonus + var/attacker_athletics_skill = (attacker.mind?.get_skill_modifier(/datum/skill/athletics, SKILL_RANDS_MODIFIER) + base_unarmed_effectiveness) + + // Defender boxing skill and armor block are used as a defense here. This has already factored in base_unarmed_effectiveness from the attacker + var/defender_athletics_skill = clamp(defender.mind?.get_skill_modifier(/datum/skill/athletics, SKILL_RANDS_MODIFIER), 0, 100) + + //Determine our final probability, using a clamp to stop any prob() weirdness. + var/final_knockout_probability = clamp(round(attacker_athletics_skill - defender_athletics_skill), 0 , 100) + + if(!prob(final_knockout_probability)) + return TRUE + + if(defender.get_timed_status_effect_duration(/datum/status_effect/staggered)) + defender.visible_message( + span_danger("[attacker] knocks [defender] out with a haymaker!"), + span_userdanger("You're knocked unconscious by [attacker]!"), + span_hear("You hear a sickening sound of flesh hitting flesh!"), + COMBAT_MESSAGE_RANGE, + attacker, + ) + to_chat(attacker, span_danger("You knock [defender] out with a haymaker!")) + defender.apply_effect(20 SECONDS, EFFECT_KNOCKDOWN, armor_block) + defender.SetSleeping(10 SECONDS) + log_combat(attacker, defender, "knocked out (boxing) ") + else + defender.visible_message( + span_danger("[attacker] staggers [defender] with a haymaker!"), + span_userdanger("You're nearly knocked off your feet by [attacker]!"), + span_hear("You hear a sickening sound of flesh hitting flesh!"), + COMBAT_MESSAGE_RANGE, + attacker, + ) + defender.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH, 10 SECONDS) + to_chat(attacker, span_danger("You stagger [defender] with a haymaker!")) + log_combat(attacker, defender, "staggered (boxing) ") + + playsound(defender, 'sound/effects/coin2.ogg', 40, TRUE) + new /obj/effect/temp_visual/crit(get_turf(defender)) + skill_experience_adjustment(attacker, (damage/lower_force)) //double experience for a successful crit + + return TRUE + +/// Returns whether whoever is checked by this proc is complying with the rules of boxing. The boxer cannot block non-boxers, and cannot apply their scariest moves against non-boxers. +/datum/martial_art/boxing/proc/honor_check(mob/living/possible_boxer) + if(!honorable_boxer) + return TRUE //You scoundrel!! + + if(!HAS_TRAIT(possible_boxer, TRAIT_BOXING_READY)) + return FALSE + + return TRUE + +/// Handles our instances of experience gain while boxing. It also applies the exercised status effect. +/datum/martial_art/boxing/proc/skill_experience_adjustment(mob/living/boxer, experience_value) + //Boxing in heavier gravity gives you more experience + var/gravity_modifier = boxer.has_gravity() > STANDARD_GRAVITY ? 1 : 0.5 + + //You gotta sleep before you get any experience! + boxer.mind?.adjust_experience(/datum/skill/athletics, experience_value * gravity_modifier) + boxer.apply_status_effect(/datum/status_effect/exercised) + +/// Handles our blocking signals, similar to hit_reaction() on items. Only blocks while the boxer is in throw mode. +/datum/martial_art/boxing/proc/check_block(mob/living/boxer, atom/movable/hitby, damage, attack_text, attack_type, ...) + SIGNAL_HANDLER + + if(!can_use(boxer) || !boxer.throw_mode || boxer.incapacitated(IGNORE_GRAB)) + return NONE + + if(attack_type != UNARMED_ATTACK) + return NONE + + //Determines unarmed defense against boxers using our current active arm. + var/obj/item/bodypart/arm/active_arm = boxer.get_active_hand() + var/base_unarmed_effectiveness = active_arm.unarmed_effectiveness + + // Out athletics skill is added to our block potential + var/athletics_skill_rands = boxer.mind?.get_skill_modifier(/datum/skill/athletics, SKILL_RANDS_MODIFIER) + + var/block_chance = base_unarmed_effectiveness + athletics_skill_rands + + var/block_text = pick("block", "evade") + + if(!prob(block_chance)) + return NONE + + var/mob/living/attacker = GET_ASSAILANT(hitby) + + if(!honor_check(attacker)) + return NONE + + if(istype(attacker) && boxer.Adjacent(attacker)) + attacker.apply_damage(10, STAMINA) + boxer.apply_damage(5, STAMINA) + + boxer.visible_message( + span_danger("[boxer] [block_text]s [attack_text]!"), + span_userdanger("You [block_text] [attack_text]!"), + ) + if(block_text == "evade") + playsound(boxer.loc, active_arm.unarmed_miss_sound, 25, TRUE, -1) + + skill_experience_adjustment(boxer, 1) //just getting hit a bunch doesn't net you much experience + + return SUCCESSFUL_BLOCK /datum/martial_art/boxing/can_use(mob/living/martial_artist) if(!ishuman(martial_artist)) return FALSE return ..() -/obj/item/clothing/gloves/boxing +/// Evil Boxing; for sick, evil scoundrels. Has no honor, making it more lethal (therefore unable to be used by pacifists). +/// Grants Strength and Stimmed to speed up any experience gain. -/obj/item/clothing/gloves/boxing/Initialize(mapload) - . = ..() - var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/extendohand_l, /datum/crafting_recipe/extendohand_r) +/datum/martial_art/boxing/evil + name = "Evil Boxing" + id = MARTIALART_EVIL_BOXING + pacifist_style = FALSE + honorable_boxer = FALSE + boxing_traits = list(TRAIT_BOXING_READY, TRAIT_STRENGTH, TRAIT_STIMMED) - AddComponent( - /datum/component/slapcrafting,\ - slapcraft_recipes = slapcraft_recipe_list,\ - ) - - AddComponent(/datum/component/martial_art_giver, /datum/martial_art/boxing) +#undef LEFT_RIGHT_COMBO +#undef RIGHT_LEFT_COMBO +#undef LEFT_LEFT_COMBO +#undef RIGHT_RIGHT_COMBO diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index da5a15b8d31..9d6b8674728 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -10,7 +10,7 @@ Simple datum which is instanced once per type and is used for every object of sa var/name = "material" /// A short description of the material. Not used anywhere, yet... var/desc = "its..stuff." - /// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material. + /// What the material is indexed by in the DSmaterials.materials list. Defaults to the type of the material. var/id ///Base color of the material, is used for greyscale. Item isn't changed in color if this is null. @@ -23,7 +23,7 @@ Simple datum which is instanced once per type and is used for every object of sa ///Starlight color of the material ///This is the color of light it'll emit if its turf is transparent and over space. Defaults to COLOR_STARLIGHT if not set var/starlight_color - ///Bitflags that influence how SSmaterials handles this material. + ///Bitflags that influence how DSmaterials handles this material. var/init_flags = MATERIAL_INIT_MAPLOAD ///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for var/list/categories = list() diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 6d3768704fb..b7b781c1819 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -279,15 +279,42 @@ desc = "The user's muscles slightly expand." quality = POSITIVE text_gain_indication = "You feel strong." + instability = 5 difficulty = 16 +/datum/mutation/human/strong/on_acquiring(mob/living/carbon/human/owner) + . = ..() + if(.) + return + ADD_TRAIT(owner, TRAIT_STRENGTH, GENETIC_MUTATION) + +/datum/mutation/human/strong/on_losing(mob/living/carbon/human/owner) + . = ..() + if(.) + return + REMOVE_TRAIT(owner, TRAIT_STRENGTH, GENETIC_MUTATION) + + /datum/mutation/human/stimmed name = "Stimmed" desc = "The user's chemical balance is more robust." quality = POSITIVE text_gain_indication = "You feel stimmed." + instability = 5 difficulty = 16 +/datum/mutation/human/stimmed/on_acquiring(mob/living/carbon/human/owner) + . = ..() + if(.) + return + ADD_TRAIT(owner, TRAIT_STIMMED, GENETIC_MUTATION) + +/datum/mutation/human/stimmed/on_losing(mob/living/carbon/human/owner) + . = ..() + if(.) + return + REMOVE_TRAIT(owner, TRAIT_STIMMED, GENETIC_MUTATION) + /datum/mutation/human/insulated name = "Insulated" desc = "The affected person does not conduct electricity." diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 8c8642a81ea..311725d9cc6 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -278,4 +278,22 @@ TRAIT_STUNIMMUNE, ) // no chunk +/datum/mutation/human/hulk/superhuman + health_req = 0 + instability = 0 + /// List of traits to add/remove when someone gets this mutation. + mutation_traits = list( + TRAIT_CHUNKYFINGERS, + TRAIT_HULK, + TRAIT_IGNOREDAMAGESLOWDOWN, + TRAIT_NOSOFTCRIT, + TRAIT_NOHARDCRIT, + TRAIT_PUSHIMMUNE, + TRAIT_STUNIMMUNE, + TRAIT_ANALGESIA, + ) // fight till your last breath + +/datum/mutation/human/hulk/superhuman/on_life(seconds_per_tick, times_fired) + return + #undef HULK_TAILTHROW_STEPS diff --git a/code/datums/proximity_monitor/fields/timestop.dm b/code/datums/proximity_monitor/fields/timestop.dm index a3e22483c7a..91e13c79142 100644 --- a/code/datums/proximity_monitor/fields/timestop.dm +++ b/code/datums/proximity_monitor/fields/timestop.dm @@ -214,7 +214,7 @@ frozen_mobs += victim victim.Stun(20, ignore_canstun = TRUE) victim.add_traits(list(TRAIT_MUTE, TRAIT_EMOTEMUTE), TIMESTOP_TRAIT) - SSmove_manager.stop_looping(victim) //stops them mid pathing even if they're stunimmune //This is really dumb + DSmove_manager.stop_looping(victim) //stops them mid pathing even if they're stunimmune //This is really dumb if(isanimal(victim)) var/mob/living/simple_animal/animal_victim = victim animal_victim.toggle_ai(AI_OFF) diff --git a/code/datums/shuttles/pirate.dm b/code/datums/shuttles/pirate.dm index c6f94b5684b..99f866d23fc 100644 --- a/code/datums/shuttles/pirate.dm +++ b/code/datums/shuttles/pirate.dm @@ -29,3 +29,7 @@ /datum/map_template/shuttle/pirate/geode suffix = "geode" name = "pirate ship (Lustrous Geode)" + +/datum/map_template/shuttle/pirate/medieval + suffix = "medieval" + name = "pirate ship (Siege Pod)" diff --git a/code/datums/skills/athletics.dm b/code/datums/skills/athletics.dm new file mode 100644 index 00000000000..2ef336e5ba9 --- /dev/null +++ b/code/datums/skills/athletics.dm @@ -0,0 +1,27 @@ +/datum/skill/athletics + name = "Athletics" + title = "Athlete" + desc = "Twinkle twinkle little star, hit the gym and lift the bar." + // The skill value modifier effects the max duration that is possible for /datum/status_effect/exercised; The rands modifier determines block probability and crit probability while boxing against boxers + modifiers = list( + SKILL_VALUE_MODIFIER = list( + 1 MINUTES, + 1.5 MINUTES, + 2 MINUTES, + 2.5 MINUTES, + 3 MINUTES, + 3.5 MINUTES, + 5 MINUTES + ), + SKILL_RANDS_MODIFIER = list( + 0, + 5, + 10, + 15, + 20, + 30, + 50 + ) + ) + + skill_item_path = /obj/item/clothing/gloves/boxing/golden diff --git a/code/datums/skills/fitness.dm b/code/datums/skills/fitness.dm deleted file mode 100644 index 945b21710c2..00000000000 --- a/code/datums/skills/fitness.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/skill/fitness - name = "Fitness" - title = "Powerlifter" - desc = "Twinkle twinkle little star, hit the gym and lift the bar." - /// The skill value modifier effects the max duration that is possible for /datum/status_effect/exercised - modifiers = list(SKILL_VALUE_MODIFIER = list(1 MINUTES, 1.5 MINUTES, 2 MINUTES, 2.5 MINUTES, 3 MINUTES, 3.5 MINUTES, 5 MINUTES)) - /// How much bigger your mob becomes per level (these effects don't stack together) - var/static/size_boost = list(0, 1/16, 1/8, 3/16, 2/8, 3/8, 4/8) - // skill_item_path - your mob sprite gets bigger to showoff so we don't get a special item - -/* SKYRAT EDIT REMOVAL START - NO SIZE INCREASE -/datum/skill/fitness/level_gained(datum/mind/mind, new_level, old_level, silent) - . = ..() - var/old_gym_size = RESIZE_DEFAULT_SIZE + size_boost[old_level] - var/new_gym_size = RESIZE_DEFAULT_SIZE + size_boost[new_level] - - mind.current.update_transform(new_gym_size / old_gym_size) - -/datum/skill/fitness/level_lost(datum/mind/mind, new_level, old_level, silent) - . = ..() - var/old_gym_size = RESIZE_DEFAULT_SIZE + size_boost[old_level] - var/new_gym_size = RESIZE_DEFAULT_SIZE + size_boost[new_level] - - mind.current.update_transform(new_gym_size / old_gym_size) -SKYRAT EDIT REMOVAL END */ diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 39d5c3a3754..7c9a4e1cc1a 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -195,6 +195,9 @@ if(HAS_TRAIT(new_owner, TRAIT_HULK)) modifier += 0.5 + if(HAS_TRAIT(new_owner, TRAIT_STIMMED)) // Naturally produces stimulants to help get you PUMPED + modifier += 1 + if(HAS_TRAIT(new_owner, TRAIT_FAT)) // less xp until you get into shape modifier -= 0.5 @@ -209,10 +212,10 @@ if(new_owner.reagents.has_reagent(workout_reagent)) food_boost += supplementary_reagents_bonus[workout_reagent] - var/skill_level_boost = (new_owner.mind.get_skill_level(/datum/skill/fitness) - 1) * 2 SECONDS + var/skill_level_boost = (new_owner.mind.get_skill_level(/datum/skill/athletics) - 1) * 2 SECONDS bonus_time = (bonus_time + food_boost + skill_level_boost) * modifier - var/exhaustion_limit = new_owner.mind.get_skill_modifier(/datum/skill/fitness, SKILL_VALUE_MODIFIER) + world.time + var/exhaustion_limit = new_owner.mind.get_skill_modifier(/datum/skill/athletics, SKILL_VALUE_MODIFIER) + world.time if(duration + bonus_time >= exhaustion_limit) duration = exhaustion_limit to_chat(new_owner, span_userdanger("Your muscles are exhausted! Might be a good idea to sleep...")) @@ -228,10 +231,10 @@ /datum/status_effect/exercised/refresh(mob/living/new_owner, bonus_time) duration += workout_duration(new_owner, bonus_time) new_owner.clear_mood_event("exercise") // we need to reset the old mood event in case our fitness skill changes - new_owner.add_mood_event("exercise", /datum/mood_event/exercise, new_owner.mind.get_skill_level(/datum/skill/fitness)) + new_owner.add_mood_event("exercise", /datum/mood_event/exercise, new_owner.mind.get_skill_level(/datum/skill/athletics)) /datum/status_effect/exercised/on_apply() - owner.add_mood_event("exercise", /datum/mood_event/exercise, owner.mind.get_skill_level(/datum/skill/fitness)) + owner.add_mood_event("exercise", /datum/mood_event/exercise, owner.mind.get_skill_level(/datum/skill/athletics)) return ..() /datum/status_effect/exercised/on_remove() diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index 362a9eee23b..feabf36312b 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -224,7 +224,7 @@ var/datum/status_effect/exercised/exercised = carbon_owner.has_status_effect(/datum/status_effect/exercised) if(exercised && carbon_owner.mind) // the better you sleep, the more xp you gain - carbon_owner.mind.adjust_experience(/datum/skill/fitness, seconds_between_ticks * sleep_quality * SLEEP_QUALITY_WORKOUT_MULTIPLER) + carbon_owner.mind.adjust_experience(/datum/skill/athletics, seconds_between_ticks * sleep_quality * SLEEP_QUALITY_WORKOUT_MULTIPLER) carbon_owner.adjust_timed_status_effect(-1 * seconds_between_ticks * sleep_quality * SLEEP_QUALITY_WORKOUT_MULTIPLER, /datum/status_effect/exercised) if(prob(2)) to_chat(carbon_owner, span_notice("You feel your fitness improving!")) diff --git a/code/datums/systems/_system.dm b/code/datums/systems/_system.dm new file mode 100644 index 00000000000..fe3271048ab --- /dev/null +++ b/code/datums/systems/_system.dm @@ -0,0 +1,16 @@ +#define NEW_DS_GLOBAL(varname) if(varname != src){if(istype(varname)){qdel(varname);}varname = src;} + +#define DATASYSTEM_DEF(X) GLOBAL_REAL(DS##X, /datum/system/##X);\ +/datum/system/##X/New(){\ + NEW_DS_GLOBAL(DS##X);\ +}\ +/datum/system/##X + + +/** + * Global systems which are distinct from subsystems in that they do not process by the MC. + * Data systems or "DS" are used to store round information and procs to interface with that data, if needed. + */ +/datum/system + /// Name of the system + var/name = "Datum System" diff --git a/code/controllers/subsystem/battle_royale.dm b/code/datums/systems/ds/battle_royale.dm similarity index 96% rename from code/controllers/subsystem/battle_royale.dm rename to code/datums/systems/ds/battle_royale.dm index 139a5aa8b49..1cdc7358a56 100644 --- a/code/controllers/subsystem/battle_royale.dm +++ b/code/datums/systems/ds/battle_royale.dm @@ -7,7 +7,7 @@ GLOBAL_LIST_INIT(battle_royale_regions, list( ), "Research Division" = list( /area/station/command/heads_quarters/rd, - /area/station/security/checkpoint/science, + /area/station/security/checkpoint/science, /area/station/science, ), "Engineering Bay" = list( @@ -24,14 +24,13 @@ GLOBAL_LIST_INIT(battle_royale_regions, list( )) /// Basically just exists to hold references to datums so that they don't GC -SUBSYSTEM_DEF(battle_royale) +DATASYSTEM_DEF(battle_royale) name = "Battle Royale" - flags = SS_NO_INIT | SS_NO_FIRE /// List of battle royale datums currently running var/list/active_battles /// Start a new battle royale using a passed list of implants -/datum/controller/subsystem/battle_royale/proc/start_battle(list/competitors) +/datum/system/battle_royale/proc/start_battle(list/competitors) var/datum/battle_royale_controller/controller = new() if (!controller.start(competitors)) return FALSE @@ -42,7 +41,7 @@ SUBSYSTEM_DEF(battle_royale) return TRUE /// Drop reference when it kills itself -/datum/controller/subsystem/battle_royale/proc/battle_ended(datum/source) +/datum/system/battle_royale/proc/battle_ended(datum/source) SIGNAL_HANDLER LAZYREMOVE(active_battles, source) if (!LAZYLEN(active_battles)) @@ -52,7 +51,7 @@ SUBSYSTEM_DEF(battle_royale) /// Datum which controls the conflict /datum/battle_royale_controller /// Where is our battle taking place? - var/chosen_area + var/chosen_area /// Is the battle currently in progress? var/battle_running = TRUE /// Should we let everyone know that someone has died? diff --git a/code/controllers/subsystem/communications.dm b/code/datums/systems/ds/communications.dm similarity index 87% rename from code/controllers/subsystem/communications.dm rename to code/datums/systems/ds/communications.dm index 3ad52bbf150..7c9cee61509 100644 --- a/code/controllers/subsystem/communications.dm +++ b/code/datums/systems/ds/communications.dm @@ -2,9 +2,8 @@ #define COMMUNICATION_COOLDOWN_AI (30 SECONDS) #define COMMUNICATION_COOLDOWN_MEETING (5 MINUTES) -SUBSYSTEM_DEF(communications) +DATASYSTEM_DEF(communications) name = "Communications" - flags = SS_NO_INIT | SS_NO_FIRE COOLDOWN_DECLARE(silicon_message_cooldown) COOLDOWN_DECLARE(nonsilicon_message_cooldown) @@ -21,7 +20,7 @@ SUBSYSTEM_DEF(communications) /// The location where the special xenomorph egg was planted var/area/captivity_area -/datum/controller/subsystem/communications/proc/can_announce(mob/living/user, is_silicon) +/datum/system/communications/proc/can_announce(mob/living/user, is_silicon) if(is_silicon && COOLDOWN_FINISHED(src, silicon_message_cooldown)) return TRUE else if(!is_silicon && COOLDOWN_FINISHED(src, nonsilicon_message_cooldown)) @@ -29,7 +28,7 @@ SUBSYSTEM_DEF(communications) else return FALSE -/datum/controller/subsystem/communications/proc/make_announcement(mob/living/user, is_silicon, input, syndicate, list/players) +/datum/system/communications/proc/make_announcement(mob/living/user, is_silicon, input, syndicate, list/players) if(!can_announce(user, is_silicon)) return FALSE if(is_silicon) @@ -45,7 +44,7 @@ SUBSYSTEM_DEF(communications) user.log_talk(input, LOG_SAY, tag="priority announcement") message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.") -/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE) +/datum/system/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE) for(var/obj/machinery/computer/communications/C in GLOB.shuttle_caller_list) if(!(C.machine_stat & (BROKEN|NOPOWER)) && is_station_level(C.z)) if(unique) diff --git a/code/controllers/subsystem/materials.dm b/code/datums/systems/ds/materials.dm similarity index 92% rename from code/controllers/subsystem/materials.dm rename to code/datums/systems/ds/materials.dm index 25efd8695dc..527c1a3d642 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/datums/systems/ds/materials.dm @@ -1,13 +1,12 @@ /*! How material datums work -Materials are now instanced datums, with an associative list of them being kept in SSmaterials. We only instance the materials once and then re-use these instances for everything. +Materials are now instanced datums, with an associative list of them being kept in DSmaterials. We only instance the materials once and then re-use these instances for everything. These materials call on_applied() on whatever item they are applied to, common effects are adding components, changing color and changing description. This allows us to differentiate items based on the material they are made out of.area */ -SUBSYSTEM_DEF(materials) +DATASYSTEM_DEF(materials) name = "Materials" - flags = SS_NO_FIRE | SS_NO_INIT ///Dictionary of material.id || material ref var/list/materials ///Dictionary of type || list of material refs @@ -37,7 +36,7 @@ SUBSYSTEM_DEF(materials) var/list/datum/dimension_theme/dimensional_themes ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) -/datum/controller/subsystem/materials/proc/InitializeMaterials() +/datum/system/materials/proc/InitializeMaterials() materials = list() materials_by_type = list() materialids_by_type = list() @@ -58,7 +57,7 @@ SUBSYSTEM_DEF(materials) * - [arguments][/list]: The arguments to use to create the material datum * - The first element is the type of material to initialize. */ -/datum/controller/subsystem/materials/proc/InitializeMaterial(list/arguments) +/datum/system/materials/proc/InitializeMaterial(list/arguments) var/datum/material/mat_type = arguments[1] if(initial(mat_type.init_flags) & MATERIAL_INIT_BESPOKE) arguments[1] = GetIdFromArguments(arguments) @@ -90,13 +89,13 @@ SUBSYSTEM_DEF(materials) * - If the material type is bespoke a text ID is generated from the arguments list and used to load a material datum from the cache. * - The following elements are used to generate bespoke IDs */ -/datum/controller/subsystem/materials/proc/_GetMaterialRef(list/arguments) +/datum/system/materials/proc/_GetMaterialRef(list/arguments) if(!materials) InitializeMaterials() var/datum/material/key = arguments[1] if(istype(key)) - return key // We are assuming here that the only thing allowed to create material datums is [/datum/controller/subsystem/materials/proc/InitializeMaterial] + return key // We are assuming here that the only thing allowed to create material datums is [/datum/system/materials/proc/InitializeMaterial] if(istext(key)) // Handle text id . = materials[key] @@ -124,7 +123,7 @@ SUBSYSTEM_DEF(materials) * Named arguments can appear in any order and we need them to appear after ordered arguments * We assume that no one will pass in a named argument with a value of null **/ -/datum/controller/subsystem/materials/proc/GetIdFromArguments(list/arguments) +/datum/system/materials/proc/GetIdFromArguments(list/arguments) var/datum/material/mattype = arguments[1] var/list/fullid = list("[initial(mattype.id) || mattype]") var/list/named_arguments = list() @@ -150,7 +149,7 @@ SUBSYSTEM_DEF(materials) /// Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters. -/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier) +/datum/system/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier) if(!LAZYLEN(materials_declaration)) return null // If we get a null we pass it right back, we don't want to generate stack traces just because something is clearing out its materials list. diff --git a/code/controllers/subsystem/movement/move_handler.dm b/code/datums/systems/ds/move_handler.dm similarity index 91% rename from code/controllers/subsystem/movement/move_handler.dm rename to code/datums/systems/ds/move_handler.dm index fcc5c1c6504..dc3458627ef 100644 --- a/code/controllers/subsystem/movement/move_handler.dm +++ b/code/datums/systems/ds/move_handler.dm @@ -17,16 +17,14 @@ * * You can find the logic for this control in this file * - * Specifics of how different loops operate can be found in the movement_types.dm file, alongside the [add to loop][/datum/controller/subsystem/move_manager/proc/add_to_loop] helper procs that use them + * Specifics of how different loops operate can be found in the movement_types.dm file, alongside the [add to loop][/datum/system/move_manager/proc/add_to_loop] helper procs that use them * **/ -SUBSYSTEM_DEF(move_manager) +DATASYSTEM_DEF(move_manager) name = "Movement Handler" - flags = SS_NO_INIT | SS_NO_FIRE - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME ///Adds a movable thing to a movement subsystem. Returns TRUE if it all worked, FALSE if it failed somehow -/datum/controller/subsystem/move_manager/proc/add_to_loop(atom/movable/thing_to_add, datum/controller/subsystem/movement/subsystem = SSmovement, datum/move_loop/loop_type, priority = MOVEMENT_DEFAULT_PRIORITY, flags, datum/extra_info) +/datum/system/move_manager/proc/add_to_loop(atom/movable/thing_to_add, datum/controller/subsystem/movement/subsystem = SSmovement, datum/move_loop/loop_type, priority = MOVEMENT_DEFAULT_PRIORITY, flags, datum/extra_info) var/datum/movement_packet/our_data = thing_to_add.move_packet if(!our_data) our_data = new(thing_to_add) @@ -35,7 +33,7 @@ SUBSYSTEM_DEF(move_manager) return our_data.add_loop(arglist(arguments)) ///Returns the subsystem's loop if we're processing on it, null otherwise -/datum/controller/subsystem/move_manager/proc/processing_on(atom/movable/packet_owner, datum/controller/subsystem/movement/subsystem) +/datum/system/move_manager/proc/processing_on(atom/movable/packet_owner, datum/controller/subsystem/movement/subsystem) var/datum/movement_packet/packet = packet_owner.move_packet if(!packet) return diff --git a/code/datums/systems/manager.dm b/code/datums/systems/manager.dm new file mode 100644 index 00000000000..0d5fdb8b839 --- /dev/null +++ b/code/datums/systems/manager.dm @@ -0,0 +1,14 @@ +// See initialization order in /code/game/world.dm +GLOBAL_REAL(SysMgr, /datum/system_manager) + + +/** + * Initializes all data systems and keeps track of them. + */ +/datum/system_manager + /// List of managed data systems, post initialization. + var/list/datum/system/managed = list() + + +/datum/system_manager/New() + init_subtypes(/datum/system, managed) diff --git a/code/game/atom/atom_materials.dm b/code/game/atom/atom_materials.dm index 345a8486dd6..deb27140257 100644 --- a/code/game/atom/atom_materials.dm +++ b/code/game/atom/atom_materials.dm @@ -23,7 +23,7 @@ var/datum/material/custom_material = GET_MATERIAL_REF(current_material) custom_material.on_applied(src, OPTIMAL_COST(materials[current_material] * multiplier * material_modifier), material_flags) - custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) + custom_materials = DSmaterials.FindOrCreateMaterialCombo(materials, multiplier) /** * Returns the material composition of the atom. diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 1bdcba84967..02dfa624d35 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -4,8 +4,8 @@ icon = 'icons/obj/machines/lathes.dmi' icon_state = "autolathe" density = TRUE - //Energy cost per full stack of sheets worth of materials used. Material insertion is 40% of this. - active_power_usage = 25 * BASE_MACHINE_ACTIVE_CONSUMPTION + ///Energy cost per full stack of sheets worth of materials used. Material insertion is 40% of this. + active_power_usage = 0.025 * STANDARD_CELL_RATE circuit = /obj/item/circuitboard/machine/autolathe layer = BELOW_OBJ_LAYER processing_flags = NONE @@ -32,7 +32,7 @@ /obj/machinery/autolathe/Initialize(mapload) materials = AddComponent( \ /datum/component/material_container, \ - SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ + DSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ 0, \ MATCONTAINER_EXAMINE, \ container_signals = list(COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/autolathe, AfterMaterialInsert)) \ @@ -252,7 +252,7 @@ var/amount_needed = design.materials[material] if(istext(material)) // category var/list/choices = list() - for(var/datum/material/valid_candidate as anything in SSmaterials.materials_by_category[material]) + for(var/datum/material/valid_candidate as anything in DSmaterials.materials_by_category[material]) if(materials.get_material_amount(valid_candidate) < amount_needed) continue choices[valid_candidate.name] = valid_candidate diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index ae3ae36e51b..c2c1fcaa025 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -7,7 +7,7 @@ circuit = /obj/item/circuitboard/machine/cell_charger pass_flags = PASSTABLE var/obj/item/stock_parts/cell/charging = null - var/charge_rate = 250 KILO WATTS + var/charge_rate = 0.25 * STANDARD_CELL_RATE /* OVERWRITTEN IN modular_skyrat\modules\aesthetics\cells\cell.dm /obj/machinery/cell_charger/update_overlays() @@ -133,7 +133,7 @@ /obj/machinery/cell_charger/RefreshParts() . = ..() - charge_rate = 250 KILO WATTS + charge_rate = 0.25 * STANDARD_CELL_RATE for(var/datum/stock_part/capacitor/capacitor in component_parts) charge_rate *= capacitor.tier @@ -147,7 +147,8 @@ if(!main_draw) return - use_energy(main_draw * 0.01) //use a small bit for the charger itself, but power usage scales up with the part tier + //use a small bit for the charger itself, but power usage scales up with the part tier + use_energy(main_draw * 0.01) charge_cell(main_draw, charging, grid_only = TRUE) update_appearance() diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 1868bc3c38c..f5695dd6284 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -53,17 +53,15 @@ actions += new move_down_action(src) /obj/machinery/computer/camera_advanced/Destroy() - if(!QDELETED(current_user)) - unset_machine(current_user) - if(eyeobj) - QDEL_NULL(eyeobj) + unset_machine() + QDEL_NULL(eyeobj) QDEL_LIST(actions) current_user = null return ..() /obj/machinery/computer/camera_advanced/process() if(!can_use(current_user) || (issilicon(current_user) && !current_user.has_unlimited_silicon_privilege)) - unset_machine(current_user) + unset_machine() return PROCESS_KILL /obj/machinery/computer/camera_advanced/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) @@ -124,12 +122,12 @@ /obj/machinery/computer/camera_advanced/on_set_is_operational(old_value) if(!is_operational) - unset_machine(current_user) + unset_machine() -/obj/machinery/computer/camera_advanced/proc/unset_machine(mob/M) - if(M == current_user) - remove_eye_control(M) - end_processing() +/obj/machinery/computer/camera_advanced/proc/unset_machine() + if(!QDELETED(current_user)) + remove_eye_control(current_user) + end_processing() /obj/machinery/computer/camera_advanced/proc/can_use(mob/living/user) return can_interact(user) @@ -147,7 +145,7 @@ return if(isnull(user.client)) return - if(current_user) + if(!QDELETED(current_user)) to_chat(user, span_warning("The console is already in use!")) return var/mob/living/L = user @@ -179,7 +177,7 @@ give_eye_control(L) eyeobj.setLoc(camera_location) else - unset_machine(user) + unset_machine() else give_eye_control(L) eyeobj.setLoc(eyeobj.loc) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index caa3452626e..c71d80ccfba 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -335,7 +335,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) if (!message) return - SScommunications.soft_filtering = FALSE + DScommunications.soft_filtering = FALSE var/list/hard_filter_result = is_ic_filtered(message) if(hard_filter_result) tgui_alert(usr, "Your message contains: (\"[hard_filter_result[CHAT_FILTER_INDEX_WORD]]\"), which is not allowed on this server.") @@ -347,7 +347,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) return message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". They may be using a disallowed term for a cross-station message. Increasing delay time to reject.\n\n Message: \"[html_encode(message)]\"") log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". They may be using a disallowed term for a cross-station message. Increasing delay time to reject.\n\n Message: \"[message]\"") - SScommunications.soft_filtering = TRUE + DScommunications.soft_filtering = TRUE playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) @@ -358,13 +358,13 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) GLOB.admins, span_adminnotice( \ "CROSS-SECTOR MESSAGE (OUTGOING): [ADMIN_LOOKUPFLW(usr)] is about to send \ - the following message to [destination] (will autoapprove in [SScommunications.soft_filtering ? DisplayTimeText(EXTENDED_CROSS_SECTOR_CANCEL_TIME) : DisplayTimeText(CROSS_SECTOR_CANCEL_TIME)]): \ + the following message to [destination] (will autoapprove in [DScommunications.soft_filtering ? DisplayTimeText(EXTENDED_CROSS_SECTOR_CANCEL_TIME) : DisplayTimeText(CROSS_SECTOR_CANCEL_TIME)]): \ REJECT
\ [html_encode(message)]" \ ) ) - send_cross_comms_message_timer = addtimer(CALLBACK(src, PROC_REF(send_cross_comms_message), usr, destination, message), SScommunications.soft_filtering ? EXTENDED_CROSS_SECTOR_CANCEL_TIME : CROSS_SECTOR_CANCEL_TIME, TIMER_STOPPABLE) + send_cross_comms_message_timer = addtimer(CALLBACK(src, PROC_REF(send_cross_comms_message), usr, destination, message), DScommunications.soft_filtering ? EXTENDED_CROSS_SECTOR_CANCEL_TIME : CROSS_SECTOR_CANCEL_TIME, TIMER_STOPPABLE) COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) if ("setState") @@ -445,7 +445,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) state = STATE_MAIN playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) imprint_gps(gps_tag = "Encrypted Communications Channel") - + if ("toggleEmergencyAccess") if(emergency_access_cooldown(usr)) //if were in cooldown, dont allow the following code return @@ -552,7 +552,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) var/network_name = CONFIG_GET(string/cross_comms_network) if(network_name) payload["network"] = network_name - if(SScommunications.soft_filtering) + if(DScommunications.soft_filtering) payload["is_filtered"] = TRUE var/name_to_send = "[CONFIG_GET(string/cross_comms_name)]([station_name()])" //SKYRAT EDIT ADDITION @@ -562,7 +562,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) usr.log_talk(message, LOG_SAY, tag = "message to the other server") message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server\[s].") deadchat_broadcast(" has sent an outgoing message to the other station(s).", "[usr.real_name]", usr, message_type = DEADCHAT_ANNOUNCEMENT) - SScommunications.soft_filtering = FALSE // set it to false at the end of the proc to ensure that everything prior reads as intended + DScommunications.soft_filtering = FALSE // set it to false at the end of the proc to ensure that everything prior reads as intended /obj/machinery/computer/communications/ui_data(mob/user) var/list/data = list( @@ -727,7 +727,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) return deltimer(send_cross_comms_message_timer) - SScommunications.soft_filtering = FALSE + DScommunications.soft_filtering = FALSE send_cross_comms_message_timer = null log_admin("[key_name(usr)] has cancelled the outgoing cross-comms message.") @@ -800,7 +800,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) /obj/machinery/computer/communications/proc/make_announcement(mob/living/user) var/is_ai = HAS_SILICON_ACCESS(user) - if(!SScommunications.can_announce(user, is_ai)) + if(!DScommunications.can_announce(user, is_ai)) to_chat(user, span_alert("Intercomms recharging. Please stand by.")) return var/input = tgui_input_text(user, "Message to announce to the station crew", "Announcement") @@ -821,7 +821,7 @@ GLOBAL_VAR_INIT(cops_arrived, FALSE) ) var/list/players = get_communication_players() - SScommunications.make_announcement(user, is_ai, input, syndicate || (obj_flags & EMAGGED), players) + DScommunications.make_announcement(user, is_ai, input, syndicate || (obj_flags & EMAGGED), players) deadchat_broadcast(" made a priority announcement from [span_name("[get_area_name(usr, TRUE)]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT) /obj/machinery/computer/communications/proc/get_communication_players() diff --git a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm index 0882c9ce99a..13f350f1da1 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm @@ -107,6 +107,10 @@ item_path = /obj/item/radio/weather_monitor cost_per_order = 320 +/datum/orderable_item/mining/ventpointer + item_path = /obj/item/pinpointer/vent + cost_per_order = 1150 + /datum/orderable_item/mining/boulder_processing item_path = /obj/item/boulder_beacon desc = "A Bouldertech brand all-in-one boulder processing beacon. Each use will teleport in a component of a full boulder processing assembly line. Good for when you need to process additional boulders." diff --git a/code/game/machinery/dna_infuser/dna_infuser.dm b/code/game/machinery/dna_infuser/dna_infuser.dm index 6c239089f5d..7b5fcb501a0 100644 --- a/code/game/machinery/dna_infuser/dna_infuser.dm +++ b/code/game/machinery/dna_infuser/dna_infuser.dm @@ -64,8 +64,7 @@ balloon_alert(user, "not while it's on!") return if(occupant && infusing_from) - // Abort infusion if the occupant is invalid. - if(!is_valid_occupant(occupant, user)) + if(!occupant.can_infuse(user)) playsound(src, 'sound/machines/scanbuzz.ogg', 35, vary = TRUE) return balloon_alert(user, "starting DNA infusion...") @@ -77,92 +76,45 @@ var/mob/living/carbon/human/human_occupant = occupant infusing = TRUE visible_message(span_notice("[src] hums to life, beginning the infusion process!")) + + infusing_into = infusing_from.get_infusion_entry() var/fail_title = "" - var/fail_reason = "" - // Replace infusing_into with a [/datum/infuser_entry] - for(var/datum/infuser_entry/entry as anything in GLOB.infuser_entries) - if(entry.tier == DNA_MUTANT_UNOBTAINABLE) - continue - if(is_type_in_list(infusing_from, entry.input_obj_or_mob)) - if(entry.tier > max_tier_allowed) - fail_title = "Overcomplexity" - fail_reason = "DNA too complicated to infuse. The machine needs to infuse simpler DNA first." - infusing_into = entry - break - if(!infusing_into) - //no valid recipe, so you get a fly mutation - if(!fail_reason) - fail_title = "Unknown DNA" - fail_reason = "Unknown DNA. Consult the \"DNA infusion book\"." - infusing_into = GLOB.infuser_entries[1] + var/fail_explanation = "" + if(istype(infusing_into, /datum/infuser_entry/fly)) + fail_title = "Unknown DNA" + fail_explanation = "Unknown DNA. Consult the \"DNA infusion book\"." + if(infusing_into.tier > max_tier_allowed) + infusing_into = GLOB.infuser_entries[/datum/infuser_entry/fly] + fail_title = "Overcomplexity" + fail_explanation = "DNA too complicated to infuse. The machine needs to infuse simpler DNA first." playsound(src, 'sound/machines/blender.ogg', 50, vary = TRUE) to_chat(human_occupant, span_danger("Little needles repeatedly prick you!")) human_occupant.take_overall_damage(10) human_occupant.add_mob_memory(/datum/memory/dna_infusion, protagonist = human_occupant, deuteragonist = infusing_from, mutantlike = infusing_into.infusion_desc) Shake(duration = INFUSING_TIME) addtimer(CALLBACK(human_occupant, TYPE_PROC_REF(/mob, emote), "scream"), INFUSING_TIME - 1 SECONDS) - addtimer(CALLBACK(src, PROC_REF(end_infuse), fail_reason, fail_title), INFUSING_TIME) + addtimer(CALLBACK(src, PROC_REF(end_infuse), fail_explanation, fail_title), INFUSING_TIME) update_appearance() -/obj/machinery/dna_infuser/proc/end_infuse(fail_reason, fail_title) - if(infuse_organ(occupant)) +/obj/machinery/dna_infuser/proc/end_infuse(fail_explanation, fail_title) + var/mob/living/carbon/human/human_occupant = occupant + if(human_occupant.infuse_organ(infusing_into)) + check_tier_progression(src) to_chat(occupant, span_danger("You feel yourself becoming more... [infusing_into.infusion_desc]?")) infusing = FALSE infusing_into = null QDEL_NULL(infusing_from) playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, vary = FALSE) - if(fail_reason) + if(fail_explanation) playsound(src, 'sound/machines/printer.ogg', 100, TRUE) visible_message(span_notice("[src] prints an error report.")) var/obj/item/paper/printed_paper = new /obj/item/paper(loc) printed_paper.name = "error report - '[fail_title]'" - printed_paper.add_raw_text(fail_reason) + printed_paper.add_raw_text(fail_explanation) printed_paper.update_appearance() toggle_open() update_appearance() -/// Attempt to replace/add-to the occupant's organs with "mutated" equivalents. -/// Returns TRUE on success, FALSE on failure. -/// 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. -/obj/machinery/dna_infuser/proc/infuse_organ(mob/living/carbon/human/target) - if(!ishuman(target)) - return FALSE - var/obj/item/organ/new_organ = pick_organ(target) - if(!new_organ) - return FALSE - // Valid organ successfully picked. - new_organ = new new_organ() - new_organ.replace_into(target) - check_tier_progression(target) - return TRUE - -/// Picks a random mutated organ from the infuser entry which is also compatible with the target mob. -/// Tries to return a typepath of a valid mutant organ if all of the following criteria are true: -/// 1. Target must have a pre-existing organ in the same organ slot as the new organ; -/// - or the new organ must be external. -/// 2. Target's pre-existing organ must be organic / not robotic. -/// 3. Target must not have the same/identical organ. -/obj/machinery/dna_infuser/proc/pick_organ(mob/living/carbon/human/target) - if(!infusing_into) - return FALSE - var/list/obj/item/organ/potential_new_organs = infusing_into.output_organs.Copy() - // Remove organ typepaths from the list if they're incompatible with target. - for(var/obj/item/organ/new_organ as anything in infusing_into.output_organs) - var/obj/item/organ/old_organ = target.get_organ_slot(initial(new_organ.slot)) - if(old_organ) - if((old_organ.type != new_organ) && !IS_ROBOTIC_ORGAN(old_organ)) - continue // Old organ can be mutated! - else if(ispath(new_organ, /obj/item/organ/external)) - continue // External organ can be grown! - // Internal organ is either missing, or is non-organic. - potential_new_organs -= new_organ - // Pick a random organ from the filtered list. - if(length(potential_new_organs)) - return pick(potential_new_organs) - return FALSE - /// checks to see if the machine should progress a new tier. /obj/machinery/dna_infuser/proc/check_tier_progression(mob/living/carbon/human/target) if( @@ -254,19 +206,6 @@ infusing_from = target infusing_from.forceMove(src) -/// Verify that the occupant/target is organic, and has mutable DNA. -/obj/machinery/dna_infuser/proc/is_valid_occupant(mob/living/carbon/human/human_target, mob/user) - // Invalid: DNA is too damaged to mutate anymore / has TRAIT_BADDNA. - if(HAS_TRAIT(human_target, TRAIT_BADDNA)) - balloon_alert(user, "dna is corrupted!") - return FALSE - // Invalid: Occupant isn't Human, isn't organic, lacks DNA / has TRAIT_GENELESS. - if(!ishuman(human_target) || !human_target.can_mutate()) - balloon_alert(user, "dna is missing!") - return FALSE - // Valid: Occupant is an organic Human who has undamaged and mutable DNA. - return TRUE - /// Verify that the given infusion source/mob is a dead creature. /obj/machinery/dna_infuser/proc/is_valid_infusion(atom/movable/target, mob/user) if(user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_UI_BLOCKED) || !Adjacent(user) || !user.Adjacent(target) || !ISADVANCEDTOOLUSER(user)) @@ -291,10 +230,10 @@ /obj/machinery/dna_infuser/click_alt(mob/user) if(infusing) balloon_alert(user, "not while it's on!") - return CLICK_ACTION_BLOCKING + return if(!infusing_from) balloon_alert(user, "no sample to eject!") - return CLICK_ACTION_BLOCKING + return balloon_alert(user, "ejected sample") infusing_from.forceMove(get_turf(src)) infusing_from = null diff --git a/code/game/machinery/dna_infuser/dna_infusion.dm b/code/game/machinery/dna_infuser/dna_infusion.dm new file mode 100644 index 00000000000..c902240404c --- /dev/null +++ b/code/game/machinery/dna_infuser/dna_infusion.dm @@ -0,0 +1,75 @@ + +///returns a boolean whether a machine occupant can be infused +/atom/movable/proc/can_infuse(mob/feedback_target) + if(feedback_target) + balloon_alert(feedback_target, "no dna!") + return FALSE + +/mob/living/can_infuse(mob/feedback_target) + if(feedback_target) + balloon_alert(feedback_target, "dna too simple!") + return FALSE + +/mob/living/carbon/human/can_infuse(mob/feedback_target) + // Checked by can_mutate but explicit feedback for this issue is good + if(HAS_TRAIT(src, TRAIT_BADDNA)) + if(feedback_target) + balloon_alert(feedback_target, "dna is corrupted!") + return FALSE + if(!can_mutate()) + if(feedback_target) + balloon_alert(feedback_target, "dna is missing!") + return FALSE + return TRUE + +///returns /datum/infuser_entry that matches an item being used for infusion, returns a fly mutation on failure +/atom/movable/proc/get_infusion_entry() as /datum/infuser_entry + var/datum/infuser_entry/found + for(var/datum/infuser_entry/entry as anything in flatten_list(GLOB.infuser_entries)) + if(entry.tier == DNA_MUTANT_UNOBTAINABLE) + continue + if(is_type_in_list(src, entry.input_obj_or_mob)) + found = entry + break + if(!found) + found = GLOB.infuser_entries[/datum/infuser_entry/fly] + return found + +/// Attempt to replace/add-to the occupant's organs with "mutated" equivalents. +/// Returns TRUE on success, FALSE on failure. +/// 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) + if(!new_organ) + return FALSE + // Valid organ successfully picked. + new_organ = new new_organ() + new_organ.replace_into(src) + return TRUE + +/// Picks a random mutated organ from the given infuser entry which is also compatible with this human. +/// Tries to return a typepath of a valid mutant organ if all of the following criteria are true: +/// 1. Target must have a pre-existing organ in the same organ slot as the new organ; +/// - or the new organ must be external. +/// 2. Target's pre-existing organ must be organic / not robotic. +/// 3. Target must not have the same/identical organ. +/mob/living/carbon/human/proc/pick_infusion_organ(datum/infuser_entry/entry) + if(!entry) + return FALSE + var/list/obj/item/organ/potential_new_organs = entry.output_organs.Copy() + // Remove organ typepaths from the list if they're incompatible with target. + for(var/obj/item/organ/new_organ as anything in entry.output_organs) + var/obj/item/organ/old_organ = get_organ_slot(initial(new_organ.slot)) + if(old_organ) + if((old_organ.type != new_organ) && !IS_ROBOTIC_ORGAN(old_organ)) + continue // Old organ can be mutated! + else if(ispath(new_organ, /obj/item/organ/external)) + continue // External organ can be grown! + // Internal organ is either missing, or is non-organic. + potential_new_organs -= new_organ + // Pick a random organ from the filtered list. + if(length(potential_new_organs)) + return pick(potential_new_organs) + return FALSE diff --git a/code/game/machinery/dna_infuser/infuser_book.dm b/code/game/machinery/dna_infuser/infuser_book.dm index 75632178cca..416ed038d64 100644 --- a/code/game/machinery/dna_infuser/infuser_book.dm +++ b/code/game/machinery/dna_infuser/infuser_book.dm @@ -29,7 +29,7 @@ var/list/data = list() // Collect all info from each intry. var/list/entry_data = list() - for(var/datum/infuser_entry/entry as anything in GLOB.infuser_entries) + for(var/datum/infuser_entry/entry as anything in flatten_list(GLOB.infuser_entries)) if(entry.tier == DNA_MUTANT_UNOBTAINABLE) continue var/list/individual_entry_data = list() diff --git a/code/game/machinery/dna_infuser/infuser_entry.dm b/code/game/machinery/dna_infuser/infuser_entry.dm index dfcdfbbe08a..8b0bcfb3f79 100644 --- a/code/game/machinery/dna_infuser/infuser_entry.dm +++ b/code/game/machinery/dna_infuser/infuser_entry.dm @@ -4,17 +4,10 @@ GLOBAL_LIST_INIT(infuser_entries, prepare_infuser_entries()) /// Global proc that sets up each [/datum/infuser_entry] sub-type as singleton instances in a list, and returns it. /proc/prepare_infuser_entries() var/list/entries = list() - // Regardless of names, we want the fly/failed mutant case to show first. - var/prepended for(var/datum/infuser_entry/entry_type as anything in subtypesof(/datum/infuser_entry)) var/datum/infuser_entry/entry = new entry_type() - if(entry.type == /datum/infuser_entry/fly) - prepended = entry - continue - entries += entry - var/list/sorted = sort_names(entries) - sorted.Insert(1, prepended) - return sorted + entries[entry_type] = entry + return entries /datum/infuser_entry //-- Vars for DNA Infusion Book --// diff --git a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm index afbb8404060..f44de87e92e 100644 --- a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm @@ -27,7 +27,7 @@ /obj/item/organ/internal/lungs/carp/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "neck has odd gills.", BODY_ZONE_HEAD) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their neck has odd gills.", BODY_ZONE_HEAD) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) ADD_TRAIT(src, TRAIT_SPACEBREATHING, REF(src)) @@ -45,7 +45,7 @@ /obj/item/organ/internal/tongue/carp/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "teeth are big and sharp.", BODY_ZONE_PRECISE_MOUTH) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their teeth are big and sharp.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) /obj/item/organ/internal/tongue/carp/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags) @@ -113,7 +113,7 @@ /obj/item/organ/internal/brain/carp/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) - AddElement(/datum/element/noticable_organ, "seem%PRONOUN_S unable to stay still.") + AddElement(/datum/element/noticable_organ, "%PRONOUN_They seem%PRONOUN_S unable to stay still.") /obj/item/organ/internal/brain/carp/on_mob_insert(mob/living/carbon/brain_owner) . = ..() @@ -151,7 +151,7 @@ /obj/item/organ/internal/heart/carp/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "skin has small patches of scales growing on it.", BODY_ZONE_CHEST) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their skin has small patches of scales growing on it.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) #undef CARP_ORGAN_COLOR diff --git a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm index f9ccf16812b..ac3dae39b70 100644 --- a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm @@ -31,7 +31,7 @@ /obj/item/organ/internal/eyes/night_vision/goliath/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "eyes are blood red and stone-like.", BODY_ZONE_PRECISE_EYES) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their eyes are blood red and stone-like.", BODY_ZONE_PRECISE_EYES) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) ///goliath lungs! You can breathe lavaland air mix but can't breath pure O2 from a tank anymore. @@ -46,7 +46,7 @@ /obj/item/organ/internal/lungs/lavaland/goliath/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "back is covered in small tendrils.", BODY_ZONE_CHEST) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their back is covered in small tendrils.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) ///goliath brain. you can't use gloves but one of your arms becomes a tendril hammer that can be used to mine! @@ -63,7 +63,7 @@ /obj/item/organ/internal/brain/goliath/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "arm is just a mass of plate and tendrils.", BODY_ZONE_CHEST) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their arm is just a mass of plate and tendrils.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) /obj/item/organ/internal/brain/goliath/on_mob_insert(mob/living/carbon/brain_owner) @@ -170,7 +170,7 @@ /obj/item/organ/internal/heart/goliath/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "skin has visible hard plates growing from within.", BODY_ZONE_CHEST) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their skin has visible hard plates growing from within.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) AddElement(/datum/element/update_icon_blocker) diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm index 96e41a57789..a36ebc1d3c3 100644 --- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm @@ -31,7 +31,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... /obj/item/organ/internal/heart/gondola/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) - AddElement(/datum/element/noticable_organ, "radiate%PRONOUN_S an aura of serenity.") + AddElement(/datum/element/noticable_organ, "%PRONOUN_They radiate%PRONOUN_S an aura of serenity.") /obj/item/organ/internal/heart/gondola/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() @@ -60,7 +60,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... /obj/item/organ/internal/tongue/gondola/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "mouth is permanently affixed into a relaxed smile.", BODY_ZONE_PRECISE_MOUTH) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their mouth is permanently affixed into a relaxed smile.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) /obj/item/organ/internal/tongue/gondola/Insert(mob/living/carbon/tongue_owner, special, movement_flags) @@ -83,8 +83,8 @@ Fluoride Stare: After someone says 5 words, blah blah blah... /obj/item/organ/internal/liver/gondola/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) - AddElement(/datum/element/noticable_organ, "left arm has small needles breaching the skin all over it.", BODY_ZONE_L_ARM) - AddElement(/datum/element/noticable_organ, "right arm has small needles breaching the skin all over it.", BODY_ZONE_R_ARM) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their left arm has small needles breaching the skin all over it.", BODY_ZONE_L_ARM) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their right arm has small needles breaching the skin all over it.", BODY_ZONE_R_ARM) /obj/item/organ/internal/liver/gondola/Insert(mob/living/carbon/liver_owner, special, movement_flags) . = ..() diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index f19f3d725c7..56b147ffbee 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -29,7 +29,7 @@ /obj/item/organ/internal/eyes/night_vision/rat/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "eyes have deep, shifty black pupils, surrounded by a sickening yellow sclera.", BODY_ZONE_PRECISE_EYES) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their eyes have deep, shifty black pupils, surrounded by a sickening yellow sclera.", BODY_ZONE_PRECISE_EYES) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) ///increases hunger, disgust recovers quicker, expands what is defined as "food" @@ -47,7 +47,7 @@ /obj/item/organ/internal/stomach/rat/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) - AddElement(/datum/element/noticable_organ, "mouth is drooling excessively.", BODY_ZONE_PRECISE_MOUTH) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their mouth is drooling excessively.", BODY_ZONE_PRECISE_MOUTH) /// makes you smaller, walk over tables, and take 1.5x damage /obj/item/organ/internal/heart/rat @@ -61,7 +61,7 @@ /obj/item/organ/internal/heart/rat/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) - AddElement(/datum/element/noticable_organ, "hunch%PRONOUN_ES over unnaturally!") + AddElement(/datum/element/noticable_organ, "%PRONOUN_They hunch%PRONOUN_ES over unnaturally!") /obj/item/organ/internal/heart/rat/on_mob_insert(mob/living/carbon/receiver) . = ..() @@ -98,7 +98,7 @@ /obj/item/organ/internal/tongue/rat/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "teeth are oddly shaped and yellowing.", BODY_ZONE_PRECISE_MOUTH) + AddElement(/datum/element/noticable_organ, "%PRONOUN_Their teeth are oddly shaped and yellowing.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) /obj/item/organ/internal/tongue/rat/modify_speech(datum/source, list/speech_args) diff --git a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm index 0644bca0354..11880a50cb2 100644 --- a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm @@ -63,7 +63,7 @@ /obj/item/organ/internal/heart/roach/Initialize(mapload) . = ..() - AddElement(/datum/element/noticable_organ, "has hardened, somewhat translucent skin.") + AddElement(/datum/element/noticable_organ, "%PRONOUN_They %PRONOUN_have hardened, somewhat translucent skin.") AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach) roach_shell = new() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 437acc60cdf..661e9035f01 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -98,6 +98,7 @@ smoothing_groups = SMOOTH_GROUP_AIRLOCK interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_OPEN + interaction_flags_click = ALLOW_SILICON_REACH blocks_emissive = EMISSIVE_BLOCK_NONE // Custom emissive blocker. We don't want the normal behavior. ///The type of door frame to drop during deconstruction diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index cc084bea23c..13d3b8714be 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -884,7 +884,7 @@ return if(istype(attacking_object, /obj/item/electroadaptive_pseudocircuit)) var/obj/item/electroadaptive_pseudocircuit/raspberrypi = attacking_object - if(!raspberrypi.adapt_circuit(user, circuit_cost = DEFAULT_STEP_TIME * 0.5 KILO JOULES)) + if(!raspberrypi.adapt_circuit(user, circuit_cost = DEFAULT_STEP_TIME * 0.0005 * STANDARD_CELL_CHARGE)) return user.visible_message(span_notice("[user] fabricates a circuit and places it into [src]."), \ span_notice("You adapt a firelock circuit and slot it into the assembly.")) diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 21494d17b99..c89260f7ceb 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -406,7 +406,7 @@ else if(istype(tool, /obj/item/electroadaptive_pseudocircuit)) var/obj/item/electroadaptive_pseudocircuit/pseudoc = tool - if(!pseudoc.adapt_circuit(user, circuit_cost = 15 KILO JOULES)) + if(!pseudoc.adapt_circuit(user, circuit_cost = 0.015 * STANDARD_CELL_CHARGE)) return user.visible_message(span_notice("[user] fabricates a circuit and places it into [src]."), \ span_notice("You adapt a fire alarm circuit and slot it into the assembly.")) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 273538b834b..d2041f80659 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -47,6 +47,7 @@ Possible to do for anyone motivated enough: armor_type = /datum/armor/machinery_holopad circuit = /obj/item/circuitboard/machine/holopad interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_IGNORE_MOBILITY + interaction_flags_click = ALLOW_SILICON_REACH // Blue, dim light light_power = 0.8 light_color = LIGHT_COLOR_BLUE diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 06b1b977847..ffbecf91180 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -910,6 +910,7 @@ DEFINE_BITFIELD(turret_flags, list( density = FALSE req_access = list(ACCESS_AI_UPLOAD) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + interaction_flags_click = ALLOW_SILICON_REACH /// Variable dictating if linked turrets are active and will shoot targets var/enabled = TRUE /// Variable dictating if linked turrets will shoot lethal projectiles diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index d067c3e8cbb..287fef5057d 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -178,7 +178,7 @@ if(!occupant) return - if(!use_energy(active_power_usage * seconds_per_tick)) + if(!use_energy(active_power_usage * seconds_per_tick, force = FALSE)) return SEND_SIGNAL(occupant, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, charge_cell, seconds_per_tick, repairs, sendmats) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 28aae488866..9df7d584f42 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -21,7 +21,7 @@ /obj/machinery/recycler/Initialize(mapload) materials = AddComponent( /datum/component/material_container, \ - SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_NO_INSERT \ ) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index d95668975f5..a5e301c2168 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -1,3 +1,4 @@ + // SUIT STORAGE UNIT ///////////////// /obj/machinery/suit_storage_unit name = "suit storage unit" @@ -55,9 +56,9 @@ /// How long it takes to break out of the SSU. var/breakout_time = 30 SECONDS /// Power contributed by this machine to charge the mod suits cell without any capacitors - var/base_charge_rate = 200 KILO WATTS + var/base_charge_rate = 0.2 * STANDARD_CELL_RATE /// Final charge rate which is base_charge_rate + contribution by capacitors - var/final_charge_rate = 250 KILO WATTS + var/final_charge_rate = 0.25 * STANDARD_CELL_RATE /// is the card reader installed in this machine var/card_reader_installed = FALSE /// physical reference of the players id card to check for PERSONAL access level @@ -287,7 +288,7 @@ . = ..() for(var/datum/stock_part/capacitor/capacitor in component_parts) - final_charge_rate = base_charge_rate + (capacitor.tier * 50 KILO WATTS) + final_charge_rate = base_charge_rate + (capacitor.tier * 0.05 * STANDARD_CELL_RATE) set_access() diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 693668e9e89..154b03e0f98 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -606,7 +606,7 @@ var/datum/radial_menu_choice/null_choice = new null_choice.name = DIMENSION_CHOICE_RANDOM choosable_dimensions[DIMENSION_CHOICE_RANDOM] = null_choice - for(var/datum/dimension_theme/theme as anything in SSmaterials.dimensional_themes) + for(var/datum/dimension_theme/theme as anything in DSmaterials.dimensional_themes) var/datum/radial_menu_choice/theme_choice = new theme_choice.image = image(initial(theme.icon), initial(theme.icon_state)) theme_choice.name = initial(theme.name) @@ -628,14 +628,14 @@ /obj/item/bombcore/dimensional/detonate() var/list/affected_turfs = circle_range_turfs(src, range_heavy) - var/theme_count = length(SSmaterials.dimensional_themes) + var/theme_count = length(DSmaterials.dimensional_themes) var/num_affected = 0 for(var/turf/affected as anything in affected_turfs) var/datum/dimension_theme/theme_to_use if(isnull(chosen_theme)) - theme_to_use = SSmaterials.dimensional_themes[SSmaterials.dimensional_themes[rand(1, theme_count)]] + theme_to_use = DSmaterials.dimensional_themes[DSmaterials.dimensional_themes[rand(1, theme_count)]] else - theme_to_use = SSmaterials.dimensional_themes[chosen_theme] + theme_to_use = DSmaterials.dimensional_themes[chosen_theme] if(!theme_to_use.can_convert(affected)) continue num_affected++ diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm index 026c5974d5f..a4ebfc21f1a 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm @@ -51,7 +51,7 @@ /obj/effect/anomaly/dimensional/proc/prepare_area(new_theme_path) if (!new_theme_path) new_theme_path = pick(subtypesof(/datum/dimension_theme)) - theme = SSmaterials.dimensional_themes[new_theme_path] + theme = DSmaterials.dimensional_themes[new_theme_path] apply_theme_icon() target_turfs = list() diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index 4f4b2543792..fb87f788036 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -47,7 +47,7 @@ break return - var/datum/move_loop/loop = SSmove_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) /obj/effect/decal/cleanable/xenoblood/xgibs/proc/spread_movement_effects(datum/move_loop/has_target/source) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index ccb05b082b3..7812ba789b5 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -163,7 +163,7 @@ break return - var/datum/move_loop/loop = SSmove_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) /obj/effect/decal/cleanable/blood/gibs/proc/spread_movement_effects(datum/move_loop/has_target/source) @@ -376,7 +376,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) /// Set the splatter up to fly through the air until it rounds out of steam or hits something /obj/effect/decal/cleanable/blood/hitsplatter/proc/fly_towards(turf/target_turf, range) var/delay = 2 - var/datum/move_loop/loop = SSmove_manager.move_towards(src, target_turf, delay, timeout = delay * range, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_START_FAST) + var/datum/move_loop/loop = DSmove_manager.move_towards(src, target_turf, delay, timeout = delay * range, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_START_FAST) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(loop_done)) diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index d248b5e691d..77034850a0b 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -32,7 +32,7 @@ break return - var/datum/move_loop/loop = SSmove_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) /obj/effect/decal/cleanable/robot_debris/proc/spread_movement_effects(datum/move_loop/has_target/source) diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index 9d2d13f9925..9e5418a94f4 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -67,7 +67,7 @@ would spawn and follow the beaker, even if it is carried or thrown. var/step_amt = pick(1,2,3) var/step_delay = 5 - var/datum/move_loop/loop = SSmove_manager.move(effect, direction, step_delay, timeout = step_delay * step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move(effect, direction, step_delay, timeout = step_delay * step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(decrement_total_effect)) /datum/effect_system/proc/decrement_total_effect(datum/source) diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index 32be64c9353..9153d4151b3 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -11,7 +11,7 @@ /obj/effect/particle_effect/expl_particles/LateInitialize() var/step_amt = pick(25;1,50;2,100;3,200;4) - var/datum/move_loop/loop = SSmove_manager.move(src, pick(GLOB.alldirs), 1, timeout = step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move(src, pick(GLOB.alldirs), 1, timeout = step_amt, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(end_particle)) /obj/effect/particle_effect/expl_particles/proc/end_particle(datum/source) diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm index 2edca60a320..6444cf3d0ee 100644 --- a/code/game/objects/effects/effect_system/effects_water.dm +++ b/code/game/objects/effects/effect_system/effects_water.dm @@ -38,7 +38,7 @@ /// Starts the effect moving at a target with a delay in deciseconds, and a lifetime in moves /// Returns the created loop /obj/effect/particle_effect/water/extinguisher/proc/move_at(atom/target, delay, lifetime) - var/datum/move_loop/loop = SSmove_manager.move_towards_legacy(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move_towards_legacy(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_forcemove)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(movement_stopped)) return loop @@ -63,7 +63,7 @@ // Stomach acid doesn't use legacy because it's not "targeted", and we instead want the circular sorta look /obj/effect/particle_effect/water/extinguisher/stomach_acid/move_at(atom/target, delay, lifetime) - var/datum/move_loop/loop = SSmove_manager.move_towards(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move_towards(src, target, delay, timeout = delay * lifetime, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_forcemove)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(movement_stopped)) return loop diff --git a/code/game/objects/effects/spawners/xeno_egg_delivery.dm b/code/game/objects/effects/spawners/xeno_egg_delivery.dm index b09a37f14b1..e87b27e0913 100644 --- a/code/game/objects/effects/spawners/xeno_egg_delivery.dm +++ b/code/game/objects/effects/spawners/xeno_egg_delivery.dm @@ -25,5 +25,5 @@ /obj/structure/alien/egg/delivery/Initialize(mapload) . = ..() - SScommunications.xenomorph_egg_delivered = TRUE - SScommunications.captivity_area = get_area(src) + DScommunications.xenomorph_egg_delivered = TRUE + DScommunications.captivity_area = get_area(src) diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm index ecfa560bfe6..874104c9202 100644 --- a/code/game/objects/effects/step_triggers.dm +++ b/code/game/objects/effects/step_triggers.dm @@ -70,7 +70,7 @@ ADD_TRAIT(AM, TRAIT_IMMOBILIZED, REF(src)) affecting[AM] = AM.dir - var/datum/move_loop/loop = SSmove_manager.move(AM, direction, speed, tiles ? tiles * speed : INFINITY) + var/datum/move_loop/loop = DSmove_manager.move(AM, direction, speed, tiles ? tiles * speed : INFINITY) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(set_to_normal)) diff --git a/code/game/objects/effects/temporary_visuals/effect_trail.dm b/code/game/objects/effects/temporary_visuals/effect_trail.dm index 028e5141653..2fd7d41d22c 100644 --- a/code/game/objects/effects/temporary_visuals/effect_trail.dm +++ b/code/game/objects/effects/temporary_visuals/effect_trail.dm @@ -29,7 +29,7 @@ AddElement(/datum/element/floor_loving) AddComponent(/datum/component/spawner, spawn_types = list(spawned_effect), max_spawned = max_spawned, spawn_time = spawn_interval) src.target = target - movement = SSmove_manager.move_towards(src, chasing = target, delay = move_speed, home = homing, timeout = duration, flags = MOVEMENT_LOOP_START_FAST) + movement = DSmove_manager.move_towards(src, chasing = target, delay = move_speed, home = homing, timeout = duration, flags = MOVEMENT_LOOP_START_FAST) RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_invalid)) if (isliving(target)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index b6241828e86..bd70bf2f475 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -923,7 +923,7 @@ if(flags & ITEM_SLOT_EYES) owner.update_worn_glasses() if(flags & ITEM_SLOT_EARS) - owner.update_inv_ears() + owner.update_worn_ears() if(flags & ITEM_SLOT_MASK) owner.update_worn_mask() if(flags & ITEM_SLOT_HEAD) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 4cb077808a8..556d0d47646 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -759,7 +759,7 @@ pre_noise = TRUE post_noise = FALSE - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING /obj/item/toy/crayon/spraycan/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm index c9b6fe4a134..7a57782dd39 100644 --- a/code/game/objects/items/credit_holochip.dm +++ b/code/game/objects/items/credit_holochip.dm @@ -7,7 +7,7 @@ throwforce = 0 force = 0 w_class = WEIGHT_CLASS_TINY - interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH|ALLOW_RESTING /// Amount on money on the card var/credits = 0 diff --git a/code/game/objects/items/devices/battle_royale.dm b/code/game/objects/items/devices/battle_royale.dm index b4ea15c6de7..4a47b164f43 100644 --- a/code/game/objects/items/devices/battle_royale.dm +++ b/code/game/objects/items/devices/battle_royale.dm @@ -78,7 +78,7 @@ balloon_alert(user, "[required_contestants - contestant_count] contestants needed!") return - SSbattle_royale.start_battle(implanted_implants) + DSbattle_royale.start_battle(implanted_implants) for (var/obj/implanter as anything in linked_implanters) do_sparks(3, cardinal_only = FALSE, source = implanter) diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm index b7b693b999f..e43e0a656af 100644 --- a/code/game/objects/items/devices/desynchronizer.dm +++ b/code/game/objects/items/devices/desynchronizer.dm @@ -9,7 +9,7 @@ lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 2.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 5) - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /// Max time this can be set var/max_duration = 300 SECONDS /// Currently set time diff --git a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm index de14a9e123f..d5d2e6c4d14 100644 --- a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm +++ b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm @@ -1,3 +1,6 @@ +#define MIN_ENERGY_COST (0.01 * STANDARD_CELL_CHARGE) +#define MAX_ENERGY_COST (0.5 * STANDARD_CELL_CHARGE) + //Used by engineering cyborgs in place of generic circuits. /obj/item/electroadaptive_pseudocircuit name = "electroadaptive pseudocircuit" @@ -32,12 +35,12 @@ if(!R.cell) to_chat(R, span_warning("You need a power cell installed for that.")) return - if(!R.cell.use(circuit_cost)) - to_chat(R, span_warning("You don't have the energy for that (you need [display_energy(circuit_cost)].)")) - return if(recharging) to_chat(R, span_warning("[src] needs some time to recharge first.")) return + if(!R.cell.use(circuit_cost)) + to_chat(R, span_warning("You don't have the energy for that (you need [display_energy(circuit_cost)].)")) + return if(!circuits) to_chat(R, span_warning("You need more material. Use [src] on existing simple circuits to break them down.")) return @@ -46,8 +49,10 @@ circuits-- maptext = MAPTEXT(circuits) icon_state = "[initial(icon_state)]_recharging" - var/recharge_time = min(600, circuit_cost * 5) //40W of cost for one fabrication = 20 seconds of recharge time; this is to prevent spamming - addtimer(CALLBACK(src, PROC_REF(recharge)), recharge_time) + var/recharge_time = (circuit_cost - MIN_ENERGY_COST) / (MAX_ENERGY_COST - MIN_ENERGY_COST) + recharge_time = clamp(recharge_time, 0, 1) + recharge_time = (5 SECONDS) + (55 SECONDS) * recharge_time //anywhere between 5 seconds to 1 minute + addtimer(CALLBACK(src, PROC_REF(recharge)), ROUND_UP(recharge_time)) return TRUE //The actual circuit magic itself is done on a per-object basis /obj/item/electroadaptive_pseudocircuit/afterattack(atom/target, mob/living/user, proximity) @@ -68,3 +73,6 @@ playsound(src, 'sound/machines/chime.ogg', 25, TRUE) recharging = FALSE icon_state = initial(icon_state) + +#undef MIN_ENERGY_COST +#undef MAX_ENERGY_COST diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 66a8f29ed1d..ebd7729b4c5 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -152,7 +152,7 @@ name = "electronic multitool" desc = "Optimised version of a regular multitool. Streamlines processes handled by its internal microchip." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "multitool_cyborg" + icon_state = "toolkit_engiborg_multitool" toolspeed = 0.5 #undef PROXIMITY_NEAR diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 1b000ea2f91..1925737143e 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -171,7 +171,7 @@ if(istype(terminal.master, /obj/machinery/power/apc)) var/obj/machinery/power/apc/apc = terminal.master if(apc.operating && apc.cell) - drained += 0.001 * apc.cell.use(50 KILO JOULES, force = TRUE) + drained += 0.001 * apc.cell.use(0.05 * STANDARD_CELL_CHARGE, force = TRUE) internal_heat += drained /obj/item/powersink/process() diff --git a/code/game/objects/items/devices/quantum_keycard.dm b/code/game/objects/items/devices/quantum_keycard.dm index 34b83a62092..ccaef00cfc6 100644 --- a/code/game/objects/items/devices/quantum_keycard.dm +++ b/code/game/objects/items/devices/quantum_keycard.dm @@ -10,7 +10,7 @@ righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' w_class = WEIGHT_CLASS_TINY obj_flags = UNIQUE_RENAME - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /// The linked quantum pad var/obj/machinery/quantumpad/qpad diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 0898c73aa2e..44975ae417b 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -17,7 +17,7 @@ tool_behaviour = TOOL_ANALYZER custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT * 0.3, /datum/material/glass=SMALL_MATERIAL_AMOUNT * 0.2) grind_results = list(/datum/reagent/mercury = 5, /datum/reagent/iron = 5, /datum/reagent/silicon = 5) - interaction_flags_click = NEED_LITERACY|NEED_LIGHT + interaction_flags_click = NEED_LITERACY|NEED_LIGHT|ALLOW_RESTING /// Boolean whether this has a CD var/cooldown = FALSE /// The time in deciseconds diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 1a264cf3924..f52f97aeeb5 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -20,7 +20,7 @@ throw_speed = 3 throw_range = 7 custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT *2) - interaction_flags_click = NEED_LITERACY|NEED_LIGHT + interaction_flags_click = NEED_LITERACY|NEED_LIGHT|ALLOW_RESTING /// Verbose/condensed var/mode = SCANNER_VERBOSE /// HEALTH/WOUND diff --git a/code/game/objects/items/devices/swapper.dm b/code/game/objects/items/devices/swapper.dm index 6db67049174..96f378c6e32 100644 --- a/code/game/objects/items/devices/swapper.dm +++ b/code/game/objects/items/devices/swapper.dm @@ -8,7 +8,7 @@ item_flags = NOBLUDGEON lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /// Cooldown for usage var/cooldown = 30 SECONDS /// Next available time diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index c78242255a6..0132cc0f0d8 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -258,7 +258,7 @@ //Chair movement loop /obj/item/extinguisher/proc/move_chair(obj/buckled_object, movementdirection) - var/datum/move_loop/loop = SSmove_manager.move(buckled_object, movementdirection, 1, timeout = 9, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move(buckled_object, movementdirection, 1, timeout = 9, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) //This means the chair slowing down is dependant on the extinguisher existing, which is weird //Couldn't figure out a better way though RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(manage_chair_speed)) diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm index 901e506194e..2859b4d3b2c 100644 --- a/code/game/objects/items/fireaxe.dm +++ b/code/game/objects/items/fireaxe.dm @@ -86,3 +86,13 @@ tool_behaviour = TOOL_CROWBAR toolspeed = 1 usesound = 'sound/items/crowbar.ogg' + +//boarding axe +/obj/item/fireaxe/boardingaxe + icon_state = "boarding_axe0" + base_icon_state = "boarding_axe" + name = "boarding axe" + desc = "A hulking cleaver that feels like a burden just looking at it. Seems excellent at halving obstacles like windows, airlocks, barricades and people." + force_unwielded = 5 + force_wielded = 30 + demolition_mod = 3 diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index d2f4b0cfc71..be89193ba7e 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -20,7 +20,7 @@ light_range = 2 light_power = 2 light_on = FALSE - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING var/status = FALSE var/lit = FALSE //on or off var/operating = FALSE//cooldown diff --git a/code/game/objects/items/implants/implantpad.dm b/code/game/objects/items/implants/implantpad.dm index 0d0391126c9..dffd7aa77a4 100644 --- a/code/game/objects/items/implants/implantpad.dm +++ b/code/game/objects/items/implants/implantpad.dm @@ -10,7 +10,7 @@ throw_speed = 3 throw_range = 5 w_class = WEIGHT_CLASS_SMALL - interaction_flags_click = FORBID_TELEKINESIS_REACH + interaction_flags_click = FORBID_TELEKINESIS_REACH|ALLOW_RESTING ///The implant case currently inserted into the pad. var/obj/item/implantcase/inserted_case diff --git a/code/game/objects/items/inspector.dm b/code/game/objects/items/inspector.dm index f96c1beb573..ab5db9b65ce 100644 --- a/code/game/objects/items/inspector.dm +++ b/code/game/objects/items/inspector.dm @@ -1,3 +1,6 @@ +///Energy used to say an error message. +#define ENERGY_TO_SPEAK (0.001 * STANDARD_CELL_CHARGE) + /** * # N-spect scanner * @@ -28,8 +31,6 @@ var/cell_cover_open = FALSE ///Energy used per print. var/energy_per_print = INSPECTOR_ENERGY_USAGE_NORMAL - ///Energy used to say an error message. - var/energy_to_speak = 1 KILO JOULES /obj/item/inspector/Initialize(mapload) . = ..() @@ -112,7 +113,7 @@ to_chat(user, "\The [src] doesn't seem to be on... Perhaps it ran out of power?") return if(!cell.use(energy_per_print)) - if(cell.use(energy_to_speak)) + if(cell.use(ENERGY_TO_SPEAK)) say("ERROR! POWER CELL CHARGE LEVEL TOO LOW TO PRINT REPORT!") return @@ -258,7 +259,7 @@ /obj/item/inspector/clown/bananium/proc/check_settings_legality() if(print_sound_mode == INSPECTOR_PRINT_SOUND_MODE_NORMAL && time_mode == INSPECTOR_TIME_MODE_HONK) - if(cell.use(energy_to_speak)) + if(cell.use(ENERGY_TO_SPEAK)) say("Setting combination forbidden by Geneva convention revision CCXXIII selected, reverting to defaults") time_mode = INSPECTOR_TIME_MODE_SLOW print_sound_mode = INSPECTOR_PRINT_SOUND_MODE_NORMAL @@ -296,7 +297,7 @@ if(time_mode != INSPECTOR_TIME_MODE_HONK) return ..() if(paper_charges == 0) - if(cell.use(energy_to_speak)) + if(cell.use(ENERGY_TO_SPEAK)) say("ERROR! OUT OF PAPER! MAXIMUM PRINTING SPEED UNAVAIBLE! SWITCH TO A SLOWER SPEED TO OR PROVIDE PAPER!") else to_chat(user, "\The [src] doesn't seem to be on... Perhaps it ran out of power?") @@ -372,7 +373,7 @@ */ /obj/item/paper/fake_report/water grind_results = list(/datum/reagent/water = 5) - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING /obj/item/paper/fake_report/water/click_alt(mob/living/user) var/datum/action/innate/origami/origami_action = locate() in user.actions @@ -383,5 +384,6 @@ target.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) to_chat(user, span_notice("As you try to fold [src] into the shape of a plane, it disintegrates into water!")) qdel(src) - return CLICK_ACTION_SUCCESS + +#undef ENERGY_TO_SPEAK diff --git a/code/game/objects/items/machine_wand.dm b/code/game/objects/items/machine_wand.dm index c1dd0bf382d..7ce94b9ad40 100644 --- a/code/game/objects/items/machine_wand.dm +++ b/code/game/objects/items/machine_wand.dm @@ -150,7 +150,7 @@ CRASH("a moving bug has been created but isn't moving towards anything!") src.controller = controller src.thing_moving_towards = thing_moving_towards - var/datum/move_loop/loop = SSmove_manager.home_onto(src, thing_moving_towards, delay = 5, flags = MOVEMENT_LOOP_NO_DIR_UPDATE) + var/datum/move_loop/loop = DSmove_manager.home_onto(src, thing_moving_towards, delay = 5, flags = MOVEMENT_LOOP_NO_DIR_UPDATE) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(reached_destination_check)) RegisterSignal(thing_moving_towards, COMSIG_QDELETING, PROC_REF(on_machine_del)) diff --git a/code/game/objects/items/maintenance_loot.dm b/code/game/objects/items/maintenance_loot.dm index 52ed1880081..f6d7fd1c329 100644 --- a/code/game/objects/items/maintenance_loot.dm +++ b/code/game/objects/items/maintenance_loot.dm @@ -30,7 +30,7 @@ icon_state = "lead_battery" throwforce = 10 maxcharge = STANDARD_CELL_CHARGE * 20 //decent max charge - chargerate = STANDARD_CELL_CHARGE * 0.7 //charging is about 30% less efficient than lithium batteries. + chargerate = STANDARD_CELL_RATE * 0.7 //charging is about 30% less efficient than lithium batteries. charge_light_type = null connector_type = "leadacid" rating = 2 //Kind of a mid-tier battery diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index 91b51053b0e..88daf279c59 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -428,7 +428,7 @@ desc = "A device used to rapidly build walls and floors." banned_upgrades = RCD_UPGRADE_SILO_LINK /// enery usage - var/energyfactor = 72 KILO JOULES + var/energyfactor = 0.072 * STANDARD_CELL_CHARGE /obj/item/construction/rcd/borg/get_matter(mob/user) if(!iscyborg(user)) @@ -470,7 +470,7 @@ desc = "A reverse-engineered RCD with black market upgrades that allow this device to deconstruct reinforced walls. Property of Donk Co." icon_state = "ircd" inhand_icon_state = "ircd" - energyfactor = 66 KILO JOULES + energyfactor = 0.066 * STANDARD_CELL_CHARGE canRturf = TRUE /obj/item/construction/rcd/loaded @@ -522,7 +522,7 @@ upgrade = RCD_ALL_UPGRADES & ~RCD_UPGRADE_SILO_LINK ///How much charge is used up for each matter unit. -#define MASS_TO_ENERGY (16 KILO JOULES) +#define MASS_TO_ENERGY (0.016 * STANDARD_CELL_CHARGE) /obj/item/construction/rcd/exosuit name = "mounted RCD" diff --git a/code/game/objects/items/robot/items/food.dm b/code/game/objects/items/robot/items/food.dm index 1878b0c1e00..40166a6a8fb 100644 --- a/code/game/objects/items/robot/items/food.dm +++ b/code/game/objects/items/robot/items/food.dm @@ -121,7 +121,7 @@ check_amount() if(iscyborg(user)) var/mob/living/silicon/robot/robot_user = user - if(!robot_user.cell.use(12 KILO JOULES)) + if(!robot_user.cell.use(0.012 * STANDARD_CELL_CHARGE)) to_chat(user, span_warning("Not enough power.")) return AFTERATTACK_PROCESSED_ITEM switch(mode) diff --git a/code/game/objects/items/robot/items/hypo.dm b/code/game/objects/items/robot/items/hypo.dm index 847807ee9f4..b685d5405f1 100644 --- a/code/game/objects/items/robot/items/hypo.dm +++ b/code/game/objects/items/robot/items/hypo.dm @@ -109,7 +109,7 @@ */ var/max_volume_per_reagent = 30 /// Cell cost for charging a reagent - var/charge_cost = 50 KILO JOULES + var/charge_cost = 0.05 * STANDARD_CELL_CHARGE /// Counts up to the next time we charge var/charge_timer = 0 /// Time it takes for shots to recharge (in seconds) @@ -310,7 +310,7 @@ SKYRAT EDIT REMOVAL END */ Also metabolizes potassium iodide for radiation poisoning, inacusiate for ear damage and morphine for offense." icon_state = "borghypo_s" tgui_theme = "syndicate" - charge_cost = 20 KILO JOULES + charge_cost = 0.02 * STANDARD_CELL_CHARGE recharge_time = 2 default_reagent_types = BASE_SYNDICATE_REAGENTS bypass_protection = TRUE @@ -323,7 +323,7 @@ SKYRAT EDIT REMOVAL END */ icon_state = "shaker" possible_transfer_amounts = list(5,10,20,1) // Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster. - charge_cost = 20 KILO JOULES + charge_cost = 0.02 * STANDARD_CELL_CHARGE recharge_time = 3 dispensed_temperature = WATER_MATTERSTATE_CHANGE_TEMP //Water stays wet, ice stays ice default_reagent_types = BASE_SERVICE_REAGENTS @@ -395,7 +395,7 @@ SKYRAT EDIT REMOVAL END */ icon_state = "flour" possible_transfer_amounts = list(5,10,20,1) // Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster. - charge_cost = 40 KILO JOULES //Costs double the power of the borgshaker due to synthesizing solids + charge_cost = 0.04 * STANDARD_CELL_CHARGE //Costs double the power of the borgshaker due to synthesizing solids recharge_time = 6 //Double the recharge time too, for the same reason. dispensed_temperature = WATER_MATTERSTATE_CHANGE_TEMP default_reagent_types = EXPANDED_SERVICE_REAGENTS diff --git a/code/game/objects/items/robot/items/tools.dm b/code/game/objects/items/robot/items/tools.dm index 538fd1b7ca1..49c3197ae1e 100644 --- a/code/game/objects/items/robot/items/tools.dm +++ b/code/game/objects/items/robot/items/tools.dm @@ -1,5 +1,7 @@ #define PKBORG_DAMPEN_CYCLE_DELAY (2 SECONDS) -#define POWER_RECHARGE_CYBORG_DRAIN_MULTIPLIER (0.4 KILO WATTS) +#define POWER_RECHARGE_CYBORG_DRAIN_MULTIPLIER (0.0004 * STANDARD_CELL_RATE) +#define NO_TOOL "deactivated" +#define TOOL_DRAPES "surgical_drapes" /obj/item/cautery/prt //it's a subtype of cauteries so that it inherits the cautery sprites and behavior and stuff, because I'm too lazy to make sprites for this thing name = "plating repair tool" @@ -174,5 +176,214 @@ projectile.speed *= (1 / projectile_speed_coefficient) projectile.cut_overlay(projectile_effect) +//bare minimum omni-toolset for modularity +/obj/item/borg/cyborg_omnitool + name = "cyborg omni-toolset" + desc = "You shouldn't see this in-game normally." + icon = 'icons/mob/silicon/robot_items.dmi' + icon_state = "toolkit_medborg" + ///our tools + var/list/radial_menu_options = list() + ///object we are referencing to for force, sharpness and sound + var/obj/item/reference + //is the toolset upgraded or not + var/upgraded = FALSE + ///how much faster should the toolspeed be? + var/upgraded_toolspeed = 0.7 + +/obj/item/borg/cyborg_omnitool/get_all_tool_behaviours() + return list(TOOL_SCALPEL, TOOL_HEMOSTAT) + +/obj/item/borg/cyborg_omnitool/Initialize(mapload) + . = ..() + AddComponent(/datum/component/butchering, \ + speed = 8 SECONDS, \ + effectiveness = 100, \ + disabled = TRUE, \ + ) + radial_menu_options = list( + NO_TOOL = image(icon = 'icons/mob/silicon/robot_items.dmi', icon_state = initial(icon_state)), + TOOL_SCALPEL = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_SCALPEL]"), + TOOL_HEMOSTAT = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_HEMOSTAT]"), + ) + +/obj/item/borg/cyborg_omnitool/attack_self(mob/user) + var/new_tool_behaviour = show_radial_menu(user, src, radial_menu_options, require_near = TRUE, tooltips = TRUE) + + if(isnull(new_tool_behaviour) || new_tool_behaviour == tool_behaviour) + return + if(new_tool_behaviour == NO_TOOL) + tool_behaviour = null + else + tool_behaviour = new_tool_behaviour + + reference_item_for_parameters() + update_tool_parameters(reference) + update_appearance(UPDATE_ICON_STATE) + playsound(src, 'sound/items/change_jaws.ogg', 50, TRUE) + +/// Used to get reference item for the tools +/obj/item/borg/cyborg_omnitool/proc/reference_item_for_parameters() + SHOULD_CALL_PARENT(FALSE) + switch(tool_behaviour) + if(TOOL_SCALPEL) + reference = /obj/item/scalpel + if(TOOL_HEMOSTAT) + reference = /obj/item/hemostat + +/// Used to update sounds and tool parameters during switching +/obj/item/borg/cyborg_omnitool/proc/update_tool_parameters(/obj/item/reference) + if(isnull(reference)) + sharpness = NONE + force = initial(force) + hitsound = initial(hitsound) + usesound = initial(usesound) + else + force = initial(reference.force) + sharpness = initial(reference.sharpness) + hitsound = initial(reference.hitsound) + usesound = initial(reference.usesound) + +/obj/item/borg/cyborg_omnitool/update_icon_state() + icon_state = initial(icon_state) + + if (tool_behaviour) + icon_state += "_[sanitize_css_class_name(tool_behaviour)]" + + if(tool_behaviour) + inhand_icon_state = initial(inhand_icon_state) + "_deactivated" + else + inhand_icon_state = initial(inhand_icon_state) + + return ..() + +/** + * proc that's used when cyborg is upgraded with an omnitool upgrade board + * + * adds name and desc changes. also changes tools to default configuration to indicate it's been sucessfully upgraded + * changes the toolspeed to the upgraded_toolspeed variable + */ +/obj/item/borg/cyborg_omnitool/proc/upgrade_omnitool() + name = "advanced [name]" + desc += "\nIt seems that this one has been upgraded to perform tasks faster." + toolspeed = upgraded_toolspeed + upgraded = TRUE + tool_behaviour = null + reference_item_for_parameters() + update_tool_parameters(reference) + update_appearance(UPDATE_ICON_STATE) + playsound(src, 'sound/items/change_jaws.ogg', 50, TRUE) + +/** + * proc that's used when a cyborg with an upgraded omnitool is downgraded + * + * reverts all name and desc changes to it's initial variables. also changes tools to default configuration to indicate it's been downgraded + * changes the toolspeed to default variable + */ +/obj/item/borg/cyborg_omnitool/proc/downgrade_omnitool() + name = initial(name) + desc = initial(desc) + toolspeed = initial(toolspeed) + upgraded = FALSE + tool_behaviour = null + reference_item_for_parameters() + update_tool_parameters(reference) + update_appearance(UPDATE_ICON_STATE) + playsound(src, 'sound/items/change_jaws.ogg', 50, TRUE) + +/obj/item/borg/cyborg_omnitool/medical + name = "surgical omni-toolset" + desc = "A set of surgical tools used by cyborgs to operate on various surgical operations." + item_flags = SURGICAL_TOOL + +/obj/item/borg/cyborg_omnitool/medical/get_all_tool_behaviours() + return list(TOOL_SCALPEL, TOOL_HEMOSTAT, TOOL_RETRACTOR, TOOL_SAW, TOOL_DRILL, TOOL_CAUTERY, TOOL_BONESET) + +/obj/item/borg/cyborg_omnitool/medical/Initialize(mapload) + . = ..() + AddComponent(/datum/component/butchering, \ + speed = 8 SECONDS, \ + effectiveness = 100, \ + disabled = TRUE, \ + ) + radial_menu_options = list( + TOOL_SCALPEL = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_SCALPEL]"), + TOOL_HEMOSTAT = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_HEMOSTAT]"), + TOOL_RETRACTOR = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_RETRACTOR]"), + TOOL_SAW = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_SAW]"), + TOOL_DRILL = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_DRILL]"), + TOOL_CAUTERY = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_CAUTERY]"), + TOOL_BONESET = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_BONESET]"), + TOOL_DRAPES = image(icon = 'icons/obj/medical/surgery_tools.dmi', icon_state = "[TOOL_DRAPES]"), + ) + +/obj/item/borg/cyborg_omnitool/medical/reference_item_for_parameters() + var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering) + butchering.butchering_enabled = (tool_behaviour == TOOL_SCALPEL || tool_behaviour == TOOL_SAW) + RemoveElement(/datum/element/eyestab) + qdel(GetComponent(/datum/component/surgery_initiator)) + item_flags = SURGICAL_TOOL + switch(tool_behaviour) + if(TOOL_SCALPEL) + reference = /obj/item/scalpel + AddElement(/datum/element/eyestab) + if(TOOL_DRILL) + reference = /obj/item/surgicaldrill + AddElement(/datum/element/eyestab) + if(TOOL_HEMOSTAT) + reference = /obj/item/hemostat + if(TOOL_RETRACTOR) + reference = /obj/item/retractor + if(TOOL_CAUTERY) + reference = /obj/item/cautery + if(TOOL_SAW) + reference = /obj/item/circular_saw + if(TOOL_BONESET) + reference = /obj/item/bonesetter + if(TOOL_DRAPES) + reference = /obj/item/surgical_drapes + AddComponent(/datum/component/surgery_initiator) + item_flags = null + +//Toolset for engineering cyborgs, this is all of the tools except for the welding tool. since it's quite hard to implement (read:can't be arsed to) +/obj/item/borg/cyborg_omnitool/engineering + name = "engineering omni-toolset" + desc = "A set of engineering tools used by cyborgs to conduct various engineering tasks." + icon = 'icons/obj/items_cyborg.dmi' + icon_state = "toolkit_engiborg" + item_flags = null + toolspeed = 0.5 + upgraded_toolspeed = 0.3 + +/obj/item/borg/cyborg_omnitool/engineering/get_all_tool_behaviours() + return list(TOOL_SCREWDRIVER, TOOL_CROWBAR, TOOL_WRENCH, TOOL_WIRECUTTER, TOOL_MULTITOOL) + +/obj/item/borg/cyborg_omnitool/engineering/Initialize(mapload) + . = ..() + radial_menu_options = list( + TOOL_SCREWDRIVER = image(icon = 'icons/obj/tools.dmi', icon_state = "[TOOL_SCREWDRIVER]_map"), + TOOL_CROWBAR = image(icon = 'icons/obj/tools.dmi', icon_state = "[TOOL_CROWBAR]"), + TOOL_WRENCH = image(icon = 'icons/obj/tools.dmi', icon_state = "[TOOL_WRENCH]"), + TOOL_WIRECUTTER = image(icon = 'icons/obj/tools.dmi', icon_state = "[TOOL_WIRECUTTER]_map"), + TOOL_MULTITOOL = image(icon = 'icons/obj/devices/tool.dmi', icon_state = "[TOOL_MULTITOOL]"), + ) + +/obj/item/borg/cyborg_omnitool/engineering/reference_item_for_parameters() + RemoveElement(/datum/element/eyestab) + switch(tool_behaviour) + if(TOOL_SCREWDRIVER) + reference = /obj/item/crowbar + AddElement(/datum/element/eyestab) + if(TOOL_CROWBAR) + reference = /obj/item/surgicaldrill + if(TOOL_WRENCH) + reference = /obj/item/wrench + if(TOOL_WIRECUTTER) + reference = /obj/item/wirecutters + if(TOOL_MULTITOOL) + reference = /obj/item/multitool + #undef PKBORG_DAMPEN_CYCLE_DELAY #undef POWER_RECHARGE_CYBORG_DRAIN_MULTIPLIER +#undef NO_TOOL +#undef TOOL_DRAPES diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 885a97a9329..666ae97105f 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -298,7 +298,7 @@ /// Minimum time between repairs in seconds var/repair_cooldown = 4 var/on = FALSE - var/energy_cost = 10 KILO JOULES + var/energy_cost = 0.01 * STANDARD_CELL_CHARGE var/datum/action/toggle_action /obj/item/borg/upgrade/selfrepair/action(mob/living/silicon/robot/R, user = usr) @@ -366,16 +366,16 @@ if(cyborg.health < cyborg.maxHealth) if(cyborg.health < 0) repair_amount = -2.5 - energy_cost = 30 KILO JOULES + energy_cost = 0.03 * STANDARD_CELL_CHARGE else repair_amount = -1 - energy_cost = 10 KILO JOULES + energy_cost = 0.01 * STANDARD_CELL_CHARGE cyborg.adjustBruteLoss(repair_amount) cyborg.adjustFireLoss(repair_amount) cyborg.updatehealth() cyborg.cell.use(energy_cost) else - cyborg.cell.use(5 KILO JOULES) + cyborg.cell.use(0.005 * STANDARD_CELL_CHARGE) next_repair = world.time + repair_cooldown * 10 // Multiply by 10 since world.time is in deciseconds if(TIMER_COOLDOWN_FINISHED(src, COOLDOWN_BORG_SELF_REPAIR)) @@ -444,6 +444,60 @@ for(var/obj/item/reagent_containers/borghypo/H in R.model.modules) H.bypass_protection = initial(H.bypass_protection) +/obj/item/borg/upgrade/surgery_omnitool + name = "cyborg surgical omni-tool upgrade" + desc = "An upgrade to the Medical model, upgrading the built-in \ + surgical omnitool, to be on par with advanced surgical tools" + icon_state = "cyborg_upgrade3" + require_model = TRUE + model_type = list(/obj/item/robot_model/medical, /obj/item/robot_model/syndicate_medical) + model_flags = BORG_MODEL_MEDICAL + +/obj/item/borg/upgrade/surgery_omnitool/action(mob/living/silicon/robot/cyborg, user = usr) + . = ..() + if(!.) + return FALSE + for(var/obj/item/borg/cyborg_omnitool/medical/omnitool_upgrade in cyborg.model.modules) + if(omnitool_upgrade.upgraded) + to_chat(user, span_warning("This unit is already equipped with an omnitool upgrade!")) + return FALSE + for(var/obj/item/borg/cyborg_omnitool/medical/omnitool in cyborg.model.modules) + omnitool.upgrade_omnitool() + +/obj/item/borg/upgrade/surgery_omnitool/deactivate(mob/living/silicon/robot/cyborg, user = usr) + . = ..() + if(!.) + return FALSE + for(var/obj/item/borg/cyborg_omnitool/omnitool in cyborg.model.modules) + omnitool.downgrade_omnitool() + +/obj/item/borg/upgrade/engineering_omnitool + name = "cyborg engineering omni-tool upgrade" + desc = "An upgrade to the Engineering model, upgrading the built-in \ + engineering omnitool, to be on par with advanced engineering tools" + icon_state = "cyborg_upgrade3" + require_model = TRUE + model_type = list(/obj/item/robot_model/engineering, /obj/item/robot_model/saboteur) + model_flags = BORG_MODEL_ENGINEERING + +/obj/item/borg/upgrade/engineering_omnitool/action(mob/living/silicon/robot/cyborg, user = usr) + . = ..() + if(!.) + return FALSE + for(var/obj/item/borg/cyborg_omnitool/engineering/omnitool_upgrade in cyborg.model.modules) + if(omnitool_upgrade.upgraded) + to_chat(user, span_warning("This unit is already equipped with an omnitool upgrade!")) + return FALSE + for(var/obj/item/borg/cyborg_omnitool/engineering/omnitool in cyborg.model.modules) + omnitool.upgrade_omnitool() + +/obj/item/borg/upgrade/engineering_omnitool/deactivate(mob/living/silicon/robot/cyborg, user = usr) + . = ..() + if(!.) + return FALSE + for(var/obj/item/borg/cyborg_omnitool/omnitool in cyborg.model.modules) + omnitool.downgrade_omnitool() + /obj/item/borg/upgrade/defib name = "medical cyborg defibrillator" desc = "An upgrade to the Medical model, installing a built-in \ diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 66dd5a34b6a..2cc41b5d9f2 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -99,6 +99,15 @@ max_integrity = 55 w_class = WEIGHT_CLASS_NORMAL +/obj/item/shield/kite + name = "kite shield" + desc = "Protect your internal organs with this almond shaped shield." + icon_state = "kite" + inhand_icon_state = "kite" + custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 15) + shield_break_sound = 'sound/effects/grillehit.ogg' + max_integrity = 60 + /obj/item/shield/roman name = "\improper Roman shield" desc = "Bears an inscription on the inside: \"Romanes venio domus\"." diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 401ffd46934..f4c0b58a11b 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -216,6 +216,31 @@ M.Copy_Parent(user, 100, user.health/2.5, 12, 30) M.GiveTarget(L) +//MILITARY +/obj/item/spear/military + icon_state = "military_spear0" + base_icon_state = "military_spear0" + icon_prefix = "military_spear" + name = "military Javelin" + desc = "A stick with a seemingly blunt spearhead on its end. Looks like it might break bones easily." + attack_verb_continuous = list("attacks", "pokes", "jabs") + attack_verb_simple = list("attack", "poke", "jab") + throwforce = 30 + demolition_mod = 1 + wound_bonus = 5 + bare_wound_bonus = 25 + throw_range = 9 + throw_speed = 5 + sharpness = NONE // we break bones instead of cutting flesh + +/obj/item/spear/military/add_headpike_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpikemilitary) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /* * Bone Spear */ diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm index c55a39c20f7..bf2c628ab97 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -160,6 +160,11 @@ owner.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), TRAIT_STATUS_EFFECT(id)) return ..() +/// What do we multiply our damage by to convert it into power? +#define ENERGY_PER_DAMAGE (0.005 * STANDARD_CELL_CHARGE) +/// Multiplier to apply to burn damage, not 0 so that we can reverse it more easily +#define BURN_MULTIPLIER 0.05 + /// Heat immunity, turns heat damage into local power /datum/status_effect/golem/plasma overlay_state_prefix = "plasma" @@ -167,10 +172,6 @@ applied_fluff = "Plasma cooling rods sprout from your body. You can take the heat!" alert_icon_state = "sheet-plasma" alert_desc = "You are protected from high pressure and can convert heat damage into power." - /// What do we multiply our damage by to convert it into power? - var/energy_per_damage = 5 KILO JOULES - /// Multiplier to apply to burn damage, not 0 so that we can reverse it more easily - var/burn_multiplier = 0.05 /datum/status_effect/golem/plasma/on_apply() . = ..() @@ -179,14 +180,14 @@ owner.add_traits(list(TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTHEAT, TRAIT_ASHSTORM_IMMUNE), TRAIT_STATUS_EFFECT(id)) RegisterSignal(owner, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_burned)) var/mob/living/carbon/human/human_owner = owner - human_owner.physiology.burn_mod *= burn_multiplier + human_owner.physiology.burn_mod *= BURN_MULTIPLIER return TRUE /datum/status_effect/golem/plasma/on_remove() owner.remove_traits(list(TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTHEAT, TRAIT_ASHSTORM_IMMUNE), TRAIT_STATUS_EFFECT(id)) UnregisterSignal(owner, COMSIG_MOB_APPLY_DAMAGE) var/mob/living/carbon/human/human_owner = owner - human_owner.physiology.burn_mod /= burn_multiplier + human_owner.physiology.burn_mod /= BURN_MULTIPLIER return ..() /// When we take fire damage (or... technically also cold damage, we don't differentiate), zap a nearby APC @@ -195,7 +196,6 @@ if(damagetype != BURN) return - var/power = damage * energy_per_damage var/obj/machinery/power/energy_accumulator/ground = get_closest_atom(/obj/machinery/power/energy_accumulator, view(4, owner), owner) if (ground) zap_effect(ground) @@ -206,7 +206,10 @@ if (!our_apc) return zap_effect(our_apc) - our_apc.cell?.give(power) + our_apc.cell?.give(damage * ENERGY_PER_DAMAGE) + +#undef ENERGY_PER_DAMAGE +#undef BURN_MULTIPLIER /// Shoot a beam at the target atom /datum/status_effect/golem/plasma/proc/zap_effect(atom/target) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 18a95cd77d3..83235796a45 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -110,9 +110,9 @@ for(var/category in what_are_we_made_of.categories) switch(category) if(MAT_CATEGORY_BASE_RECIPES) - recipes |= SSmaterials.base_stack_recipes.Copy() + recipes |= DSmaterials.base_stack_recipes.Copy() if(MAT_CATEGORY_RIGID) - recipes |= SSmaterials.rigid_stack_recipes.Copy() + recipes |= DSmaterials.rigid_stack_recipes.Copy() update_weight() update_appearance() @@ -131,7 +131,7 @@ * - multiplier: The amount to multiply the mats per unit by. Defaults to 1. */ /obj/item/stack/proc/set_mats_per_unit(list/mats, multiplier=1) - mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats, multiplier) + mats_per_unit = DSmaterials.FindOrCreateMaterialCombo(mats, multiplier) update_custom_materials() /** Updates the custom materials list of this stack. diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index cc548be16d2..dd4fb325858 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -406,7 +406,7 @@ /obj/item/storage/bag/tray/proc/do_scatter(obj/item/tray_item) var/delay = rand(2,4) - var/datum/move_loop/loop = SSmove_manager.move_rand(tray_item, list(NORTH,SOUTH,EAST,WEST), delay, timeout = rand(1, 2) * delay, flags = MOVEMENT_LOOP_START_FAST) + var/datum/move_loop/loop = DSmove_manager.move_rand(tray_item, list(NORTH,SOUTH,EAST,WEST), delay, timeout = rand(1, 2) * delay, flags = MOVEMENT_LOOP_START_FAST) //This does mean scattering is tied to the tray. Not sure how better to handle it RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(change_speed)) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index ebfa73aa2f9..a2c553fbea1 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -839,7 +839,7 @@ inhand_icon_state = "sheath" worn_icon_state = "sheath" w_class = WEIGHT_CLASS_BULKY - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS /obj/item/storage/belt/sabre/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index 8631d62e79e..75ca06ff0ff 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -2,6 +2,7 @@ name = "storage" icon = 'icons/obj/storage/storage.dmi' w_class = WEIGHT_CLASS_NORMAL + interaction_flags_click = ALLOW_RESTING|FORBID_TELEKINESIS_REACH var/rummage_if_nodrop = TRUE /// Should we preload the contents of this type? /// BE CAREFUL, THERE'S SOME REALLY NASTY SHIT IN THIS TYPEPATH diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index b21deb35581..70c0ea0822a 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -8,7 +8,7 @@ * Generic */ /obj/item/tank/internals - interaction_flags_click = FORBID_TELEKINESIS_REACH|NEED_HANDS + interaction_flags_click = FORBID_TELEKINESIS_REACH|NEED_HANDS|ALLOW_RESTING /// Allows carbon to toggle internals via AltClick of the equipped tank. diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index 9950b8e9c93..5cef642634a 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -309,7 +309,7 @@ user.log_message("used Resin Launcher", LOG_GAME) playsound(src,'sound/items/syringeproj.ogg',40,TRUE) var/delay = 2 - var/datum/move_loop/loop = SSmove_manager.move_towards(resin, target, delay, timeout = delay * 5, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = DSmove_manager.move_towards(resin, target, delay, timeout = delay * 5, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(resin_stop_check)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(resin_landed)) return diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 56d7344f31b..9bb61e847b7 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -189,7 +189,7 @@ name = "hydraulic crowbar" desc = "A hydraulic prying tool, simple but powerful." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "crowbar_cyborg" + icon_state = "toolkit_engiborg_crowbar" worn_icon_state = "crowbar" usesound = 'sound/items/jaws_pry.ogg' force = 10 diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index cbdc79e0420..02765122a13 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -148,7 +148,7 @@ name = "automated screwdriver" desc = "A powerful automated screwdriver, designed to be both precise and quick." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "screwdriver_cyborg" + icon_state = "toolkit_engiborg_screwdriver" hitsound = 'sound/items/drill_hit.ogg' usesound = 'sound/items/drill_use.ogg' toolspeed = 0.5 diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm index dad9763bd3d..e7e4dbe699a 100644 --- a/code/game/objects/items/tools/wirecutters.dm +++ b/code/game/objects/items/tools/wirecutters.dm @@ -77,7 +77,7 @@ name = "powered wirecutters" desc = "Cuts wires with the power of ELECTRICITY. Faster than normal wirecutters." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "wirecutters_cyborg" + icon_state = "toolkit_engiborg_cutters" worn_icon_state = "cutters" toolspeed = 0.5 random_color = FALSE diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index c4326cf3de8..8fbb681acfc 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -87,7 +87,7 @@ name = "hydraulic wrench" desc = "An advanced robotic wrench, powered by internal hydraulics. Twice as fast as the handheld version." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "wrench_cyborg" + icon_state = "toolkit_engiborg_wrench" toolspeed = 0.5 /obj/item/wrench/combat diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 2aa649844e5..f7717da19e7 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -175,6 +175,18 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 block_chance = 10 resistance_flags = NONE +//bootleg claymore +/obj/item/claymore/shortsword + name = "shortsword" + desc = "A mercenary's sword, chipped and worn from battles long gone. You could say it is a swordsman's shortsword short sword." + icon_state = "shortsword" + inhand_icon_state = "shortsword" + worn_icon_state = "shortsword" + slot_flags = ITEM_SLOT_BELT + force = 20 + demolition_mod = 0.75 + block_chance = 30 + /obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." obj_flags = CONDUCTS_ELECTRICITY diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 8b4fef65293..ba2a8685b8b 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -20,7 +20,7 @@ LINEN BINS w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE dying_key = DYE_REGISTRY_BEDSHEET - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING dog_fashion = /datum/dog_fashion/head/ghost /// Custom nouns to act as the subject of dreams diff --git a/code/game/objects/structures/gym/punching_bag.dm b/code/game/objects/structures/gym/punching_bag.dm index f441887f2c1..ef0db16e953 100644 --- a/code/game/objects/structures/gym/punching_bag.dm +++ b/code/game/objects/structures/gym/punching_bag.dm @@ -57,9 +57,12 @@ stamina_exhaustion = 2 if (is_heavy_gravity) stamina_exhaustion *= 1.5 + + if(HAS_TRAIT(user, TRAIT_STRENGTH)) //The strong get reductions to stamina damage taken while exercising + stamina_exhaustion *= 0.5 user.adjustStaminaLoss(stamina_exhaustion) - user.mind?.adjust_experience(/datum/skill/fitness, is_heavy_gravity ? 0.2 : 0.1) + user.mind?.adjust_experience(/datum/skill/athletics, is_heavy_gravity ? 0.2 : 0.1) user.apply_status_effect(/datum/status_effect/exercised) /obj/structure/punching_bag/wrench_act_secondary(mob/living/user, obj/item/tool) diff --git a/code/game/objects/structures/gym/weight_machine.dm b/code/game/objects/structures/gym/weight_machine.dm index d3614ee6815..3c531f04889 100644 --- a/code/game/objects/structures/gym/weight_machine.dm +++ b/code/game/objects/structures/gym/weight_machine.dm @@ -109,7 +109,7 @@ if(do_after(user, 8 SECONDS, src) && user.has_gravity()) // with enough dedication, even clowns can overcome their handicaps - var/clumsy_chance = 30 - (user.mind.get_skill_level(/datum/skill/fitness) * 5) + var/clumsy_chance = 30 - (user.mind.get_skill_level(/datum/skill/athletics) * 5) if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(clumsy_chance)) playsound(src, 'sound/effects/bang.ogg', 50, TRUE) to_chat(user, span_warning("Your hand slips, causing the [name] to smash you!")) @@ -135,7 +135,7 @@ if(iscarbon(user)) var/gravity_modifier = user.has_gravity() > STANDARD_GRAVITY ? 2 : 1 // remember the real xp gain is from sleeping after working out - user.mind.adjust_experience(/datum/skill/fitness, WORKOUT_XP * gravity_modifier) + user.mind.adjust_experience(/datum/skill/athletics, WORKOUT_XP * gravity_modifier) user.apply_status_effect(/datum/status_effect/exercised, EXERCISE_STATUS_DURATION) end_workout() @@ -168,9 +168,13 @@ return TRUE // No weight? I could do this all day var/gravity_modifier = affected_gravity > STANDARD_GRAVITY ? 0.75 : 1 // the amount of workouts you can do before you hit stamcrit - var/workout_reps = total_workout_reps[user.mind.get_skill_level(/datum/skill/fitness)] * gravity_modifier + var/workout_reps = total_workout_reps[user.mind.get_skill_level(/datum/skill/athletics)] * gravity_modifier // total stamina drain of 1 workout calculated based on the workout length var/stamina_exhaustion = FLOOR(user.maxHealth / workout_reps / WORKOUT_LENGTH, 0.1) + + if(HAS_TRAIT(user, TRAIT_STRENGTH)) //The strong get reductions to stamina damage taken while exercising + stamina_exhaustion *= 0.5 + user.adjustStaminaLoss(stamina_exhaustion * seconds_per_tick) return TRUE diff --git a/code/game/objects/structures/headpike.dm b/code/game/objects/structures/headpike.dm index 0c29d92d53b..b4cffdb654d 100644 --- a/code/game/objects/structures/headpike.dm +++ b/code/game/objects/structures/headpike.dm @@ -17,6 +17,10 @@ icon_state = "headpike-bamboo" speartype = /obj/item/spear/bamboospear +/obj/structure/headpike/military //for military spears + icon_state = "headpike-military" + speartype = /obj/item/spear/military + /obj/structure/headpike/Initialize(mapload) . = ..() if(mapload) diff --git a/code/game/objects/structures/lavaland/gulag_vent.dm b/code/game/objects/structures/lavaland/gulag_vent.dm index aa13a1621d8..b564908cdc6 100644 --- a/code/game/objects/structures/lavaland/gulag_vent.dm +++ b/code/game/objects/structures/lavaland/gulag_vent.dm @@ -34,9 +34,10 @@ occupied = FALSE if (!succeeded) return - living_user.mind?.adjust_experience(/datum/skill/fitness, 10) + var/stamina_damage_to_inflict = HAS_TRAIT(user, TRAIT_STRENGTH) ? 60 : 120 //Decreases the amount of stamina damage inflicted by half if you're STRONG + living_user.mind?.adjust_experience(/datum/skill/athletics, 10) living_user.apply_status_effect(/datum/status_effect/exercised) new spawned_boulder(get_turf(living_user)) living_user.visible_message(span_notice("[living_user] hauls a boulder out of [src].")) - living_user.apply_damage(120, STAMINA) + living_user.apply_damage(stamina_damage_to_inflict, STAMINA) playsound(src, 'sound/weapons/genhit.ogg', vol = 50, vary = TRUE) diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index 70ab15427b7..a6ab8a58d70 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -270,6 +270,7 @@ balloon_alert_to_viewers("vent tapped!") icon_state = icon_state_tapped update_appearance(UPDATE_ICON_STATE) + qdel(GetComponent(/datum/component/gps)) else visible_message(span_danger("\the [src] creaks and groans as the mining attempt fails, and the vent closes back up.")) icon_state = initial(icon_state) @@ -308,6 +309,7 @@ discovered = TRUE generate_description(user) balloon_alert_to_viewers("vent scanned!") + AddComponent(/datum/component/gps, name) return if(DOING_INTERACTION_WITH_TARGET(user, src)) @@ -321,6 +323,7 @@ discovered = TRUE balloon_alert(user, "vent scanned!") generate_description(user) + AddComponent(/datum/component/gps, name) var/obj/item/card/id/user_id_card = user.get_idcard(TRUE) if(isnull(user_id_card)) return diff --git a/code/game/objects/structures/mystery_box.dm b/code/game/objects/structures/mystery_box.dm index 1843ef99761..ab8a25f04c6 100644 --- a/code/game/objects/structures/mystery_box.dm +++ b/code/game/objects/structures/mystery_box.dm @@ -67,6 +67,32 @@ GLOBAL_LIST_INIT(mystery_box_extended, list( /obj/item/circular_saw, )) +GLOBAL_LIST_INIT(mystery_magic, list( + /obj/item/gun/magic/wand/arcane_barrage, + /obj/item/gun/magic/wand/arcane_barrage/blood, + /obj/item/gun/magic/wand/fireball, + /obj/item/gun/magic/wand/resurrection, + /obj/item/gun/magic/wand/death, + /obj/item/gun/magic/wand/polymorph, + /obj/item/gun/magic/wand/teleport, + /obj/item/gun/magic/wand/door, + /obj/item/gun/magic/wand/nothing, + /obj/item/storage/belt/wands/full, + /obj/item/gun/magic/staff/healing, + /obj/item/gun/magic/staff/change, + /obj/item/gun/magic/staff/animate, + /obj/item/gun/magic/staff/chaos, + /obj/item/gun/magic/staff/door, + /obj/item/gun/magic/staff/honk, + /obj/item/gun/magic/staff/spellblade, + /obj/item/gun/magic/staff/locker, + /obj/item/gun/magic/staff/flying, + /obj/item/gun/magic/staff/babel, + /obj/item/singularityhammer, + /obj/item/mod/control/pre_equipped/enchanted, + /obj/item/runic_vendor_scepter, +)) + /obj/structure/mystery_box name = "mystery box" @@ -207,6 +233,12 @@ GLOBAL_LIST_INIT(mystery_box_extended, list( /obj/structure/mystery_box/tdome/generate_valid_types() valid_types = GLOB.mystery_box_guns + GLOB.mystery_box_extended +/obj/structure/mystery_box/wands + desc = "A wooden crate that seems equally magical and mysterious, capable of granting the user all kinds of different magical items." + +/obj/structure/mystery_box/wands/generate_valid_types() + valid_types = GLOB.mystery_magic + /// This represents the item that comes out of the box and is constantly changing before the box finishes deciding. Can probably be just an /atom or /movable. /obj/mystery_box_item diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index b1168302f68..48848df0fd5 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -94,7 +94,7 @@ moving = TRUE current_tube = tube - var/datum/move_loop/engine = SSmove_manager.force_move_dir(src, dir, 0, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/engine = DSmove_manager.force_move_dir(src, dir, 0, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(engine, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(before_pipe_transfer)) RegisterSignal(engine, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(after_pipe_transfer)) RegisterSignal(engine, COMSIG_QDELETING, PROC_REF(engine_finish)) diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 8165b35a256..02c714c25ff 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -40,6 +40,8 @@ var/mask_state = "lava-lightmask" /// The type for the preset fishing spot of this type of turf. var/fish_source_type = /datum/fish_source/lavaland + /// The color we use for our immersion overlay + var/immerse_overlay_color = "#a15e1b" /turf/open/lava/Initialize(mapload) . = ..() @@ -48,7 +50,7 @@ refresh_light() if(!smoothing_flags) update_appearance() - + AddElement(/datum/element/immerse, icon, icon_state, "immerse", immerse_overlay_color) /turf/open/lava/Destroy() for(var/mob/living/leaving_mob in contents) @@ -337,6 +339,7 @@ smoothing_groups = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_FLOOR_LAVA canSmoothWith = SMOOTH_GROUP_FLOOR_LAVA underfloor_accessibility = 2 //This avoids strangeness when routing pipes / wires along catwalks over lava + immerse_overlay_color = "#F98511" /turf/open/lava/smooth/lava_land_surface initial_gas_mix = LAVALAND_DEFAULT_ATMOS @@ -360,6 +363,7 @@ immunity_trait = TRAIT_SNOWSTORM_IMMUNE immunity_resistance_flags = FREEZE_PROOF lava_temperature = 100 + immerse_overlay_color = "#CD4C9F" /turf/open/lava/plasma/examine(mob/user) . = ..() diff --git a/code/game/world.dm b/code/game/world.dm index 53f3a0fe95d..a7391f2ab15 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -17,6 +17,7 @@ GLOBAL_VAR(restart_counter) * - world.init_byond_tracy() * - (Start native profiling) * - world.init_debugger() + * - SysMgr (all data systems) * - Master => * - config *unloaded * - (all subsystems) PreInit() @@ -84,6 +85,9 @@ GLOBAL_VAR(restart_counter) // Create the logger logger = new + // Initialize all the data systems + SysMgr = new + // THAT'S IT, WE'RE DONE, THE. FUCKING. END. Master = new diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm index 32e49cf2e73..fe62bb97d81 100644 --- a/code/modules/admin/verbs/adminevents.dm +++ b/code/modules/admin/verbs/adminevents.dm @@ -253,11 +253,11 @@ ADMIN_VERB(run_weather, R_FUN, "Run Weather", "Triggers specific weather on the ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a footnote to the roundstart command report.", ADMIN_CATEGORY_EVENTS) var/datum/command_footnote/command_report_footnote = new /datum/command_footnote() - SScommunications.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done. + DScommunications.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done. command_report_footnote.message = tgui_input_text(user, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.") if(!command_report_footnote.message) - SScommunications.block_command_report -= 1 + DScommunications.block_command_report -= 1 qdel(command_report_footnote) return @@ -266,8 +266,8 @@ ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a if(!command_report_footnote.signature) command_report_footnote.signature = "Classified" - SScommunications.command_report_footnotes += command_report_footnote - SScommunications.block_command_report-- + DScommunications.command_report_footnotes += command_report_footnote + DScommunications.block_command_report-- message_admins("[user] has added a footnote to the command report: [command_report_footnote.message], signed [command_report_footnote.signature]") @@ -276,5 +276,5 @@ ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a var/signature ADMIN_VERB(delay_command_report, R_FUN, "Delay Command Report", "Prevents the roundstart command report from being sent; or forces it to send it delayed.", ADMIN_CATEGORY_EVENTS) - SScommunications.block_command_report = !SScommunications.block_command_report - message_admins("[key_name_admin(user)] has [(SScommunications.block_command_report ? "delayed" : "sent")] the roundstart command report.") + DScommunications.block_command_report = !DScommunications.block_command_report + message_admins("[key_name_admin(user)] has [(DScommunications.block_command_report ? "delayed" : "sent")] the roundstart command report.") diff --git a/code/modules/admin/view_variables/debug_variable_appearance.dm b/code/modules/admin/view_variables/debug_variable_appearance.dm new file mode 100644 index 00000000000..9e92eba4605 --- /dev/null +++ b/code/modules/admin/view_variables/debug_variable_appearance.dm @@ -0,0 +1,101 @@ +/// Shows a header name on top when you investigate an appearance/image +/image/vv_get_header() + . = list() + var/icon_name = "[icon || "null"]
" + . += replacetext(icon_name, "icons/obj", "") // shortens the name. We know the path already. + if(icon) + . += icon_state ? "\"[icon_state]\"" : "(icon_state = null)" + +/// Makes nice short vv names for images +/image/debug_variable_value(name, level, datum/owner, sanitize, display_flags) + var/display_name = "[type]" + if("[src]" != "[type]") // If we have a name var, let's use it. + display_name = "[src] [type]" + + var/display_value + var/list/icon_file_name = splittext("[icon]", "/") + if(length(icon_file_name)) + display_value = icon_file_name[length(icon_file_name)] + else + display_value = "null" + + if(icon_state) + display_value = "[display_value]:[icon_state]" + + var/display_ref = get_vv_link_ref() + return "[display_name] ([display_value]) [display_ref]" + +/// Returns the ref string to use when displaying this image in the vv menu of something else +/image/proc/get_vv_link_ref() + return REF(src) + +// It is endlessly annoying to display /appearance directly for stupid byond reasons, so we copy everything we care about into a holder datum +// That we can override procs on and store other vars on and such. +/mutable_appearance/appearance_mirror + // So people can see where it came from + var/appearance_ref + // vis flags can't be displayed by mutable appearances cause it don't make sense as overlays, but appearances do carry them + // can't use the name either for byond reasons + var/_vis_flags + +// all alone at the end of the universe +GLOBAL_DATUM_INIT(pluto, /atom/movable, new /atom/movable(null)) + +// arg is actually an appearance, typed as mutable_appearance as closest mirror +/mutable_appearance/appearance_mirror/New(mutable_appearance/appearance_father) + . = ..() // /mutable_appearance/New() copies over all the appearance vars MAs care about by default + // We copy over our appearance onto an atom. This is done so we can read vars carried by but not accessible on appearances + GLOB.pluto.appearance = appearance_father + _vis_flags = GLOB.pluto.vis_flags + appearance_ref = REF(appearance_father) + +// This means if the appearance loses refs before a click it's gone, but that's consistent to other datums so it's fine +// Need to ref the APPEARANCE because we just free on our own, which sorta fucks this operation up you know? +/mutable_appearance/appearance_mirror/get_vv_link_ref() + return appearance_ref + +/mutable_appearance/appearance_mirror/can_vv_get(var_name) + var/static/datum/beloved = new() + if(beloved.vars.Find(var_name)) // If datums have it, get out + return FALSE + // If it is one of the two args on /image, yeet (I am sorry) + if(var_name == NAMEOF(src, realized_overlays)) + return FALSE + if(var_name == NAMEOF(src, realized_underlays)) + return FALSE + // Filtering out the stuff I know we don't care about + if(var_name == NAMEOF(src, x)) + return FALSE + if(var_name == NAMEOF(src, y)) + return FALSE + if(var_name == NAMEOF(src, z)) + return FALSE + // Could make an argument for these but I think they will just confuse people, so yeeet +#ifndef SPACEMAN_DMM // Spaceman doesn't believe in contents on appearances, sorry lads + if(var_name == NAMEOF(src, contents)) + return FALSE +#endif + if(var_name == NAMEOF(src, loc)) + return FALSE + if(var_name == NAMEOF(src, vis_contents)) + return FALSE + return ..() + +/mutable_appearance/appearance_mirror/vv_get_var(var_name) + // No editing for you + var/value = vars[var_name] + return "
  • (READ ONLY) [var_name] = [_debug_variable_value(var_name, value, 0, src, sanitize = TRUE, display_flags = NONE)]
  • " + +/mutable_appearance/appearance_mirror/vv_get_dropdown() + SHOULD_CALL_PARENT(FALSE) + + . = list() + VV_DROPDOWN_OPTION("", "---") + VV_DROPDOWN_OPTION(VV_HK_CALLPROC, "Call Proc") + VV_DROPDOWN_OPTION(VV_HK_MARK, "Mark Object") + VV_DROPDOWN_OPTION(VV_HK_TAG, "Tag Datum") + VV_DROPDOWN_OPTION(VV_HK_DELETE, "Delete") + VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player") + +/proc/get_vv_appearance(mutable_appearance/appearance) // actually appearance yadeeyada + return new /mutable_appearance/appearance_mirror(appearance) diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm index 8aea000a1a6..a4035acd014 100644 --- a/code/modules/admin/view_variables/debug_variables.dm +++ b/code/modules/admin/view_variables/debug_variables.dm @@ -30,6 +30,9 @@ // This is split into a seperate proc mostly to make errors that happen not break things too much /proc/_debug_variable_value(name, value, level, datum/owner, sanitize, display_flags) + if(isappearance(value)) + value = get_vv_appearance(value) + . = "DISPLAY_ERROR: ([value] [REF(value)])" // Make sure this line can never runtime if(isnull(value)) @@ -49,10 +52,6 @@ return "/icon ([value])" #endif - if(isappearance(value)) - var/image/actually_an_appearance = value - return "/appearance ([actually_an_appearance.icon])" - if(isfilter(value)) var/datum/filter_value = value return "/filter ([filter_value.type] [REF(filter_value)])" diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index b139ec9d488..37bf0911c60 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -1,7 +1,10 @@ +#define ICON_STATE_CHECKED 1 /// this dmi is checked. We don't check this one anymore. +#define ICON_STATE_NULL 2 /// this dmi has null-named icon_state, allowing it to show a sprite on vv editor. + ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the variables of a datum.", ADMIN_CATEGORY_DEBUG, datum/thing in world) user.debug_variables(thing) - // This is kept as a seperate proc because admins are able to show VV to non-admins + /client/proc/debug_variables(datum/thing in world) set category = "Debug" set name = "View Variables" @@ -18,6 +21,8 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the var/datum/asset/asset_cache_datum = get_asset_datum(/datum/asset/simple/vv) asset_cache_datum.send(usr) + if(isappearance(thing)) + thing = get_vv_appearance(thing) // this is /mutable_appearance/our_bs_subtype var/islist = islist(thing) || (!isdatum(thing) && hascall(thing, "Cut")) // Some special lists dont count as lists, but can be detected by if they have list procs if(!islist && !isdatum(thing)) return @@ -27,7 +32,7 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the var/icon/sprite var/hash - var/type = islist? /list : thing.type + var/type = islist ? /list : thing.type var/no_icon = FALSE if(isatom(thing)) @@ -36,8 +41,25 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the no_icon = TRUE else if(isimage(thing)) + // icon_state=null shows first image even if dmi has no icon_state for null name. + // This list remembers which dmi has null icon_state, to determine if icon_state=null should display a sprite + // (NOTE: icon_state="" is correct, but saying null is obvious) + var/static/list/dmi_nullstate_checklist = list() var/image/image_object = thing - sprite = icon(image_object.icon, image_object.icon_state) + var/icon_filename_text = "[image_object.icon]" // "icon(null)" type can exist. textifying filters it. + if(icon_filename_text) + if(image_object.icon_state) + sprite = icon(image_object.icon, image_object.icon_state) + + else // it means: icon_state="" + if(!dmi_nullstate_checklist[icon_filename_text]) + dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_CHECKED + if("" in icon_states(image_object.icon)) + // this dmi has nullstate. We'll allow "icon_state=null" to show image. + dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_NULL + + if(dmi_nullstate_checklist[icon_filename_text] == ICON_STATE_NULL) + sprite = icon(image_object.icon, image_object.icon_state) var/sprite_text if(sprite) @@ -285,3 +307,6 @@ datumrefresh=[refid];[HrefToken()]'>Refresh /client/proc/vv_update_display(datum/thing, span, content) src << output("[span]:[content]", "variables[REF(thing)].browser:replace_span") + +#undef ICON_STATE_CHECKED +#undef ICON_STATE_NULL diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index 099ed86044e..073d905646d 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -945,6 +945,8 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) var/prev_verbs /// Saved span state, used to restore after a voice change var/prev_span + /// The list of available voices + var/static/list/voice_options = list("normal", SPAN_ROBOT, SPAN_YELL, SPAN_CLOWN) /obj/machinery/ai_voicechanger/Initialize(mapload) . = ..() @@ -972,11 +974,12 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) /obj/machinery/ai_voicechanger/ui_data(mob/user) var/list/data = list() - data["voices"] = list("normal", SPAN_ROBOT, SPAN_YELL, SPAN_CLOWN) //manually adding this since i dont see other option + data["voices"] = voice_options data["loud"] = loudvoice data["on"] = changing_voice data["say_verb"] = say_verb data["name"] = say_name + data["selected"] = say_span || owner.speech_span return data /obj/machinery/ai_voicechanger/ui_act(action, params) @@ -1010,9 +1013,23 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) if(changing_voice) owner.radio.use_command = loudvoice if("look") - say_span = params["look"] + var/selection = params["look"] + if(isnull(selection)) + return FALSE + + var/found = FALSE + for(var/option in voice_options) + if(option == selection) + found = TRUE + break + if(!found) + stack_trace("User attempted to select an unavailable voice option") + return FALSE + + say_span = selection if(changing_voice) owner.speech_span = say_span + to_chat(usr, span_notice("Voice set to [selection].")) if("verb") say_verb = params["verb"] if(changing_voice) diff --git a/code/modules/antagonists/ninja/ninjaDrainAct.dm b/code/modules/antagonists/ninja/ninjaDrainAct.dm index c50df819e0d..403da2327a2 100644 --- a/code/modules/antagonists/ninja/ninjaDrainAct.dm +++ b/code/modules/antagonists/ninja/ninjaDrainAct.dm @@ -1,3 +1,8 @@ +/// Minimum amount of energy we can drain in a single drain action +#define NINJA_MIN_DRAIN (0.2 * STANDARD_CELL_CHARGE) +/// Maximum amount of energy we can drain in a single drain action +#define NINJA_MAX_DRAIN (0.4 * STANDARD_CELL_CHARGE) + /** * Atom level proc for space ninja's glove interactions. * @@ -26,7 +31,7 @@ var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(5, 0, loc) while(cell.charge> 0 && !maxcapacity) - drain = rand(hacking_module.mindrain, hacking_module.maxdrain) + drain = rand(NINJA_MIN_DRAIN, NINJA_MAX_DRAIN) if(cell.charge < drain) drain = cell.charge if(hacking_module.mod.get_charge() + drain > hacking_module.mod.get_max_charge()) @@ -62,7 +67,7 @@ var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(5, 0, loc) while(charge > 0 && !maxcapacity) - drain = rand(hacking_module.mindrain, hacking_module.maxdrain) + drain = rand(NINJA_MIN_DRAIN, NINJA_MAX_DRAIN) if(charge < drain) drain = charge if(hacking_module.mod.get_charge() + drain > hacking_module.mod.get_max_charge()) @@ -228,7 +233,7 @@ var/drain_total = 0 var/datum/powernet/wire_powernet = powernet while(!maxcapacity && src) - drain = (round((rand(hacking_module.mindrain, hacking_module.maxdrain))/2)) + drain = (round((rand(NINJA_MIN_DRAIN, NINJA_MAX_DRAIN))/2)) var/drained = 0 if(wire_powernet && do_after(ninja, 1 SECONDS, target = src, hidden = TRUE)) drained = min(drain, delayed_surplus()) @@ -264,7 +269,7 @@ var/drain_total = 0 if(get_charge()) while(cell.charge > 0 && !maxcapacity) - drain = rand(hacking_module.mindrain, hacking_module.maxdrain) + drain = rand(NINJA_MIN_DRAIN, NINJA_MAX_DRAIN) if(cell.charge < drain) drain = cell.charge if(hacking_module.mod.get_charge() + drain > hacking_module.mod.get_max_charge()) @@ -477,3 +482,6 @@ //FIRELOCKS// /obj/machinery/door/firedoor/ninjadrain_act(mob/living/carbon/human/ninja, obj/item/mod/module/hacker/hacking_module) crack_open() + +#undef NINJA_MIN_DRAIN +#undef NINJA_MAX_DRAIN diff --git a/code/modules/antagonists/nukeop/equipment/borgchameleon.dm b/code/modules/antagonists/nukeop/equipment/borgchameleon.dm index a2a072f02e2..9b536066843 100644 --- a/code/modules/antagonists/nukeop/equipment/borgchameleon.dm +++ b/code/modules/antagonists/nukeop/equipment/borgchameleon.dm @@ -1,5 +1,5 @@ -#define ACTIVATION_COST (300 KILO JOULES) -#define ACTIVATION_UP_KEEP (25 KILO WATTS) +#define ACTIVATION_COST (0.3 * STANDARD_CELL_CHARGE) +#define ACTIVATION_UP_KEEP (0.025 * STANDARD_CELL_RATE) /obj/item/borg_chameleon name = "cyborg chameleon projector" diff --git a/code/modules/antagonists/pirate/pirate_event.dm b/code/modules/antagonists/pirate/pirate_event.dm index e4a14182d0e..40cf038a214 100644 --- a/code/modules/antagonists/pirate/pirate_event.dm +++ b/code/modules/antagonists/pirate/pirate_event.dm @@ -42,7 +42,7 @@ priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", SSstation.announcer.get_rand_report_sound()) threat.answer_callback = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(pirates_answered), threat, chosen_gang, payoff, world.time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(spawn_pirates), threat, chosen_gang), RESPONSE_MAX_TIME) - SScommunications.send_message(threat, unique = TRUE) + DScommunications.send_message(threat, unique = TRUE) /proc/pirates_answered(datum/comm_message/threat, datum/pirate_gang/chosen_gang, payoff, initial_send_time) if(world.time > initial_send_time + RESPONSE_MAX_TIME) diff --git a/code/modules/antagonists/pirate/pirate_gangs.dm b/code/modules/antagonists/pirate/pirate_gangs.dm index d3bc0968a12..cb2f5fc1428 100644 --- a/code/modules/antagonists/pirate/pirate_gangs.dm +++ b/code/modules/antagonists/pirate/pirate_gangs.dm @@ -206,3 +206,25 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) response_too_late = "You were not ready then, and now that time has passed. We can only go forward, never back." response_not_enough = "You have insulted us, but there shall be no feud, only swift justice!" announcement_color = "purple" + +//medieval militia, from OUTER SPACE! +/datum/pirate_gang/medieval + name = "Medieval Warmongers" + + is_heavy_threat = TRUE + ship_template_id = "medieval" + ship_name_pool = "medieval_names" + + threat_title = "HOMAGE PAYMENT REQUEST" + threat_content = "SALUTATIONS, THIS IS %SHIPNAME AND WE ARE COLLECTING MONEY \ + FROM THE VASSALS IN OUR TERRITORY, YOU JUST SO HAPPEN TO BE IN IT TOO!! NORMALLY \ + WE SLAUGHTER WEAKLINGS LIKE YOU FOR TRESPASING ON OUR LAND, BUT WE ARE WILLING \ + TO WELCOME YOU INTO OUR SPACE IF YOU PAY %PAYOFF AS HOMAGE TO OUR LAW. BE WISE ON YOUR CHOICE!! \ + (send message. send message. why message not sent?)." + arrival_announcement = "I FIGURED OUT HOW TO FLY MY SHIP, WE WILL BE DOCKING NEXT TO YOU IN A MINUTE!!" + possible_answers = list("Please don't hurt me.","You are dumb, go larp somewhere else.") + + response_received = "THIS WILL SUFFICE, REMEMBER WHO OWNS YOU!!" + response_rejected = "FOOLISH DECISION, I'LL MAKE AN EXAMPLE OUT OF YOUR CARCASS!! (does anyone remember how to pilot our ship?)" + response_too_late = "YOU ARE ALREADY UNDER SIEGE YOU BUFFON, ARE YOU BRAINSICK OR IGNORANT?!!" + response_not_enough = "DO THINK OF ME AS A JESTER? YOU ARE DEAD MEAT!! (i forgot how to fly the ship, tarnation.)" diff --git a/code/modules/antagonists/pirate/pirate_outfits.dm b/code/modules/antagonists/pirate/pirate_outfits.dm index 4c73cac107f..15a3d4fe2dc 100644 --- a/code/modules/antagonists/pirate/pirate_outfits.dm +++ b/code/modules/antagonists/pirate/pirate_outfits.dm @@ -148,3 +148,34 @@ glasses = null suit = /obj/item/clothing/suit/jacket/oversized head = /obj/item/clothing/head/costume/crown + +/datum/outfit/pirate/medieval + name = "Medieval Warmonger" + + id = null + glasses = null + uniform = /obj/item/clothing/under/costume/gamberson/military + suit = /obj/item/clothing/suit/armor/vest/military + suit_store = /obj/item/spear/military + back = /obj/item/storage/backpack/satchel/leather + gloves = /obj/item/clothing/gloves/color/brown + head = /obj/item/clothing/head/helmet/military + mask = /obj/item/clothing/mask/balaclava + shoes = /obj/item/clothing/shoes/workboots + belt = /obj/item/claymore/shortsword + l_pocket = /obj/item/flashlight/flare/torch + +/datum/outfit/pirate/medieval/warlord + name = "Medieval Warlord" + + neck = /obj/item/bedsheet/pirate + suit = /obj/item/clothing/suit/armor/riot/knight/warlord + suit_store = null + back = /obj/item/fireaxe/boardingaxe + gloves = /obj/item/clothing/gloves/combat + head = /obj/item/clothing/head/helmet/knight/warlord + mask = /obj/item/clothing/mask/breath + shoes = /obj/item/clothing/shoes/bronze + belt = /obj/item/gun/magic/hook + l_pocket = /obj/item/tank/internals/emergency_oxygen + r_pocket = /obj/item/flashlight/lantern diff --git a/code/modules/antagonists/pirate/pirate_roles.dm b/code/modules/antagonists/pirate/pirate_roles.dm index 64baa724db1..78a3d3fd12a 100644 --- a/code/modules/antagonists/pirate/pirate_roles.dm +++ b/code/modules/antagonists/pirate/pirate_roles.dm @@ -191,3 +191,33 @@ /obj/effect/mob_spawn/ghost_role/human/pirate/lustrous/gunner rank = "Coruscant" + +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval + name = "\improper Improvised sleeper" + desc = "A body bag poked with holes, currently being used as a sleeping bag. Someone seems to be sleeping inside of it." + density = FALSE + you_are_text = "You were a nobody before, until you were given a sword and the opportunity to rise up in ranks. If you put some effort, you can make it big!" + flavour_text = "Raiding some cretins while engaging in bloodsport and violence? what a deal. Stay together and pillage everything!" + icon = 'icons/obj/medical/bodybag.dmi' + icon_state = "bodybag" + fluff_spawn = null + prompt_name = "a medieval warmonger" + outfit = /datum/outfit/pirate/medieval + rank = "Footsoldier" + +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval/special(mob/living/carbon/spawned_mob) + . = ..() + if(rank == "Footsoldier") + ADD_TRAIT(spawned_mob, TRAIT_NOGUNS, INNATE_TRAIT) + spawned_mob.AddComponent(/datum/component/unbreakable) + var/datum/action/cooldown/mob_cooldown/dash/dodge = new(spawned_mob) + dodge.Grant(spawned_mob) + +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval/warlord + rank = "Warlord" + outfit = /datum/outfit/pirate/medieval/warlord + +/obj/effect/mob_spawn/ghost_role/human/pirate/medieval/warlord/special(mob/living/carbon/spawned_mob) + . = ..() + spawned_mob.dna.add_mutation(/datum/mutation/human/hulk/superhuman) + spawned_mob.dna.add_mutation(/datum/mutation/human/gigantism) diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm index 04ebab73cbd..eaa1de48b58 100644 --- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm +++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm @@ -96,6 +96,9 @@ light_color = COLOR_SOFT_RED possible_destinations = "pirate_away;pirate_home;pirate_custom" +/obj/machinery/computer/shuttle/pirate/drop_pod + possible_destinations = "null" + /obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/pirate name = "pirate shuttle navigation computer" desc = "Used to designate a precise transit location for the pirate shuttle." diff --git a/code/modules/antagonists/space_dragon/carp_rift.dm b/code/modules/antagonists/space_dragon/carp_rift.dm index e003bf76e4d..8a74d4b63da 100644 --- a/code/modules/antagonists/space_dragon/carp_rift.dm +++ b/code/modules/antagonists/space_dragon/carp_rift.dm @@ -160,7 +160,7 @@ newcarp.faction = dragon.owner.current.faction.Copy() if(SPT_PROB(1.5, seconds_per_tick)) var/rand_dir = pick(GLOB.cardinals) - SSmove_manager.move_to(src, get_step(src, rand_dir), 1) + DSmove_manager.move_to(src, get_step(src, rand_dir), 1) return // Increase time trackers and check for any updated states. diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 44d00f3c170..222fcb39d16 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -362,7 +362,7 @@ qdel(src) return RegisterSignal(src, COMSIG_MOVABLE_CROSS_OVER, PROC_REF(check_teleport)) - SSmove_manager.move_towards(src, get_turf(whistle.whistler)) + DSmove_manager.move_towards(src, get_turf(whistle.whistler)) /// Check if anything the tornado crosses is the creator. /obj/effect/temp_visual/teleporting_tornado/proc/check_teleport(datum/source, atom/movable/crossed) diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm index 115e40ca595..d2e0bddd0dd 100644 --- a/code/modules/antagonists/xeno/xeno.dm +++ b/code/modules/antagonists/xeno/xeno.dm @@ -87,7 +87,7 @@ explanation_text = "Escape from captivity." /datum/objective/escape_captivity/check_completion() - if(!istype(get_area(owner), SScommunications.captivity_area)) + if(!istype(get_area(owner), DScommunications.captivity_area)) return TRUE /datum/objective/advance_hive @@ -146,7 +146,7 @@ if(!captive_alien || captive_alien.stat == DEAD) return CAPTIVE_XENO_DEAD - if(istype(get_area(captive_alien), SScommunications.captivity_area)) + if(istype(get_area(captive_alien), DScommunications.captivity_area)) return CAPTIVE_XENO_FAIL return CAPTIVE_XENO_PASS @@ -155,7 +155,7 @@ /mob/living/carbon/alien/mind_initialize() ..() if(!mind.has_antag_datum(/datum/antagonist/xeno)) - if(SScommunications.xenomorph_egg_delivered && istype(get_area(src), SScommunications.captivity_area)) + if(DScommunications.xenomorph_egg_delivered && istype(get_area(src), DScommunications.captivity_area)) mind.add_antag_datum(/datum/antagonist/xeno/captive) else mind.add_antag_datum(/datum/antagonist/xeno) diff --git a/code/modules/asset_cache/assets/tgui.dm b/code/modules/asset_cache/assets/tgui.dm index 9c79925602c..4b31d93e037 100644 --- a/code/modules/asset_cache/assets/tgui.dm +++ b/code/modules/asset_cache/assets/tgui.dm @@ -1,3 +1,23 @@ +// If you use a file(...) object, instead of caching the asset it will be loaded from disk every time it's requested. +// This is useful for development, but not recommended for production. +// And if TGS is defined, we're being run in a production environment. + +#ifdef TGS +/datum/asset/simple/tgui + keep_local_name = FALSE + assets = list( + "tgui.bundle.js" = "tgui/public/tgui.bundle.js", + "tgui.bundle.css" = "tgui/public/tgui.bundle.css", + ) + +/datum/asset/simple/tgui_panel + keep_local_name = FALSE + assets = list( + "tgui-panel.bundle.js" = "tgui/public/tgui-panel.bundle.js", + "tgui-panel.bundle.css" = "tgui/public/tgui-panel.bundle.css", + ) + +#else /datum/asset/simple/tgui keep_local_name = TRUE assets = list( @@ -11,3 +31,5 @@ "tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"), "tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"), ) + +#endif diff --git a/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm b/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm index bb45d1f8c1f..f7eaf5788c9 100644 --- a/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm +++ b/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm @@ -140,7 +140,7 @@ if(istype(W, /obj/item/electroadaptive_pseudocircuit)) var/obj/item/electroadaptive_pseudocircuit/P = W - if(!P.adapt_circuit(user, circuit_cost = 25 KILO JOULES)) + if(!P.adapt_circuit(user, circuit_cost = 0.025 * STANDARD_CELL_CHARGE)) return user.visible_message(span_notice("[user] fabricates a circuit and places it into [src]."), \ span_notice("You adapt an air alarm circuit and slot it into the assembly.")) diff --git a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm index 56ee3c6039d..2da9ac752b5 100644 --- a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm +++ b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm @@ -127,7 +127,7 @@ if(anchored) use_energy(power_to_use) else - cell.use(power_to_use KILO JOULES) + cell.use(power_to_use) /obj/machinery/electrolyzer/proc/call_reactions(datum/gas_mixture/env) for(var/reaction in GLOB.electrolyzer_reactions) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm index dc1c2d6282f..157cbae9af0 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm @@ -5,14 +5,12 @@ var/obj/machinery/atmospherics/components/unary/gas_connector /datum/gas_machine_connector/New(location, obj/machinery/connecting_machine = null, direction = SOUTH, gas_volume) - gas_connector = new(location) - connected_machine = connecting_machine if(!connected_machine) - QDEL_NULL(gas_connector) qdel(src) return + gas_connector = new(location) gas_connector.dir = connected_machine.dir gas_connector.airs[1].volume = gas_volume @@ -41,7 +39,8 @@ RegisterSignal(connected_machine, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(pre_move_connected_machine)) RegisterSignal(connected_machine, COMSIG_MOVABLE_MOVED, PROC_REF(moved_connected_machine)) RegisterSignal(connected_machine, COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, PROC_REF(wrenched_connected_machine)) - RegisterSignal(connected_machine, COMSIG_QDELETING, PROC_REF(deconstruct_connected_machine)) + RegisterSignal(connected_machine, COMSIG_OBJ_DECONSTRUCT, PROC_REF(deconstruct_connected_machine)) + RegisterSignal(connected_machine, COMSIG_QDELETING, PROC_REF(destroy_connected_machine)) /** * Unregister the signals previously registered @@ -51,7 +50,8 @@ COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_PRE_MOVE, COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, - COMSIG_QDELETING, + COMSIG_OBJ_DECONSTRUCT, + COMSIG_QDELETING )) /** @@ -82,12 +82,18 @@ */ /datum/gas_machine_connector/proc/deconstruct_connected_machine() SIGNAL_HANDLER + relocate_airs() + +/** + * Called when the machine has been destroyed + */ +/datum/gas_machine_connector/proc/destroy_connected_machine() + SIGNAL_HANDLER + disconnect_connector() SSair.stop_processing_machine(connected_machine) unregister_from_machine() - connected_machine = null - QDEL_NULL(gas_connector) qdel(src) /** diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 574daa2af3a..40258db903f 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -35,7 +35,12 @@ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works /obj/machinery/atmospherics/pipe/on_deconstruction(disassembled) - releaseAirToTurf() + //we delete the parent here so it initializes air_temporary for us. See /datum/pipeline/Destroy() which calls temporarily_store_air() + QDEL_NULL(parent) + + if(air_temporary) + var/turf/T = loc + T.assume_air(air_temporary) return ..() @@ -61,11 +66,6 @@ replace_pipenet(parent, new /datum/pipeline) return list(parent) -/obj/machinery/atmospherics/pipe/proc/releaseAirToTurf() - if(air_temporary) - var/turf/T = loc - T.assume_air(air_temporary) - /obj/machinery/atmospherics/pipe/return_air() if(air_temporary) return air_temporary diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index 75152798bba..6d4a8ad714a 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -483,7 +483,7 @@ var/energy_consumed = energy_factor * 250 * seconds_per_tick if(powered(AREA_USAGE_EQUIP, ignore_use_power = TRUE)) use_energy(energy_consumed, channel = AREA_USAGE_EQUIP) - else if(!internal_cell?.use(energy_consumed * 0.025 KILO JOULES)) + else if(!internal_cell?.use(energy_consumed * 0.025)) shielding_powered = FALSE SSair.start_processing_machine(src) investigate_log("shielding turned off due to power loss") diff --git a/code/modules/cards/deck/deck.dm b/code/modules/cards/deck/deck.dm index 54f8a5feba6..ccce3560249 100644 --- a/code/modules/cards/deck/deck.dm +++ b/code/modules/cards/deck/deck.dm @@ -11,7 +11,7 @@ hitsound = null attack_verb_continuous = list("attacks") attack_verb_simple = list("attack") - interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH|ALLOW_RESTING /// The amount of time it takes to shuffle var/shuffle_time = DECK_SHUFFLE_TIME /// Deck shuffling cooldown. diff --git a/code/modules/cards/singlecard.dm b/code/modules/cards/singlecard.dm index e03c5800346..0c228fbbb17 100644 --- a/code/modules/cards/singlecard.dm +++ b/code/modules/cards/singlecard.dm @@ -14,7 +14,7 @@ throw_range = 7 attack_verb_continuous = list("attacks") attack_verb_simple = list("attack") - interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH|ALLOW_RESTING /// Artistic style of the deck var/deckstyle = "nanotrasen" /// If the cards in the deck have different icon states (blank and CAS decks do not) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 4473f8663b2..4e0a38b2186 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -8,11 +8,11 @@ ///What level of bright light protection item has. var/flash_protect = FLASH_PROTECTION_NONE var/tint = 0 //Sets the item's level of visual impairment tint, normally set to the same as flash_protect - var/up = 0 //but separated to allow items to protect but not impair vision, like space helmets - var/visor_flags = 0 //flags that are added/removed when an item is adjusted up/down - var/visor_flags_inv = 0 //same as visor_flags, but for flags_inv - var/visor_flags_cover = 0 //same as above, but for flags_cover - ///What to toggle when toggled with weldingvisortoggle() + var/up = FALSE //but separated to allow items to protect but not impair vision, like space helmets + var/visor_flags = NONE //flags that are added/removed when an item is adjusted up/down + var/visor_flags_inv = NONE //same as visor_flags, but for flags_inv + var/visor_flags_cover = NONE //same as above, but for flags_cover + ///What to toggle when toggled with adjust_visor() var/visor_vars_to_toggle = VISOR_FLASHPROTECT | VISOR_TINT | VISOR_VISIONFLAGS | VISOR_INVISVIEW var/clothing_flags = NONE @@ -233,7 +233,9 @@ UnregisterSignal(user, COMSIG_MOVABLE_MOVED) for(var/trait in clothing_traits) REMOVE_CLOTHING_TRAIT(user, trait) - + if(iscarbon(user) && tint) + var/mob/living/carbon/carbon_user = user + carbon_user.update_tint() if(LAZYLEN(user_vars_remembered)) for(var/variable in user_vars_remembered) if(variable in user.vars) @@ -250,6 +252,9 @@ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(bristle), override = TRUE) for(var/trait in clothing_traits) ADD_CLOTHING_TRAIT(user, trait) + if(iscarbon(user) && tint) + var/mob/living/carbon/carbon_user = user + carbon_user.update_tint() if (LAZYLEN(user_vars_to_edit)) for(var/variable in user_vars_to_edit) if(variable in user.vars) @@ -465,18 +470,30 @@ BLIND // can't see anything female_clothing_icon = fcopy_rsc(female_clothing_icon) GLOB.female_clothing_icons[index] = female_clothing_icon -/obj/item/clothing/proc/weldingvisortoggle(mob/user) //proc to toggle welding visors on helmets, masks, goggles, etc. +/// Proc that adjusts the clothing item, used by things like breathing masks, welding helmets, welding goggles etc. +/obj/item/clothing/proc/adjust_visor(mob/living/user) if(!can_use(user)) return FALSE visor_toggling() - to_chat(user, span_notice("You adjust \the [src] [up ? "up" : "down"].")) + to_chat(user, span_notice("You adjust [src] [up ? "up" : "down"].")) - if(iscarbon(user)) - var/mob/living/carbon/C = user - C.head_update(src, forced = 1) update_item_action_buttons() + + if(user.is_holding(src)) + user.update_held_items() + return TRUE + if(up) + user.update_obscured_slots(visor_flags_inv) + user.update_clothing(slot_flags) + if(!iscarbon(user)) + return TRUE + var/mob/living/carbon/carbon_user = user + if(visor_vars_to_toggle & VISOR_TINT) + carbon_user.update_tint() + if((visor_flags & (MASKINTERNALS|HEADINTERNALS)) && carbon_user.invalid_internals()) + carbon_user.cutoff_internals() return TRUE /obj/item/clothing/proc/visor_toggling() //handles all the actual toggling of flags @@ -484,31 +501,17 @@ BLIND // can't see anything SEND_SIGNAL(src, COMSIG_CLOTHING_VISOR_TOGGLE, up) clothing_flags ^= visor_flags flags_inv ^= visor_flags_inv - flags_cover ^= initial(flags_cover) - icon_state = "[initial(icon_state)][up ? "up" : ""]" - if(visor_vars_to_toggle & VISOR_FLASHPROTECT) - flash_protect ^= initial(flash_protect) - if(visor_vars_to_toggle & VISOR_TINT) - tint ^= initial(tint) - -/obj/item/clothing/head/helmet/space/plasmaman/visor_toggling() //handles all the actual toggling of flags - up = !up - SEND_SIGNAL(src, COMSIG_CLOTHING_VISOR_TOGGLE, up) - clothing_flags ^= visor_flags - flags_inv ^= visor_flags_inv - icon_state = "[initial(icon_state)]" + flags_cover ^= visor_flags_cover if(visor_vars_to_toggle & VISOR_FLASHPROTECT) flash_protect ^= initial(flash_protect) if(visor_vars_to_toggle & VISOR_TINT) tint ^= initial(tint) + update_appearance() //most of the time the sprite changes /obj/item/clothing/proc/can_use(mob/user) - if(user && ismob(user)) - if(!user.incapacitated()) - return 1 - return 0 + return istype(user) && !user.incapacitated() -/obj/item/clothing/proc/_spawn_shreds() +/obj/item/clothing/proc/spawn_shreds() new /obj/effect/decal/cleanable/shreds(get_turf(src), name) /obj/item/clothing/atom_destruction(damage_flag) @@ -516,7 +519,7 @@ BLIND // can't see anything return ..() if(damage_flag == BOMB) //so the shred survives potential turf change from the explosion. - addtimer(CALLBACK(src, PROC_REF(_spawn_shreds)), 0.1 SECONDS) + addtimer(CALLBACK(src, PROC_REF(spawn_shreds)), 0.1 SECONDS) deconstruct(FALSE) if(damage_flag == CONSUME) //This allows for moths to fully consume clothing, rather than damaging it like other sources like brute var/turf/current_position = get_turf(src) diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index c44d5be4ef8..98bb6f56fc6 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -37,20 +37,17 @@ . += span_notice("Alt-click to toggle [p_their()] colors.") /obj/item/clothing/glasses/visor_toggling() - ..() + . = ..() + alternate_worn_layer = up ? ABOVE_BODY_FRONT_HEAD_LAYER : initial(alternate_worn_layer) // SKYRAT EDIT CHANGE - ORIGINAL : alternate_worn_layer = up ? ABOVE_BODY_FRONT_HEAD_LAYER : null if(visor_vars_to_toggle & VISOR_VISIONFLAGS) vision_flags ^= initial(vision_flags) if(visor_vars_to_toggle & VISOR_INVISVIEW) invis_view ^= initial(invis_view) -/obj/item/clothing/glasses/weldingvisortoggle(mob/user) +/obj/item/clothing/glasses/adjust_visor(mob/living/user) . = ..() - alternate_worn_layer = up ? ABOVE_BODY_FRONT_HEAD_LAYER : initial(alternate_worn_layer) // SKYRAT EDIT - ORIGINAL : alternate_worn_layer = up ? ABOVE_BODY_FRONT_HEAD_LAYER : null - if(. && user) + if(. && !user.is_holding(src) && (visor_vars_to_toggle & (VISOR_VISIONFLAGS|VISOR_INVISVIEW))) user.update_sight() - if(iscarbon(user)) - var/mob/living/carbon/carbon_user = user - carbon_user.head_update(src, forced = TRUE) //called when thermal glasses are emped. /obj/item/clothing/glasses/proc/thermal_overload() @@ -452,7 +449,11 @@ alternate_worn_layer = ABOVE_BODY_FRONT_HEAD_LAYER // SKYRAT EDIT - Just so it works until I make the change upstream /obj/item/clothing/glasses/welding/attack_self(mob/user) - weldingvisortoggle(user) + adjust_visor(user) + +/obj/item/clothing/glasses/welding/update_icon_state() + . = ..() + icon_state = "[initial(icon_state)][up ? "up" : ""]" /obj/item/clothing/glasses/welding/up/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm index deed90b1696..03b1cbb5bf7 100644 --- a/code/modules/clothing/gloves/boxing.dm +++ b/code/modules/clothing/gloves/boxing.dm @@ -6,6 +6,25 @@ equip_delay_other = 60 species_exception = list(/datum/species/golem) // now you too can be a golem boxing champion clothing_traits = list(TRAIT_CHUNKYFINGERS) + /// 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 + +/obj/item/clothing/gloves/boxing/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/extendohand_l, /datum/crafting_recipe/extendohand_r) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + + AddComponent(/datum/component/martial_art_giver, style_to_give) + +/obj/item/clothing/gloves/boxing/evil + name = "evil boxing gloves" + desc = "These strange gloves radiate an unsually evil aura." + greyscale_colors = "#21211f" + style_to_give = /datum/martial_art/boxing/evil /obj/item/clothing/gloves/boxing/green icon_state = "boxinggreen" @@ -18,3 +37,16 @@ /obj/item/clothing/gloves/boxing/yellow icon_state = "boxingyellow" greyscale_colors = "#d2a800" + +/obj/item/clothing/gloves/boxing/golden + name = "golden gloves" + desc = "The reigning champ of the station!" + icon_state = "boxinggold" + custom_materials = list(/datum/material/gold = SHEET_MATERIAL_AMOUNT*1) //LITERALLY GOLD + material_flags = MATERIAL_EFFECTS | MATERIAL_AFFECT_STATISTICS + equip_delay_other = 120 + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE + +/obj/item/clothing/gloves/boxing/golden/Initialize(mapload) + . = ..() + AddElement(/datum/element/skill_reward, /datum/skill/athletics) diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index c5b25166c09..4d9ec24e335 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -129,32 +129,21 @@ visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF ///Icon state of the welding visor. var/visor_state = "weldvisor" - var/visor_sprite_path //SKYRAT EDIT --- Lets the visor not smush the snout - -/obj/item/clothing/head/utility/hardhat/welding/Initialize(mapload) - . = ..() - update_appearance() /obj/item/clothing/head/utility/hardhat/welding/attack_self_secondary(mob/user, modifiers) - toggle_welding_screen(user) + adjust_visor(user) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /obj/item/clothing/head/utility/hardhat/welding/ui_action_click(mob/user, actiontype) if(istype(actiontype, /datum/action/item_action/toggle_welding_screen)) - toggle_welding_screen(user) + adjust_visor(user) return - return ..() -/obj/item/clothing/head/utility/hardhat/welding/proc/toggle_welding_screen(mob/living/user) - if(weldingvisortoggle(user)) - playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing - var/mob/living/carbon/carbon_user = user //SKYRAT EDIT --- Lets the visor not smush the snout - if(carbon_user.dna.species.mutant_bodyparts["snout"]) - visor_sprite_path = 'modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi' - else - visor_sprite_path = 'icons/mob/clothing/head/utility.dmi' //END SKYRAT EDIT - update_appearance() +/obj/item/clothing/head/utility/hardhat/welding/adjust_visor(mob/living/user) + . = ..() + if(.) + playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) /obj/item/clothing/head/utility/hardhat/welding/worn_overlays(mutable_appearance/standing, isinhands) . = ..() @@ -162,9 +151,7 @@ return if(!up) - // SKYRAT EDIT: ORIGINAL - . += mutable_appearance('icons/mob/clothing/head/utility.dmi', visor_state) - // SKYRAT EDIT: WELDING MUZZLES - . += mutable_appearance(visor_sprite_path, visor_state) + . += mutable_appearance(visor_sprite_path, visor_state) //SKYRAT EDIT CHANGE - WELDING MUZZLES - ORIGINAL: . += mutable_appearance('icons/mob/clothing/head/utility.dmi', visor_state) /obj/item/clothing/head/utility/hardhat/welding/update_overlays() . = ..() @@ -207,7 +194,8 @@ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF visor_flags_cover = NONE - flags_inv = HIDEEARS|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT + flags_inv = HIDEEARS|HIDEHAIR|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT + transparent_protection = HIDEMASK|HIDEEYES visor_flags_inv = NONE visor_state = "weldvisor_atmos" diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 236d94c39fa..0122cda3978 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -142,6 +142,7 @@ /obj/item/clothing/head/helmet/toggleable + visor_vars_to_toggle = NONE dog_fashion = null ///chat message when the visor is toggled down. var/toggle_message @@ -149,26 +150,11 @@ var/alt_toggle_message /obj/item/clothing/head/helmet/toggleable/attack_self(mob/user) + adjust_visor(user) + +/obj/item/clothing/head/helmet/toggleable/update_icon_state() . = ..() - if(.) - return - if(user.incapacitated() || !try_toggle()) - return - up = !up - flags_1 ^= visor_flags - flags_inv ^= visor_flags_inv - flags_cover ^= visor_flags_cover icon_state = "[initial(icon_state)][up ? "up" : ""]" - to_chat(user, span_notice("[up ? alt_toggle_message : toggle_message] \the [src].")) - - user.update_worn_head() - if(iscarbon(user)) - var/mob/living/carbon/carbon_user = user - carbon_user.head_update(src, forced = TRUE) - -///Attempt to toggle the visor. Returns true if it does the thing. -/obj/item/clothing/head/helmet/toggleable/proc/try_toggle() - return TRUE /obj/item/clothing/head/helmet/toggleable/riot name = "riot helmet" @@ -223,11 +209,18 @@ ///Looping sound datum for the siren helmet var/datum/looping_sound/siren/weewooloop -/obj/item/clothing/head/helmet/toggleable/justice/try_toggle() +/obj/item/clothing/head/helmet/toggleable/justice/adjust_visor(mob/living/user) if(!COOLDOWN_FINISHED(src, visor_toggle_cooldown)) return FALSE COOLDOWN_START(src, visor_toggle_cooldown, 2 SECONDS) - return TRUE + return ..() + +/obj/item/clothing/head/helmet/toggleable/justice/visor_toggling() + . = ..() + if(up) + weewooloop.start() + else + weewooloop.stop() /obj/item/clothing/head/helmet/toggleable/justice/Initialize(mapload) . = ..() @@ -237,13 +230,6 @@ QDEL_NULL(weewooloop) return ..() -/obj/item/clothing/head/helmet/toggleable/justice/attack_self(mob/user) - . = ..() - if(up) - weewooloop.start() - else - weewooloop.stop() - /obj/item/clothing/head/helmet/toggleable/justice/escape name = "alarm helmet" desc = "WEEEEOOO. WEEEEEOOO. STOP THAT MONKEY. WEEEOOOO." @@ -538,3 +524,48 @@ fire = 65 acid = 40 wound = 15 + +/obj/item/clothing/head/helmet/military + name = "Crude Helmet" + desc = "A cheaply made kettle helmet with an added faceplate to protect your eyes and mouth." + icon_state = "military" + inhand_icon_state = "knight_helmet" + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT + flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF + strip_delay = 80 + dog_fashion = null + armor_type = /datum/armor/helmet_military + +/datum/armor/helmet_military + melee = 45 + bullet = 25 + laser = 25 + energy = 25 + bomb = 25 + fire = 10 + acid = 50 + wound = 20 + +/obj/item/clothing/head/helmet/military/Initialize(mapload) + . = ..() + AddComponent(/datum/component/clothing_fov_visor, FOV_90_DEGREES) + +/obj/item/clothing/head/helmet/knight/warlord + name = "golden barbute helmet" + desc = "There is no man behind the helmet, only a terrible thought." + icon_state = "warlord" + inhand_icon_state = null + armor_type = /datum/armor/helmet_warlord + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEMASK|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT + flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF + slowdown = 0.2 + +/datum/armor/helmet_warlord + melee = 70 + bullet = 60 + laser = 70 + energy = 70 + bomb = 40 + fire = 50 + acid = 50 + wound = 30 diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index b300ff99179..4f5d377ddac 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -173,7 +173,7 @@ armor_type = /datum/armor/fedora_det_hat icon_state = "detective" inhand_icon_state = "det_hat" - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING /// Cooldown for retrieving precious candy corn on alt click var/candy_cooldown = 0 dog_fashion = /datum/dog_fashion/head/detective @@ -222,7 +222,7 @@ icon_state = "detective" inhand_icon_state = "det_hat" dog_fashion = /datum/dog_fashion/head/detective - interaction_flags_click = FORBID_TELEKINESIS_REACH + interaction_flags_click = FORBID_TELEKINESIS_REACH|ALLOW_RESTING ///prefix our phrases must begin with var/prefix = "go go gadget" ///an assoc list of phrase = item (like gun = revolver) diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 92517d4a7dd..3003e9a76ee 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -5,7 +5,7 @@ worn_icon = 'icons/mob/clothing/head/hats.dmi' icon_state = "cargosoft" inhand_icon_state = "greyscale_softcap" //todo wip - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /// For setting icon archetype var/soft_type = "cargo" /// If there is a suffix to append diff --git a/code/modules/clothing/head/welding.dm b/code/modules/clothing/head/welding.dm index bccb1d4524d..cb785447174 100644 --- a/code/modules/clothing/head/welding.dm +++ b/code/modules/clothing/head/welding.dm @@ -14,6 +14,7 @@ actions_types = list(/datum/action/item_action/toggle) visor_flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDESNOUT visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF + visor_vars_to_toggle = VISOR_FLASHPROTECT | VISOR_TINT resistance_flags = FIRE_PROOF clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT @@ -23,9 +24,9 @@ acid = 60 /obj/item/clothing/head/utility/welding/attack_self(mob/user) - weldingvisortoggle(user) + adjust_visor(user) -/obj/item/clothing/head/utility/welding/visor_toggling() +/obj/item/clothing/head/utility/welding/update_icon_state() . = ..() + icon_state = "[initial(icon_state)][up ? "up" : ""]" inhand_icon_state = "[initial(inhand_icon_state)][up ? "off" : ""]" - diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 23fc2272229..c1d29d65c86 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -7,9 +7,8 @@ slot_flags = ITEM_SLOT_MASK strip_delay = 40 equip_delay_other = 40 + visor_vars_to_toggle = NONE var/modifies_speech = FALSE - ///Whether the mask is pushed out of the food hole or not. - var/mask_adjusted = FALSE var/adjusted_flags = null ///Did we install a filtering cloth? var/has_filter = FALSE @@ -69,33 +68,17 @@ M.update_worn_mask() //Proc that moves gas/breath masks out of the way, disabling them and allowing pill/food consumption -/obj/item/clothing/mask/proc/adjustmask(mob/living/carbon/user) - if(user?.incapacitated()) - return - mask_adjusted = !mask_adjusted - if(!mask_adjusted) - icon_state = initial(icon_state) - clothing_flags |= visor_flags - flags_inv |= visor_flags_inv - flags_cover |= visor_flags_cover - to_chat(user, span_notice("You push \the [src] back into place.")) - slot_flags = initial(slot_flags) - else - icon_state += "_up" - to_chat(user, span_notice("You push \the [src] out of the way.")) - clothing_flags &= ~visor_flags - flags_inv &= ~visor_flags_inv - flags_cover &= ~visor_flags_cover +/obj/item/clothing/mask/visor_toggling(mob/living/user) + . = ..() + if(up) if(adjusted_flags) slot_flags = adjusted_flags - if(!istype(user)) - return - // Update the mob if it's wearing the mask. - if(user.wear_mask == src) - user.wear_mask_update(src, toggle_off = mask_adjusted) - if(loc == user) - // Update action button icon for adjusted mask, if someone is holding it. - user.update_mob_action_buttons() + else + slot_flags = initial(slot_flags) + +/obj/item/clothing/mask/update_icon_state() + . = ..() + icon_state = "[initial(icon_state)][up ? "_up" : ""]" /** * Proc called in lungs.dm to act if wearing a mask with filters, used to reduce the filters durability, return a changed gas mixture depending on the filter status diff --git a/code/modules/clothing/masks/bandana.dm b/code/modules/clothing/masks/bandana.dm index cd4b3980e55..c80ad733543 100644 --- a/code/modules/clothing/masks/bandana.dm +++ b/code/modules/clothing/masks/bandana.dm @@ -22,7 +22,7 @@ /obj/item/clothing/mask/bandana/examine(mob/user) . = ..() - if(mask_adjusted) + if(up) . += "Use in-hand to untie it to wear as a mask!" return if(slot_flags & ITEM_SLOT_NECK) @@ -32,25 +32,25 @@ . += "Alt-click to tie it up to wear on your neck!" /obj/item/clothing/mask/bandana/attack_self(mob/user) + adjust_visor(user) + +/obj/item/clothing/mask/bandana/adjust_visor(mob/living/user) if(slot_flags & ITEM_SLOT_NECK) to_chat(user, span_warning("You must undo [src] in order to push it into a hat!")) - return - //SKYRAT EDIT START: BANDANA HATS FOR MUTANTS + return FALSE + //SKYRAT EDIT ADDITION START: BANDANA HATS FOR MUTANTS if(slot_flags & ITEM_SLOT_HEAD) supports_variations_flags = NONE if(slot_flags & ITEM_SLOT_MASK) supports_variations_flags = initial(supports_variations_flags) - //SKYRAT EDIT END + //SKYRAT EDIT ADDITION END + return ..() - adjustmask(user) - -/obj/item/clothing/mask/bandana/adjustmask(mob/living/user) +/obj/item/clothing/mask/bandana/visor_toggling() . = ..() - if(mask_adjusted) + if(up) undyeable = TRUE else - inhand_icon_state = initial(inhand_icon_state) - worn_icon_state = initial(worn_icon_state) undyeable = initial(undyeable) /obj/item/clothing/mask/bandana/click_alt(mob/user) @@ -231,14 +231,13 @@ greyscale_config_inhand_left = /datum/greyscale_config/facescarf/inhands_left greyscale_config_inhand_right = /datum/greyscale_config/facescarf/inhands_right flags_1 = IS_PLAYER_COLORABLE_1 - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /obj/item/clothing/mask/facescarf/attack_self(mob/user) - adjustmask(user) - + adjust_visor(user) /obj/item/clothing/mask/facescarf/click_alt(mob/user) - adjustmask(user) + adjust_visor(user) return CLICK_ACTION_SUCCESS diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index 78ba0764b81..468b1272f86 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -10,7 +10,7 @@ actions_types = list(/datum/action/item_action/adjust) /obj/item/clothing/mask/balaclava/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) /obj/item/clothing/mask/floortilebalaclava name = "floortile balaclava" @@ -25,7 +25,7 @@ actions_types = list(/datum/action/item_action/adjust) /obj/item/clothing/mask/floortilebalaclava/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) /obj/item/clothing/mask/luchador name = "Luchador Mask" diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 0249f0b1321..73f91f7c6b8 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -12,7 +12,7 @@ flags_cover = MASKCOVERSMOUTH visor_flags_cover = MASKCOVERSMOUTH resistance_flags = NONE - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /datum/armor/mask_breath bio = 50 @@ -22,10 +22,10 @@ return OXYLOSS /obj/item/clothing/mask/breath/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) /obj/item/clothing/mask/breath/click_alt(mob/user) - adjustmask(user) + adjust_visor(user) return CLICK_ACTION_SUCCESS /obj/item/clothing/mask/breath/examine(mob/user) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 5b10f294000..a258eea7775 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -57,11 +57,11 @@ GLOBAL_LIST_INIT(clown_mask_options, list( cig?.equipped(equipee, slot) return ..() -/obj/item/clothing/mask/gas/adjustmask(mob/living/carbon/user) - if(isnull(cig)) - return ..() - balloon_alert(user, "there's a cig in the way!") - +/obj/item/clothing/mask/gas/adjust_visor(mob/living/user) + if(!isnull(cig)) + balloon_alert(user, "cig in the way!") + return FALSE + return ..() /obj/item/clothing/mask/gas/examine(mob/user) . = ..() @@ -219,6 +219,7 @@ GLOBAL_LIST_INIT(clown_mask_options, list( flags_cover = MASKCOVERSEYES visor_flags_inv = HIDEEYES visor_flags_cover = MASKCOVERSEYES + visor_vars_to_toggle = VISOR_FLASHPROTECT | VISOR_TINT resistance_flags = FIRE_PROOF /datum/armor/gas_welding @@ -228,10 +229,16 @@ GLOBAL_LIST_INIT(clown_mask_options, list( acid = 55 /obj/item/clothing/mask/gas/welding/attack_self(mob/user) - if(weldingvisortoggle(user)) + adjust_visor(user) + +/obj/item/clothing/mask/gas/welding/adjust_visor(mob/living/user) + . = ..() + if(.) playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) -/obj/item/clothing/mask/gas/welding/up +/obj/item/clothing/mask/gas/welding/update_icon_state() + . = ..() + icon_state = "[initial(icon_state)][up ? "up" : ""]" /obj/item/clothing/mask/gas/welding/up/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/masks/hailer.dm b/code/modules/clothing/masks/hailer.dm index 7c351d3ad34..cbfbc166cbc 100644 --- a/code/modules/clothing/masks/hailer.dm +++ b/code/modules/clothing/masks/hailer.dm @@ -124,7 +124,7 @@ GLOBAL_LIST_INIT(hailer_phrases, list( if(istype(action, /datum/action/item_action/halt)) halt() else - adjustmask(user) + adjust_visor(user) /obj/item/clothing/mask/gas/sechailer/attack_self() halt() diff --git a/code/modules/clothing/masks/surgical.dm b/code/modules/clothing/masks/surgical.dm index b754dc43014..4e8390edae7 100644 --- a/code/modules/clothing/masks/surgical.dm +++ b/code/modules/clothing/masks/surgical.dm @@ -15,4 +15,4 @@ bio = 100 /obj/item/clothing/mask/surgical/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index 785ec9e26f9..7c93019cb64 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -1,5 +1,5 @@ /// Charge per tick consumed by the thermal regulator -#define THERMAL_REGULATOR_COST (18 KILO JOULES) +#define THERMAL_REGULATOR_COST (0.018 * STANDARD_CELL_CHARGE) //Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together. // Meaning the the suit is defined directly after the corrisponding helmet. Just like below! @@ -58,7 +58,7 @@ equip_delay_other = 80 resistance_flags = NONE actions_types = list(/datum/action/item_action/toggle_spacesuit) - interaction_flags_click = NEED_DEXTERITY + interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING /// The default temperature setting var/temperature_setting = BODYTEMP_NORMAL /// If this is a path, this gets created as an object in Initialize. diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 02a54f194ea..bd20874f88d 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -88,26 +88,25 @@ . += span_notice("There's nothing placed on the helmet.") /obj/item/clothing/head/helmet/space/plasmaman/click_alt(mob/user) - toggle_welding_screen(user) - return CLICK_ACTION_SUCCESS + if(user.can_perform_action(src)) + adjust_visor(user) /obj/item/clothing/head/helmet/space/plasmaman/ui_action_click(mob/user, action) if(istype(action, /datum/action/item_action/toggle_welding_screen)) - toggle_welding_screen(user) + adjust_visor(user) return return ..() -/obj/item/clothing/head/helmet/space/plasmaman/proc/toggle_welding_screen(mob/living/user) - if(weldingvisortoggle(user)) - if(helmet_on) - to_chat(user, span_notice("Your helmet's torch can't pass through your welding visor!")) - helmet_on = FALSE - playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing - update_appearance() - else - playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing - update_appearance() +/obj/item/clothing/head/helmet/space/plasmaman/adjust_visor(mob/living/user) + . = ..() + if(!.) + return + if(helmet_on) + to_chat(user, span_notice("Your helmet's torch can't pass through your welding visor!")) + helmet_on = FALSE + playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing + update_appearance() /obj/item/clothing/head/helmet/space/plasmaman/update_icon_state() . = ..() @@ -116,7 +115,8 @@ /obj/item/clothing/head/helmet/space/plasmaman/update_overlays() . = ..() - . += visor_icon + if(!up) + . += visor_icon /obj/item/clothing/head/helmet/space/plasmaman/attackby(obj/item/hitting_item, mob/living/user) . = ..() diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index dcf6d502834..7367020ea04 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -712,3 +712,48 @@ fire = 40 acid = 50 wound = 30 + +/obj/item/clothing/suit/armor/vest/military + name = "Crude chestplate" + desc = "It may look rough, rusty and battered, but it's also made out of junk and uncomfortable to wear." + icon_state = "military" + inhand_icon_state = "armor" + dog_fashion = null + armor_type = /datum/armor/military + allowed = list( + /obj/item/banner, + /obj/item/claymore/shortsword, + /obj/item/nullrod, + /obj/item/spear, + /obj/item/gun/ballistic/bow + ) + +/datum/armor/military + melee = 45 + bullet = 25 + laser = 25 + energy = 25 + bomb = 25 + fire = 10 + acid = 50 + wound = 20 + +/obj/item/clothing/suit/armor/riot/knight/warlord + name = "golden plate armor" + desc = "This bulky set of armor is coated with a shiny layer of gold. It seems to almost reflect all light sources." + icon_state = "warlord" + inhand_icon_state = null + armor_type = /datum/armor/armor_warlord + w_class = WEIGHT_CLASS_BULKY + clothing_flags = THICKMATERIAL + slowdown = 0.8 + +/datum/armor/armor_warlord + melee = 70 + bullet = 60 + laser = 70 + energy = 70 + bomb = 40 + fire = 50 + acid = 50 + wound = 30 diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index b09aaa34104..bc9aad4198a 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -431,3 +431,17 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS|HEAD flags_inv = HIDEGLOVES|HIDESHOES|HIDEEARS|HIDEEYES|HIDEHAIR +/obj/item/clothing/under/costume/gamberson + name = "re-enactor's Gamberson" + desc = "A colorful set of clothes made to look like a medieval gamberson." + icon_state = "gamberson" + inhand_icon_state = null + female_sprite_flags = NO_FEMALE_UNIFORM + can_adjust = FALSE + +/obj/item/clothing/under/costume/gamberson/military + name = "swordsman's Gamberson" + desc = "A padded medieval gamberson. Has enough woolen layers to dull a strike from any small weapon." + armor_type = /datum/armor/clothing_under/rank_security + has_sensor = NO_SENSORS + diff --git a/code/modules/deathmatch/deathmatch_loadouts.dm b/code/modules/deathmatch/deathmatch_loadouts.dm index 341b85fb926..ae5f22975a0 100644 --- a/code/modules/deathmatch/deathmatch_loadouts.dm +++ b/code/modules/deathmatch/deathmatch_loadouts.dm @@ -21,6 +21,9 @@ user.set_species(/datum/species/human) for(var/datum/action/act as anything in granted_spells) var/datum/action/new_ability = new act(user) + if(istype(new_ability, /datum/action/cooldown/spell)) + var/datum/action/cooldown/spell/new_spell = new_ability + new_spell.spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC new_ability.Grant(user) /datum/outfit/deathmatch_loadout/naked @@ -173,6 +176,7 @@ name = "Deathmatch: Druid" display_name = "Druid" desc = "How can plants help you?" + species_override = /datum/species/pod l_hand = /obj/item/gun/ballistic/bow r_hand = /obj/item/ammo_casing/arrow @@ -240,7 +244,6 @@ l_pocket = /obj/item/reagent_containers/hypospray/combat r_pocket = /obj/item/reagent_containers/hypospray/medipen/penthrite l_hand = /obj/item/chainsaw - backpack_contents = list( /obj/item/storage/medkit/tactical, /obj/item/reagent_containers/hypospray/medipen/stimulants, @@ -274,7 +277,6 @@ l_pocket = /obj/item/melee/energy/sword/bananium r_pocket = /obj/item/shield/energy/bananium gloves = /obj/item/clothing/gloves/tackler/rocket - backpack_contents = list( /obj/item/reagent_containers/spray/waterflower = 1, /obj/item/instrument/bikehorn = 1, @@ -377,3 +379,167 @@ shoes = /obj/item/clothing/shoes/cowboy belt = /obj/item/storage/belt/holster/detective/full head = /obj/item/clothing/head/cowboy/brown + +/// wizards + +/datum/outfit/deathmatch_loadout/wizard + name = "Deathmatch: Wizard" + display_name = "Wizard" + desc = "It's wizard time, motherfucker! FIREBALL!!" + + l_hand = /obj/item/staff + uniform = /datum/outfit/wizard::uniform + suit = /datum/outfit/wizard::suit + head = /datum/outfit/wizard::head + shoes = /datum/outfit/wizard::shoes + granted_spells = list( + /datum/action/cooldown/spell/aoe/magic_missile, + /datum/action/cooldown/spell/forcewall, + /datum/action/cooldown/spell/jaunt/ethereal_jaunt, + ) + +/datum/outfit/deathmatch_loadout/wizard/pyro + name = "Deathmatch: Pyromancer" + display_name = "Pyromancer" + desc = "Burninating the station-side! Burninating all the wizards!" + + suit = /obj/item/clothing/suit/wizrobe/red + head = /obj/item/clothing/head/wizard/red + mask = /obj/item/clothing/mask/cigarette + granted_spells = list( + /datum/action/cooldown/spell/pointed/projectile/fireball, + /datum/action/cooldown/spell/smoke, + ) + +/datum/outfit/deathmatch_loadout/wizard/electro + name = "Deathmatch: Electromancer" + display_name = "Electromancer" + desc = "Batons are so last century." + + suit = /obj/item/clothing/suit/wizrobe/magusred + head = /obj/item/clothing/head/wizard/magus + granted_spells = list( + /datum/action/cooldown/spell/pointed/projectile/lightningbolt, + /datum/action/cooldown/spell/charged/beam/tesla, + ) + +/datum/outfit/deathmatch_loadout/wizard/necromancer + name = "Deathmatch: Necromancer" + display_name = "Necromancer" + desc = "I've got a BONE to pick- Yeah, sorry." + + species_override = /datum/species/skeleton + suit = /obj/item/clothing/suit/wizrobe/black + head = /obj/item/clothing/head/wizard/black + granted_spells = list( + /datum/action/cooldown/spell/touch/scream_for_me, + /datum/action/cooldown/spell/teleport/radius_turf/blink, + ) + +/datum/outfit/deathmatch_loadout/wizard/larp + name = "Deathmatch: LARPer" + display_name = "LARPer" + desc = "Lightning bolt! Lightning bolt! Lightning bolt!" + + l_hand = /obj/item/staff/stick + suit = /obj/item/clothing/suit/wizrobe/fake + head = /obj/item/clothing/head/wizard/fake + shoes = /obj/item/clothing/shoes/sandal + granted_spells = list( + /datum/action/cooldown/spell/conjure_item/spellpacket, + /datum/action/cooldown/spell/aoe/repulse/wizard, + ) + +/datum/outfit/deathmatch_loadout/wizard/chuuni + name = "Deathmatch: Chuuni" + display_name = "Chuunibyou" + desc = "Darkness blacker than black and darker than dark, I beseech thee..." + + l_hand = /obj/item/staff/broom + suit = /obj/item/clothing/suit/wizrobe/marisa + head = /obj/item/clothing/head/wizard/marisa + shoes = /obj/item/clothing/shoes/sneakers/marisa + granted_spells = list( + /datum/action/cooldown/spell/chuuni_invocations, + /datum/action/cooldown/spell/pointed/projectile/spell_cards, + ) + +/datum/outfit/deathmatch_loadout/wizard/battle + name = "Deathmatch: Battlemage" + display_name = "Battlemage" + desc = "Have you heard of the High Elves?" + + l_hand = /obj/item/mjollnir + suit = /obj/item/clothing/suit/wizrobe/magusblue + head = /obj/item/clothing/head/wizard/magus + granted_spells = list( + /datum/action/cooldown/spell/summonitem, + ) + +/datum/outfit/deathmatch_loadout/wizard/apprentice + name = "Deathmatch: Apprentice" + display_name = "Apprentice" + desc = "You feel severely under-leveled for this encounter..." + + l_hand = null + granted_spells = list( + /datum/action/cooldown/spell/charge, + ) + +/datum/outfit/deathmatch_loadout/wizard/gunmancer + name = "Deathmatch: Gunmancer" + display_name = "Gunmancer" + desc = "Magic is lame." + + l_hand = /obj/item/gun/ballistic/automatic/pistol/m1911 + suit = /obj/item/clothing/suit/wizrobe/tape + head = /obj/item/clothing/head/wizard/tape + shoes = /obj/item/clothing/shoes/jackboots + granted_spells = list( + /datum/action/cooldown/spell/conjure_item/infinite_guns/gun, + /datum/action/cooldown/spell/aoe/knock, + ) + +/datum/outfit/deathmatch_loadout/wizard/chaos + name = "Deathmatch: Chaos" + display_name = "Chaosmancer" + desc = "Hardcore Random Body ONLY!" + + l_hand = /obj/item/gun/magic/staff/chaos + uniform = /obj/item/clothing/under/color/rainbow + suit = /obj/item/clothing/suit/costume/hawaiian + head = /obj/item/clothing/head/wizard/red + shoes = /obj/item/clothing/shoes/sneakers/marisa + granted_spells = list( + /datum/action/cooldown/spell/rod_form, + /datum/action/cooldown/spell/conjure/the_traps, + ) + +/datum/outfit/deathmatch_loadout/wizard/clown + name = "Deathmatch: Clown" + display_name = "Funnymancer" + desc = "Honk NATH!" + + l_hand = /obj/item/gun/magic/staff/honk + uniform = /obj/item/clothing/under/rank/civilian/clown + suit = /obj/item/clothing/suit/chaplainsuit/clownpriest + head = /obj/item/clothing/head/chaplain/clownmitre + mask = /obj/item/clothing/mask/gas/clown_hat + back = /obj/item/storage/backpack/clown + shoes = /obj/item/clothing/shoes/clown_shoes + granted_spells = null + +/datum/outfit/deathmatch_loadout/wizard/monkey + name = "Deathmatch: Monkey" + display_name = "Monkeymancer" + desc = "Ook eek aaa ooo eee!" + + species_override = /datum/species/monkey + l_hand = /obj/item/food/grown/banana + uniform = null + suit = null + head = /obj/item/clothing/head/wizard + shoes = null + granted_spells = list( + /datum/action/cooldown/spell/conjure/simian, + ) diff --git a/code/modules/deathmatch/deathmatch_mapping.dm b/code/modules/deathmatch/deathmatch_mapping.dm index c3e10279363..95b9f5cf278 100644 --- a/code/modules/deathmatch/deathmatch_mapping.dm +++ b/code/modules/deathmatch/deathmatch_mapping.dm @@ -10,3 +10,6 @@ /obj/effect/landmark/deathmatch_player_spawn name = "Deathmatch Player Spawner" + +/area/deathmatch/teleport //Prevent access to cross-z teleportation in the map itself (no wands of safety/teleportation scrolls). Cordons should prevent same-z teleportations outside of the arena. + area_flags = UNIQUE_AREA | ABDUCTOR_PROOF | EVENT_PROTECTED | QUIET_LOGS diff --git a/code/modules/deathmatch/deathmatch_maps.dm b/code/modules/deathmatch/deathmatch_maps.dm index ebc3328e0ca..1abe92e7053 100644 --- a/code/modules/deathmatch/deathmatch_maps.dm +++ b/code/modules/deathmatch/deathmatch_maps.dm @@ -153,3 +153,25 @@ ) map_name = "backalley" key = "backalley" + +/datum/lazy_template/deathmatch/raginmages + name = "Ragin' Mages" + desc = "Greetings! We're the wizards of the wizard federation!" + max_players = 8 + automatic_gameend_time = 4 MINUTES // ill be surprised if this lasts more than two minutes + allowed_loadouts = list( + /datum/outfit/deathmatch_loadout/wizard, + /datum/outfit/deathmatch_loadout/wizard/pyro, + /datum/outfit/deathmatch_loadout/wizard/electro, + /datum/outfit/deathmatch_loadout/wizard/necromancer, + /datum/outfit/deathmatch_loadout/wizard/larp, + /datum/outfit/deathmatch_loadout/wizard/chuuni, + /datum/outfit/deathmatch_loadout/wizard/battle, + /datum/outfit/deathmatch_loadout/wizard/apprentice, + /datum/outfit/deathmatch_loadout/wizard/gunmancer, + /datum/outfit/deathmatch_loadout/wizard/monkey, + /datum/outfit/deathmatch_loadout/wizard/chaos, + /datum/outfit/deathmatch_loadout/wizard/clown, + ) + map_name = "ragin_mages" + key = "ragin_mages" diff --git a/code/modules/events/immovable_rod/immovable_rod.dm b/code/modules/events/immovable_rod/immovable_rod.dm index a4cc4d4d683..658d2d07bd8 100644 --- a/code/modules/events/immovable_rod/immovable_rod.dm +++ b/code/modules/events/immovable_rod/immovable_rod.dm @@ -45,9 +45,9 @@ RegisterSignal(src, COMSIG_ATOM_ENTERING, PROC_REF(on_entering_atom)) if(special_target) - SSmove_manager.home_onto(src, special_target) + DSmove_manager.home_onto(src, special_target) else - SSmove_manager.move_towards(src, real_destination) + DSmove_manager.move_towards(src, real_destination) /obj/effect/immovablerod/Destroy(force) UnregisterSignal(src, COMSIG_ATOM_ENTERING) @@ -113,7 +113,7 @@ return visible_message(span_danger("[src] phases into reality.")) - SSmove_manager.home_onto(src, special_target) + DSmove_manager.home_onto(src, special_target) if(loc == target_turf) complete_trajectory() @@ -264,7 +264,7 @@ * Stops your rod's automated movement. Sit... Stay... Good rod! */ /obj/effect/immovablerod/proc/sit_stay_good_rod() - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) /** * Allows your rod to release restraint level zero and go for a walk. @@ -278,7 +278,7 @@ /obj/effect/immovablerod/proc/go_for_a_walk(walkies_location = null) if(walkies_location) special_target = walkies_location - SSmove_manager.home_onto(src, special_target) + DSmove_manager.home_onto(src, special_target) return complete_trajectory() @@ -294,7 +294,7 @@ */ /obj/effect/immovablerod/proc/walk_in_direction(direction) destination_turf = get_edge_target_turf(src, direction) - SSmove_manager.move_towards(src, destination_turf) + DSmove_manager.move_towards(src, destination_turf) /** * Rod will push the tram to a landmark if it hits the tram from the front/back diff --git a/code/modules/events/shuttle_insurance.dm b/code/modules/events/shuttle_insurance.dm index 4fce9c556b8..fed6ad9af9e 100644 --- a/code/modules/events/shuttle_insurance.dm +++ b/code/modules/events/shuttle_insurance.dm @@ -43,7 +43,7 @@ /datum/round_event/shuttle_insurance/start() insurance_message = new("Shuttle Insurance", "Hey, pal, this is the [ship_name]. Can't help but notice you're rocking a wild and crazy shuttle there with NO INSURANCE! Crazy. What if something happened to it, huh?! We've done a quick evaluation on your rates in this sector and we're offering [insurance_evaluation] to cover for your shuttle in case of any disaster.", list("Purchase Insurance.","Reject Offer.")) insurance_message.answer_callback = CALLBACK(src, PROC_REF(answered)) - SScommunications.send_message(insurance_message, unique = TRUE) + DScommunications.send_message(insurance_message, unique = TRUE) /datum/round_event/shuttle_insurance/proc/answered() if(EMERGENCY_AT_LEAST_DOCKED) diff --git a/code/modules/explorer_drone/loot.dm b/code/modules/explorer_drone/loot.dm index 88cd5f38275..72773123968 100644 --- a/code/modules/explorer_drone/loot.dm +++ b/code/modules/explorer_drone/loot.dm @@ -175,7 +175,7 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index()) return if(LAZYACCESS(user.do_afters, "firelance")) return - if(!cell.use(200 KILO JOULES)) + if(!cell.use(0.2 * STANDARD_CELL_CHARGE)) to_chat(user,span_warning("[src] battery ran dry!")) return ADD_TRAIT(user, TRAIT_IMMOBILIZED, REF(src)) diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index 55509886a3a..0f1be89410a 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -15,7 +15,7 @@ #define MAX_MICROWAVE_DIRTINESS 100 /// For the wireless version, and display fluff -#define TIER_1_CELL_CHARGE_RATE (250 KILO JOULES) +#define TIER_1_CELL_CHARGE_RATE (0.25 * STANDARD_CELL_CHARGE) /obj/machinery/microwave name = "microwave oven" diff --git a/code/modules/food_and_drinks/machinery/oven.dm b/code/modules/food_and_drinks/machinery/oven.dm index ef9aac9a410..c997f349241 100644 --- a/code/modules/food_and_drinks/machinery/oven.dm +++ b/code/modules/food_and_drinks/machinery/oven.dm @@ -264,7 +264,7 @@ if(isnull(item.atom_storage)) return NONE - if(length(contents >= max_items)) + if(length(contents) >= max_items) balloon_alert(user, "it's full!") return ITEM_INTERACT_BLOCKING diff --git a/code/modules/food_and_drinks/recipes/food_mixtures.dm b/code/modules/food_and_drinks/recipes/food_mixtures.dm index bada60cd548..f7e72b6a48d 100644 --- a/code/modules/food_and_drinks/recipes/food_mixtures.dm +++ b/code/modules/food_and_drinks/recipes/food_mixtures.dm @@ -1,4 +1,5 @@ /datum/crafting_recipe/food + mass_craftable = TRUE /datum/crafting_recipe/food/on_craft_completion(mob/user, atom/result) SHOULD_CALL_PARENT(TRUE) diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm index a971b2b6a74..676c0cec7bb 100644 --- a/code/modules/hydroponics/fermenting_barrel.dm +++ b/code/modules/hydroponics/fermenting_barrel.dm @@ -163,3 +163,13 @@ /obj/structure/fermenting_barrel/gunpowder/Initialize(mapload) . = ..() reagents.add_reagent(/datum/reagent/gunpowder, 500) + +/// Medieval pirates can have a barrel as a treat +/obj/structure/fermenting_barrel/thermite + name = "thermite barrel" + desc = "A large wooden barrel for holding thermite. Use this to make a big flipping hole on walls." + can_open = FALSE + +/obj/structure/fermenting_barrel/thermite/Initialize(mapload) + . = ..() + reagents.add_reagent(/datum/reagent/thermite, 500) diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index bf52eb315d8..7cff6080f2b 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -589,7 +589,7 @@ var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc) pocell.icon = our_plant.icon // Just in case the plant icons get spread out in different files eventually, this trait won't cause error sprites (also yay downstreams) pocell.icon_state = our_plant.icon_state - pocell.maxcharge = our_seed.potency * 20 KILO JOULES + pocell.maxcharge = our_seed.potency * 0.02 * STANDARD_CELL_CHARGE // The secret of potato supercells! var/datum/plant_gene/trait/cell_charge/electrical_gene = our_seed.get_gene(/datum/plant_gene/trait/cell_charge) diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index 2055080710e..b31574bec33 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -19,6 +19,12 @@ if(isAdminGhostAI(accessor)) //Access can't stop the abuse return TRUE + //If the mob has the simple_access component with the requried access, we let them in. + var/attempted_access = SEND_SIGNAL(accessor, COMSIG_MOB_TRIED_ACCESS, src) + if(attempted_access & ACCESS_ALLOWED) + return TRUE + if(attempted_access & ACCESS_DISALLOWED) + return FALSE if(HAS_SILICON_ACCESS(accessor)) if(ispAI(accessor)) return FALSE @@ -28,9 +34,6 @@ if(onSyndieBase() && loc != accessor) return FALSE return TRUE //AI can do whatever it wants - //If the mob has the simple_access component with the requried access, we let them in. - else if(SEND_SIGNAL(accessor, COMSIG_MOB_TRIED_ACCESS, src) & ACCESS_ALLOWED) - return TRUE //If the mob is holding a valid ID, we let them in. get_active_held_item() is on the mob level, so no need to copypasta everywhere. else if(check_access(accessor.get_active_held_item()) || check_access(accessor.get_inactive_held_item())) return TRUE diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm b/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm index 150b4c5e44b..55fe9e77eac 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/biodome_winter.dm @@ -45,5 +45,5 @@ else if(isliving(hit_atom)) var/mob/living/hit_mob = hit_atom - SSmove_manager.stop_looping(hit_mob) //stops them mid pathing even if they're stunimmune + DSmove_manager.stop_looping(hit_mob) //stops them mid pathing even if they're stunimmune hit_mob.apply_status_effect(/datum/status_effect/ice_block_talisman, 3 SECONDS) diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm index 6ce6056b477..8dc9cec326d 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/necropolis_gate.dm @@ -262,7 +262,7 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate) var/static/list/give_turf_traits if(!give_turf_traits) - give_turf_traits = string_list(list(TRAIT_LAVA_STOPPED, TRAIT_CHASM_STOPPED)) + give_turf_traits = string_list(list(TRAIT_LAVA_STOPPED, TRAIT_CHASM_STOPPED, TRAIT_IMMERSE_STOPPED)) AddElement(/datum/element/give_turf_traits, give_turf_traits) /obj/structure/stone_tile/singularity_pull() diff --git a/code/modules/meteors/meteor_types.dm b/code/modules/meteors/meteor_types.dm index 2b37a55aaa4..d7a7dd14002 100644 --- a/code/modules/meteors/meteor_types.dm +++ b/code/modules/meteors/meteor_types.dm @@ -76,7 +76,7 @@ /obj/effect/meteor/proc/chase_target(atom/chasing, delay, home) if(!isatom(chasing)) return - var/datum/move_loop/new_loop = SSmove_manager.move_towards(src, chasing, delay, home, lifetime) + var/datum/move_loop/new_loop = DSmove_manager.move_towards(src, chasing, delay, home, lifetime) if(!new_loop) return diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 4845b0f9c00..5485ce72f22 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -85,20 +85,20 @@ starting_filter_type = /obj/item/gas_filter/plasmaman /obj/item/clothing/mask/gas/explorer/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) -/obj/item/clothing/mask/gas/explorer/adjustmask(mob/user) +/obj/item/clothing/mask/gas/explorer/visor_toggling() . = ..() // adjusted = out of the way = smaller = can fit in boxes - update_weight_class(mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL) - inhand_icon_state = mask_adjusted ? "[initial(inhand_icon_state)]_up" : initial(inhand_icon_state) - if(user) - user.update_held_items() + update_weight_class(up ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL) +/obj/item/clothing/mask/gas/explorer/update_icon_state() + . = ..() + inhand_icon_state = "[initial(inhand_icon_state)][up ? "_up" : ""]" /obj/item/clothing/mask/gas/explorer/examine(mob/user) . = ..() - if(mask_adjusted || w_class == WEIGHT_CLASS_SMALL) + if(up || w_class == WEIGHT_CLASS_SMALL) return . += span_notice("You could fit this into a box if you adjusted it.") @@ -107,7 +107,7 @@ /obj/item/clothing/mask/gas/explorer/folded/Initialize(mapload) . = ..() - adjustmask() + visor_toggling() /obj/item/clothing/suit/hooded/cloak icon = 'icons/obj/clothing/suits/armor.dmi' diff --git a/code/modules/mining/equipment/vent_pointer.dm b/code/modules/mining/equipment/vent_pointer.dm new file mode 100644 index 00000000000..4edab185597 --- /dev/null +++ b/code/modules/mining/equipment/vent_pointer.dm @@ -0,0 +1,19 @@ +/obj/item/pinpointer/vent + name = "ventpointer" + desc = "A handheld tracking device. It will locate and point to nearby vents. A bit unreliable though." + icon_state = "pinpointer_vent" + minimum_range = 14 //gotta use them eyes + +/obj/item/pinpointer/vent/scan_for_target() + var/closest_dist = INFINITY + + for(var/obj/structure/ore_vent/vent in SSore_generation.possible_vents) + if(vent.discovered || vent.tapped) + continue + if(vent.z != loc.z) + continue + + var/target_dist = get_dist(src, vent) + if(target_dist < closest_dist) + closest_dist = target_dist + target = vent diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 61318f63b92..2eaa1d95db9 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -152,7 +152,7 @@ materials = AddComponent( \ /datum/component/material_container, \ - SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ allowed_items = accepted_type \ diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index 97c3a90b78e..5096f00a770 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -20,7 +20,7 @@ materials = AddComponent( \ /datum/component/material_container, \ - SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ + DSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ container_signals = list( \ diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index f06c16e11de..1eec176a67d 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -429,10 +429,10 @@ var/obscured = NONE var/hidden_slots = NONE - for(var/obj/item/I in get_all_worn_items()) - hidden_slots |= I.flags_inv + for(var/obj/item/equipped_item in get_equipped_items()) + hidden_slots |= equipped_item.flags_inv if(transparent_protection) - hidden_slots |= I.transparent_protection + hidden_slots |= equipped_item.transparent_protection if(hidden_slots & HIDENECK) obscured |= ITEM_SLOT_NECK @@ -504,12 +504,8 @@ if(!I) to_chat(src, span_warning("You are not holding anything to equip!")) return - if (temporarilyRemoveItemFromInventory(I) && !QDELETED(I)) - if(I.equip_to_best_slot(src)) - return - if(put_in_active_hand(I)) - return - I.forceMove(drop_location()) + if(!QDELETED(I)) + I.equip_to_best_slot(src) //used in code for items usable by both carbon and drones, this gives the proper back slot for each mob.(defibrillator, backpack watertank, ...) /mob/proc/getBackSlot() diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index ccd4b0d617f..d98369294e0 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -104,7 +104,7 @@ GLOBAL_LIST_INIT(command_strings, list( AddElement(/datum/element/relay_attackers) RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(handle_loop_movement)) RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(after_attacked)) - RegisterSignal(src, COMSIG_OBJ_ALLOWED, PROC_REF(attempt_access)) + RegisterSignal(src, COMSIG_MOB_TRIED_ACCESS, PROC_REF(attempt_access)) ADD_TRAIT(src, TRAIT_NO_GLIDE, INNATE_TRAIT) GLOB.bots_list += src @@ -757,7 +757,7 @@ GLOBAL_LIST_INIT(command_strings, list( /mob/living/basic/bot/proc/attempt_access(mob/bot, obj/door_attempt) SIGNAL_HANDLER - return (door_attempt.check_access(access_card) ? COMPONENT_OBJ_ALLOW : COMPONENT_OBJ_DISALLOW) + return (door_attempt.check_access(access_card) ? ACCESS_ALLOWED : ACCESS_DISALLOWED) /mob/living/basic/bot/proc/generate_speak_list() return null diff --git a/code/modules/mob/living/basic/bots/bot_ai.dm b/code/modules/mob/living/basic/bots/bot_ai.dm index 16ca5200308..1c30f83b2e6 100644 --- a/code/modules/mob/living/basic/bots/bot_ai.dm +++ b/code/modules/mob/living/basic/bots/bot_ai.dm @@ -91,10 +91,9 @@ behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/manage_unreachable_list/perform(seconds_per_tick, datum/ai_controller/controller, list_key) - . = ..() if(!isnull(controller.blackboard[list_key])) controller.clear_blackboard_key(list_key) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/manage_unreachable_list/finish_action(datum/ai_controller/controller, succeeded) . = ..() @@ -123,7 +122,6 @@ /datum/ai_behavior/find_first_beacon_target /datum/ai_behavior/find_first_beacon_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/closest_distance = INFINITY var/mob/living/basic/bot/bot_pawn = controller.pawn var/atom/final_target @@ -138,19 +136,16 @@ final_target = beacon if(isnull(final_target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_BEACON_TARGET, final_target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_next_beacon_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/bot/bot_pawn = controller.pawn var/atom/final_target var/obj/machinery/navbeacon/prev_beacon = controller.blackboard[BB_PREVIOUS_BEACON_TARGET] if(QDELETED(prev_beacon)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/obj/machinery/navbeacon/beacon as anything in GLOB.navbeacons["[bot_pawn.z]"]) if(beacon.location == prev_beacon.codes[NAVBEACON_PATROL_NEXT]) @@ -159,10 +154,10 @@ if(isnull(final_target)) controller.clear_blackboard_key(BB_PREVIOUS_BEACON_TARGET) - finish_action(controller, FALSE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(BB_BEACON_TARGET, final_target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/travel_towards/beacon @@ -224,14 +219,11 @@ /datum/ai_behavior/salute_authority /datum/ai_behavior/salute_authority/perform(seconds_per_tick, datum/ai_controller/controller, target_key, salute_keys) - . = ..() if(!controller.blackboard_key_exists(target_key)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/list/salute_list = controller.blackboard[salute_keys] if(!length(salute_list)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/bot/bot_pawn = controller.pawn //special interaction if we are wearing a fedora var/obj/item/our_hat = (locate(/obj/item/clothing/head) in bot_pawn) @@ -239,8 +231,7 @@ salute_list += "tips [our_hat] at " bot_pawn.manual_emote(pick(salute_list) + " [controller.blackboard[target_key]]!") - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/salute_authority/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm b/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm index 537490c8431..a58a97c7274 100644 --- a/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm +++ b/code/modules/mob/living/basic/bots/cleanbot/cleanbot_ai.dm @@ -122,16 +122,14 @@ set_movement_target(controller, target) /datum/ai_behavior/execute_clean/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.UnarmedAttack(target, proximity_flag = TRUE) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/execute_clean/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() diff --git a/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm b/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm index d982869595b..2c614e003c8 100644 --- a/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm +++ b/code/modules/mob/living/basic/bots/hygienebot/hygienebot_ai.dm @@ -80,11 +80,10 @@ break if(isnull(found_target)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, found_target) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED @@ -112,17 +111,15 @@ var/mob/living/carbon/human/unclean_target = controller.blackboard[target_key] var/mob/living/basic/living_pawn = controller.pawn if(QDELETED(unclean_target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(living_pawn.loc == get_turf(unclean_target)) living_pawn.melee_attack(unclean_target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/frustration_count = controller.blackboard[BB_WASH_FRUSTRATION] controller.set_blackboard_key(BB_WASH_FRUSTRATION, frustration_count + 1) - finish_action(controller, FALSE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/wash_target/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm b/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm index 21f9ab29d1b..0a4520ad17b 100644 --- a/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm +++ b/code/modules/mob/living/basic/bots/medbot/medbot_ai.dm @@ -53,7 +53,6 @@ action_cooldown = 2 SECONDS /datum/ai_behavior/find_suitable_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, threshold, heal_type, mode_flags, access_flags) - . = ..() search_range = (mode_flags & MEDBOT_STATIONARY_MODE) ? 1 : initial(search_range) var/list/ignore_keys = controller.blackboard[BB_TEMPORARY_IGNORE_LIST] for(var/mob/living/carbon/human/treatable_target in oview(search_range, controller.pawn)) @@ -71,7 +70,10 @@ controller.set_if_can_reach(BB_PATIENT_TARGET, treatable_target, distance = BOT_PATIENT_PATH_LIMIT, bypass_add_to_blacklist = (search_range == 1)) break - finish_action(controller, controller.blackboard_key_exists(BB_PATIENT_TARGET)) + if(controller.blackboard_key_exists(BB_PATIENT_TARGET)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + else + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/find_suitable_patient/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -91,21 +93,18 @@ set_movement_target(controller, target) /datum/ai_behavior/tend_to_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, threshold, damage_type_healer, access_flags, is_stationary) - . = ..() var/mob/living/carbon/human/patient = controller.blackboard[target_key] if(QDELETED(patient) || patient.stat == DEAD) - finish_action(controller, FALSE, target_key, is_stationary) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(check_if_healed(patient, threshold, damage_type_healer, access_flags)) - finish_action(controller, TRUE, target_key, is_stationary, healed_target = TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/mob/living/basic/bot/bot_pawn = controller.pawn if(patient.stat >= HARD_CRIT && prob(5)) var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY] announcement?.announce(pick(controller.blackboard[BB_NEAR_DEATH_SPEECH])) bot_pawn.melee_attack(patient) - finish_action(controller, TRUE, target_key, is_stationary) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED // only clear the target if they get healed /datum/ai_behavior/tend_to_patient/finish_action(datum/ai_controller/controller, succeeded, target_key, is_stationary, healed_target = FALSE) @@ -171,11 +170,10 @@ speech_to_pick_from += MEDIBOT_VOICED_CHICKEN if(!length(speech_to_pick_from)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED announcement.announce(pick(speech_to_pick_from)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_planning_subtree/find_and_hunt_target/patients_in_crit target_key = BB_PATIENT_IN_CRIT @@ -202,18 +200,15 @@ behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/announce_patient/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key) - . = ..() var/mob/living/living_target = controller.blackboard[target_key] if(QDELETED(living_target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY] if(QDELETED(announcement)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/text_to_announce = "Medical emergency! [living_target] is in critical condition at [get_area(living_target)]!" announcement.announce(text_to_announce, controller.blackboard[BB_RADIO_CHANNEL]) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/announce_patient/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/drone/drone_tools.dm b/code/modules/mob/living/basic/drone/drone_tools.dm index 2350ec9cafb..1fa3aa7884b 100644 --- a/code/modules/mob/living/basic/drone/drone_tools.dm +++ b/code/modules/mob/living/basic/drone/drone_tools.dm @@ -48,7 +48,7 @@ name = "built-in crowbar" desc = "A crowbar built into your chassis." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "crowbar_cyborg" + icon_state = "toolkit_engiborg_crowbar" inhand_icon_state = "crowbar" item_flags = NO_MAT_REDEMPTION @@ -56,7 +56,7 @@ name = "built-in screwdriver" desc = "A screwdriver built into your chassis." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "screwdriver_cyborg" + icon_state = "toolkit_engiborg_screwdriver" inhand_icon_state = "screwdriver" item_flags = NO_MAT_REDEMPTION random_color = FALSE @@ -75,7 +75,7 @@ name = "built-in wrench" desc = "A wrench built into your chassis." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "wrench_cyborg" + icon_state = "toolkit_engiborg_wrench" inhand_icon_state = "wrench" item_flags = NO_MAT_REDEMPTION @@ -90,7 +90,7 @@ name = "built-in wirecutters" desc = "Wirecutters built into your chassis." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "wirecutters_cyborg" + icon_state = "toolkit_engiborg_cutters" inhand_icon_state = "cutters" item_flags = NO_MAT_REDEMPTION random_color = FALSE @@ -99,6 +99,6 @@ name = "built-in multitool" desc = "A multitool built into your chassis." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "multitool_cyborg" + icon_state = "toolkit_engiborg_multitool" item_flags = NO_MAT_REDEMPTION toolspeed = 0.5 diff --git a/code/modules/mob/living/basic/drone/visuals_icons.dm b/code/modules/mob/living/basic/drone/visuals_icons.dm index ec01d7d2d78..7a2122022f8 100644 --- a/code/modules/mob/living/basic/drone/visuals_icons.dm +++ b/code/modules/mob/living/basic/drone/visuals_icons.dm @@ -27,7 +27,7 @@ client.screen += internal_storage -/mob/living/basic/drone/update_worn_head() +/mob/living/basic/drone/update_worn_head(update_obscured = TRUE) remove_overlay(DRONE_HEAD_LAYER) if(head) @@ -44,7 +44,7 @@ apply_overlay(DRONE_HEAD_LAYER) -/mob/living/basic/drone/update_worn_mask() +/mob/living/basic/drone/update_worn_mask(update_obscured = TRUE) update_worn_head() /mob/living/basic/drone/regenerate_icons() diff --git a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm index 0c48a945381..b4d73ad5927 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm @@ -25,7 +25,6 @@ set_movement_target(controller, target) /datum/ai_behavior/enter_exit_hive/perform(seconds_per_tick, datum/ai_controller/controller, target_key, attack_key) - . = ..() var/obj/structure/beebox/current_home = controller.blackboard[target_key] var/mob/living/bee_pawn = controller.pawn var/atom/attack_target = controller.blackboard[attack_key] @@ -35,7 +34,7 @@ var/datum/callback/callback = CALLBACK(bee_pawn, TYPE_PROC_REF(/mob/living/basic/bee, handle_habitation), current_home) callback.Invoke() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/inhabit_hive behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH @@ -48,17 +47,15 @@ set_movement_target(controller, target) /datum/ai_behavior/inhabit_hive/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/structure/beebox/potential_home = controller.blackboard[target_key] var/mob/living/bee_pawn = controller.pawn if(!potential_home.habitable(bee_pawn)) //the house become full before we get to it - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/callback/callback = CALLBACK(bee_pawn, TYPE_PROC_REF(/mob/living/basic/bee, handle_habitation), potential_home) callback.Invoke() - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/inhabit_hive/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -158,19 +155,18 @@ set_movement_target(controller, target) /datum/ai_behavior/swirl_around_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED if(get_dist(target, living_pawn) > 1) set_movement_target(controller, target) - return + return AI_BEHAVIOR_DELAY if(!SPT_PROB(swirl_chance, seconds_per_tick)) - return + return AI_BEHAVIOR_DELAY var/list/possible_turfs = list() @@ -180,10 +176,11 @@ possible_turfs += possible_turf if(!length(possible_turfs)) - return + return AI_BEHAVIOR_DELAY if(isnull(controller.movement_target_source) || controller.movement_target_source == type) set_movement_target(controller, pick(possible_turfs)) + return AI_BEHAVIOR_DELAY /datum/pet_command/beehive diff --git a/code/modules/mob/living/basic/festivus_pole.dm b/code/modules/mob/living/basic/festivus_pole.dm index 90eca4b272d..838674c0811 100644 --- a/code/modules/mob/living/basic/festivus_pole.dm +++ b/code/modules/mob/living/basic/festivus_pole.dm @@ -1,3 +1,6 @@ +///how much charge we give off to cells around us when rubbed +#define FESTIVUS_RECHARGE_VALUE (0.075 * STANDARD_CELL_CHARGE) + /mob/living/basic/festivus name = "festivus pole" desc = "Serenity now... SERENITY NOW!" @@ -37,10 +40,6 @@ ai_controller = /datum/ai_controller/basic_controller/festivus_pole - ///how much charge we give off to cells around us when rubbed - var/recharge_value = 75 KILO JOULES - - /mob/living/basic/festivus/Initialize(mapload) . = ..() AddComponent(/datum/component/seethrough_mob) @@ -71,16 +70,16 @@ for(var/atom/affected in range(2, get_turf(src))) if(istype(affected, /obj/item/stock_parts/cell)) var/obj/item/stock_parts/cell/cell = affected - cell.give(recharge_value) + cell.give(FESTIVUS_RECHARGE_VALUE) cell.update_appearance() if(istype(affected, /mob/living/silicon/robot)) var/mob/living/silicon/robot/robot = affected if(robot.cell) - robot.cell.give(recharge_value) + robot.cell.give(FESTIVUS_RECHARGE_VALUE) if(istype(affected, /obj/machinery/power/apc)) var/obj/machinery/power/apc/apc_target = affected if(apc_target.cell) - apc_target.cell.give(recharge_value) + apc_target.cell.give(FESTIVUS_RECHARGE_VALUE) /datum/ai_planning_subtree/find_and_hunt_target/look_for_apcs hunting_behavior = /datum/ai_behavior/hunt_target/apcs @@ -118,3 +117,5 @@ return FALSE return can_see(source, dinner, radius) + +#undef FESTIVUS_RECHARGE_VALUE diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm index 20bcd8a69a1..8a900b0308a 100644 --- a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm @@ -48,13 +48,11 @@ /datum/ai_behavior/find_valid_teleport_location /datum/ai_behavior/find_valid_teleport_location/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range) - . = ..() var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] var/list/possible_turfs = list() if(QDELETED(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/turf/open/potential_turf in oview(hunt_range, target)) //we check for turfs around the target if(potential_turf.is_blocked_turf()) @@ -64,11 +62,10 @@ possible_turfs += potential_turf if(!length(possible_turfs)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(hunting_target_key, pick(possible_turfs)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/hunt_target/use_ability_on_target/demon_teleport hunt_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm index 725dcc09b5e..53d7e7191ef 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm @@ -38,8 +38,7 @@ /datum/ai_behavior/hunt_target/unarmed_attack_target/dragon_cannibalise/perform(seconds_per_tick, datum/ai_controller/controller, target_key, attack_key) var/mob/living/target = controller.blackboard[target_key] if(QDELETED(target) || target.stat != DEAD || target.pulledby) //we were too slow - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() /datum/ai_behavior/cannibalize/finish_action(datum/ai_controller/controller, succeeded, target_key) @@ -67,17 +66,14 @@ set_movement_target(controller, target) /datum/ai_behavior/sculpt_statue/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/atom/target = controller.blackboard[target_key] var/mob/living/basic/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.melee_attack(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/sculpt_statue/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -123,8 +119,6 @@ /datum/ai_behavior/set_target_tree /datum/ai_behavior/set_target_tree/perform(seconds_per_tick, datum/ai_controller/controller, tree_key) - . = ..() - var/mob/living_pawn = controller.pawn var/list/possible_trees = list() @@ -134,11 +128,10 @@ possible_trees += possible_tree if(!length(possible_trees)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(tree_key, pick(possible_trees)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/targeted_mob_ability/and_clear_target/burn_trees behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm index 0012aff294d..98025373b41 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm @@ -43,6 +43,5 @@ /datum/ai_behavior/targeted_mob_ability/brimbeam/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) var/mob/living/target = controller.blackboard[target_key] if (QDELETED(target) || !(get_dir(controller.pawn, target) in GLOB.cardinals) || get_dist(controller.pawn, target) > max_target_distance) - finish_action(controller, succeeded = FALSE, ability_key = ability_key, target_key = target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED return ..() diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm index 76c230520df..86ba1e00320 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm @@ -36,8 +36,7 @@ if (ismecha(target) || (isliving(target) && !target.has_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled))) var/datum/action/cooldown/using_action = controller.blackboard[BB_GOLIATH_TENTACLES] if (using_action?.IsAvailable()) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() /datum/ai_planning_subtree/targeted_mob_ability/goliath_tentacles @@ -67,20 +66,18 @@ var/scan_range = 3 /datum/ai_behavior/goliath_find_diggable_turf/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/turf/target_turf = controller.blackboard[target_key] if (is_valid_turf(target_turf)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/pawn = controller.pawn var/list/nearby_turfs = RANGE_TURFS(scan_range, pawn) var/turf/check_turf = pick(nearby_turfs) // This isn't an efficient search algorithm but we don't need it to be if (!is_valid_turf(check_turf)) - finish_action(controller, succeeded = FALSE) // Otherwise they won't perform idle wanderin - return + // Otherwise they won't perform idle wanderin + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, check_turf) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// Return true if this is a turf we can dig /datum/ai_behavior/goliath_find_diggable_turf/proc/is_valid_turf(turf/check_turf) @@ -112,13 +109,12 @@ set_movement_target(controller, target_turf) /datum/ai_behavior/goliath_dig/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/turf/target_turf = controller.blackboard[target_key] var/mob/living/basic/basic_mob = controller.pawn if(!basic_mob.CanReach(target_turf)) - return + return AI_BEHAVIOR_DELAY basic_mob.melee_attack(target_turf) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/goliath_dig/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm index be45879c64b..352f1b46b17 100644 --- a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm @@ -44,12 +44,9 @@ continue living_pawn.befriend(potential_friend) to_chat(potential_friend, span_nicegreen("[living_pawn] looks at you with endearing eyes!")) - finish_action(controller, TRUE) - return - - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_controller/basic_controller/gutlunch/gutlunch_baby diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index b80d5d6b9f7..c8e294f3e06 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -47,8 +47,8 @@ if (!is_vulnerable) controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, FALSE) if (!controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) - finish_action(controller = controller, succeeded = TRUE, target_key = target_key) // We don't want to clear our target - return + // We don't want to clear our target + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED return ..() /datum/ai_planning_subtree/flee_target/lobster @@ -72,8 +72,7 @@ if (!HAS_TRAIT(target, trait)) continue controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/living/us = controller.pawn if (us.pulling == target) @@ -132,14 +131,12 @@ set_movement_target(controller, current_target) /datum/ai_behavior/grab_fingers/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/atom/current_target = controller.blackboard[target_key] if (QDELETED(current_target)) - return + return AI_BEHAVIOR_DELAY var/mob/living/living_pawn = controller.pawn living_pawn.start_pulling(current_target) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /// How far we'll try to go before eating an arm #define FLEE_TO_RANGE 9 @@ -159,14 +156,18 @@ if (QDELETED(current_target)) set_movement_target(controller, get_turf(controller.pawn)) return - target_step_away(controller, current_target, target_key) + var/perform_flags = target_step_away(controller, current_target, target_key) + if (perform_flags & AI_BEHAVIOR_SUCCEEDED) + finish_action(controller, TRUE, target_key) + else if(perform_flags & AI_BEHAVIOR_FAILED) + finish_action(controller, FALSE, target_key) /// Find the next step to take away from the current target /datum/ai_behavior/hoard_fingers/proc/target_step_away(datum/ai_controller/controller, atom/current_target, target_key) var/turf/next_step = get_step_away(controller.pawn, current_target) if (!isnull(next_step) && !next_step.is_blocked_turf(exclude_mobs = TRUE)) set_movement_target(controller, next_step) - return + return NONE var/list/all_dirs = GLOB.alldirs.Copy() all_dirs -= get_dir(controller.pawn, next_step) all_dirs -= get_dir(controller.pawn, current_target) @@ -175,37 +176,37 @@ next_step = get_step(controller.pawn, dir) if (!isnull(next_step) && !next_step.is_blocked_turf(exclude_mobs = TRUE)) set_movement_target(controller, next_step) - return - finish_action(controller, succeeded = FALSE, target_key = target_key) - return + return NONE + return AI_BEHAVIOR_FAILED /datum/ai_behavior/hoard_fingers/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/current_patience = controller.blackboard[patience_key] + 1 if (current_patience >= MAX_LOBSTROSITY_PATIENCE) - eat_fingers(controller, target_key) - return + if(eat_fingers(controller, target_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(patience_key, current_patience) var/mob/living/living_pawn = controller.pawn if (isnull(living_pawn.pulling)) - finish_action(controller, succeeded = FALSE, target_key = target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/atom/current_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] if (QDELETED(current_target) || !can_see(controller.pawn, current_target, FLEE_TO_RANGE)) - eat_fingers(controller, target_key) - return - target_step_away(controller, current_target, target_key) + if(eat_fingers(controller, target_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + if(target_step_away(controller, current_target, target_key)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /// Finally consume those delicious digits /datum/ai_behavior/hoard_fingers/proc/eat_fingers(datum/ai_controller/controller, target_key) var/mob/living/basic/living_pawn = controller.pawn var/atom/fingers = controller.blackboard[target_key] if (QDELETED(fingers) || living_pawn.pulling != fingers) - finish_action(controller, succeeded = FALSE, target_key = target_key) - return + return AI_BEHAVIOR_FAILED living_pawn.melee_attack(fingers) - finish_action(controller, succeeded = TRUE, target_key = target_key) + return AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/hoard_fingers/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm index 50416693061..eeefc7a8b5c 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm @@ -117,15 +117,13 @@ GLOBAL_LIST_INIT(mook_commands, list( /datum/ai_behavior/find_village /datum/ai_behavior/find_village/perform(seconds_per_tick, datum/ai_controller/controller, village_key) - . = ..() var/obj/effect/landmark/home_marker = locate(/obj/effect/landmark/mook_village) in GLOB.landmarks_list if(isnull(home_marker)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(village_key, home_marker) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///explore the lands away from the village to look for ore /datum/ai_planning_subtree/wander_away_from_village @@ -190,8 +188,7 @@ GLOBAL_LIST_INIT(mook_commands, list( return return_turf /datum/ai_behavior/wander/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) - . = ..() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_planning_subtree/mine_walls/mook find_wall_behavior = /datum/ai_behavior/find_mineral_wall/mook @@ -367,23 +364,20 @@ GLOBAL_LIST_INIT(mook_commands, list( action_cooldown = 5 SECONDS /datum/ai_behavior/issue_commands/perform(seconds_per_tick, datum/ai_controller/controller, target_key, command_path) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/atom/target = controller.blackboard[target_key] if(isnull(target)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/pet_command/to_command = locate(command_path) in GLOB.mook_commands if(isnull(to_command)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/issue_command = pick(to_command.speech_commands) living_pawn.say(issue_command, forced = "controller") living_pawn._pointed(target) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///find an ore, only pick it up when a mook brings it close to us diff --git a/code/modules/mob/living/basic/minebots/minebot_ai.dm b/code/modules/mob/living/basic/minebots/minebot_ai.dm index 059048f761a..959049f957d 100644 --- a/code/modules/mob/living/basic/minebots/minebot_ai.dm +++ b/code/modules/mob/living/basic/minebots/minebot_ai.dm @@ -86,15 +86,13 @@ set_movement_target(controller, target) /datum/ai_behavior/repair_drone/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn living_pawn.say("REPAIRING [target]!") living_pawn.UnarmedAttack(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/repair_drone/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -119,20 +117,17 @@ action_cooldown = 2 MINUTES /datum/ai_behavior/send_sos_message/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/carbon/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(QDELETED(target) || is_station_level(target.z)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/turf/target_turf = get_turf(target) var/obj/item/implant/radio/radio_implant = locate(/obj/item/implant/radio) in living_pawn.contents if(!radio_implant) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/message = "ALERT, [target] in need of help at coordinates: [target_turf.x], [target_turf.y], [target_turf.z]!" radio_implant.radio.talk_into(living_pawn, message, RADIO_CHANNEL_SUPPLY) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/send_sos_message/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -182,11 +177,10 @@ minimum_distance = controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE] ? controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE] : initial(minimum_distance) var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, target_key, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn if(get_dist(living_pawn, target) <= minimum_distance) - finish_action(controller, target_key, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED ///mine walls if we are on automated mining mode /datum/ai_planning_subtree/minebot_mining/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) @@ -220,24 +214,20 @@ set_movement_target(controller, target) /datum/ai_behavior/minebot_mine_turf/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/turf/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(check_obstacles_in_path(controller, target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(!living_pawn.combat_mode) living_pawn.set_combat_mode(TRUE) living_pawn.RangedAttack(target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/minebot_mine_turf/proc/check_obstacles_in_path(datum/ai_controller/controller, turf/target) var/mob/living/source = controller.pawn diff --git a/code/modules/mob/living/basic/pets/cat/cat_ai.dm b/code/modules/mob/living/basic/pets/cat/cat_ai.dm index 7eff8582355..d6589d29b40 100644 --- a/code/modules/mob/living/basic/pets/cat/cat_ai.dm +++ b/code/modules/mob/living/basic/pets/cat/cat_ai.dm @@ -60,15 +60,13 @@ set_movement_target(controller, target) /datum/ai_behavior/enter_cat_home/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/obj/structure/cat_house/home = controller.blackboard[target_key] var/mob/living/basic/living_pawn = controller.pawn if(living_pawn == home.resident_cat || isnull(home.resident_cat)) living_pawn.melee_attack(home) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED - finish_action(controller, FALSE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/enter_cat_home/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -133,8 +131,7 @@ var/mob/living/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/mob/living/living_pawn = controller.pawn var/list/threaten_list = controller.blackboard[cries_key] @@ -149,7 +146,7 @@ loser_controller.set_blackboard_key(BB_BASIC_MOB_FLEE_TARGET, target) target.ai_controller.clear_blackboard_key(BB_TRESSPASSER_TARGET) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/territorial_struggle/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -191,19 +188,16 @@ set_movement_target(controller, target) /datum/ai_behavior/play_with_mouse/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/mouse/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED consume_chance = istype(target, /mob/living/basic/mouse/brown/tom) ? 5 : initial(consume_chance) if(prob(consume_chance)) target.splat() - finish_action(controller, TRUE, target_key) - return - finish_action(controller, FALSE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/play_with_mouse/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -272,22 +266,19 @@ set_movement_target(controller, target) /datum/ai_behavior/deliver_food_to_kitten/perform(seconds_per_tick, datum/ai_controller/controller, target_key, food_key) - . = ..() var/mob/living/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key, food_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn var/atom/movable/food = controller.blackboard[food_key] if(isnull(food) || !(food in living_pawn)) - finish_action(controller, FALSE, target_key, food_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED food.forceMove(get_turf(living_pawn)) - finish_action(controller, TRUE, target_key, food_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/deliver_food_to_kitten/finish_action(datum/ai_controller/controller, success, target_key, food_key) . = ..() diff --git a/code/modules/mob/living/basic/pets/cat/kitten_ai.dm b/code/modules/mob/living/basic/pets/cat/kitten_ai.dm index 15630c07838..b694235a39e 100644 --- a/code/modules/mob/living/basic/pets/cat/kitten_ai.dm +++ b/code/modules/mob/living/basic/pets/cat/kitten_ai.dm @@ -30,16 +30,15 @@ action_cooldown = 5 SECONDS /datum/ai_behavior/beacon_for_food/perform(seconds_per_tick, datum/ai_controller/controller, target_key, meows_key) - . = ..() var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn var/list/meowing_list = controller.blackboard[meows_key] if(length(meowing_list)) living_pawn.say(pick(meowing_list), forced = "ai_controller") living_pawn._pointed(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/beacon_for_food/finish_action(datum/ai_controller/controller, success, target_key) . = ..() diff --git a/code/modules/mob/living/basic/pets/orbie/orbie_ai.dm b/code/modules/mob/living/basic/pets/orbie/orbie_ai.dm index 854a0209464..92f433bd08a 100644 --- a/code/modules/mob/living/basic/pets/orbie/orbie_ai.dm +++ b/code/modules/mob/living/basic/pets/orbie/orbie_ai.dm @@ -65,18 +65,16 @@ set_movement_target(controller, target) /datum/ai_behavior/interact_with_playmate/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.manual_emote("plays with [target]!") living_pawn.spin(spintime = 4, speed = 1) living_pawn.ClickOn(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/interact_with_playmate/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -92,16 +90,14 @@ controller.queue_behavior(/datum/ai_behavior/relay_pda_message, BB_LAST_RECIEVED_MESSAGE) /datum/ai_behavior/relay_pda_message/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/mob/living/basic/living_pawn = controller.pawn var/text_to_say = controller.blackboard[target_key] if(isnull(text_to_say)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.say(text_to_say, forced = "AI controller") living_pawn.spin(spintime = 4, speed = 1) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/relay_pda_message/finish_action(datum/ai_controller/controller, success, target_key) . = ..() diff --git a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm index ccc3ef92f6e..b5b34e30cad 100644 --- a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm +++ b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parrot_perching.dm @@ -47,25 +47,21 @@ set_movement_target(controller, target) /datum/ai_behavior/perch_on_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/parrot/living_pawn = controller.pawn if(!ishuman(target)) living_pawn.start_perching(target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED if(!check_human_conditions(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED living_pawn.start_perching(target) - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/perch_on_target/proc/check_human_conditions(mob/living/living_human) if(living_human.stat == DEAD || LAZYLEN(living_human.buckled_mobs) >= living_human.max_buckled_mobs) diff --git a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm index d1488a60b3b..493d67cbca8 100644 --- a/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm +++ b/code/modules/mob/living/basic/pets/parrot/parrot_ai/parroting_action.dm @@ -45,6 +45,6 @@ speaking_pawn.say(modified_speech, forced = "AI Controller") if(speech_sound) playsound(speaking_pawn, speech_sound, 80, vary = TRUE) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED #undef HAS_CHANNEL_PREFIX diff --git a/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm b/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm index dc778b5816f..fb106809918 100644 --- a/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm +++ b/code/modules/mob/living/basic/pets/pet_cult/pet_cult_ai.dm @@ -100,25 +100,21 @@ set_movement_target(controller, target) /datum/ai_behavior/activate_rune/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/target = controller.blackboard[target_key] if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/team/cult/cult_team = controller.blackboard[BB_CULT_TEAM] var/mob/living/revive_mob = locate(/mob/living) in get_turf(target) if(isnull(revive_mob) || revive_mob.stat != DEAD || !(revive_mob.mind in cult_team.members)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/basic/living_pawn = controller.pawn living_pawn.melee_attack(target) - finish_action(controller, TRUE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/activate_rune/finish_action(datum/ai_controller/controller, success, target_key) . = ..() @@ -211,12 +207,10 @@ set_movement_target(controller, target) /datum/ai_behavior/drag_target_to_rune/perform(seconds_per_tick, datum/ai_controller/controller, target_key, cultist_key) - . = ..() var/mob/living/our_pawn = controller.pawn var/atom/cultist_target = controller.blackboard[cultist_key] if(isnull(cultist_target)) - finish_action(controller, FALSE, target_key, cultist_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/list/possible_dirs = GLOB.alldirs.Copy() possible_dirs -= get_dir(our_pawn, cultist_target) for(var/direction in possible_dirs) @@ -225,7 +219,7 @@ possible_dirs -= direction step(our_pawn, pick(possible_dirs)) our_pawn.stop_pulling() - finish_action(controller, TRUE, target_key, cultist_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/drag_target_to_rune/finish_action(datum/ai_controller/controller, success, target_key, cultist_key) diff --git a/code/modules/mob/living/basic/ruin_defender/flesh.dm b/code/modules/mob/living/basic/ruin_defender/flesh.dm index a6087f08589..6f46e690700 100644 --- a/code/modules/mob/living/basic/ruin_defender/flesh.dm +++ b/code/modules/mob/living/basic/ruin_defender/flesh.dm @@ -178,6 +178,6 @@ /mob/living/basic/living_limb_flesh/proc/wake_up(atom/limb) visible_message(span_warning("[src] begins flailing around!")) Shake(6, 6, 0.5 SECONDS) - ai_controller.set_ai_status(AI_STATUS_IDLE) + ai_controller.set_ai_status(AI_STATUS_ON) forceMove(limb.drop_location()) qdel(limb) diff --git a/code/modules/mob/living/basic/slime/ai/behaviours.dm b/code/modules/mob/living/basic/slime/ai/behaviours.dm index 0db592099bb..e573bd57354 100644 --- a/code/modules/mob/living/basic/slime/ai/behaviours.dm +++ b/code/modules/mob/living/basic/slime/ai/behaviours.dm @@ -1,10 +1,9 @@ /datum/ai_behavior/perform_change_slime_face /datum/ai_behavior/perform_change_slime_face/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/basic/slime/slime_pawn = controller.pawn if(!istype(slime_pawn)) - return + return AI_BEHAVIOR_DELAY var/current_mood = slime_pawn.current_mood @@ -23,7 +22,7 @@ slime_pawn.current_mood = new_mood slime_pawn.regenerate_icons() - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_hunt_target/find_slime_food diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index cf905de5dbf..ee2073987da 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -134,6 +134,8 @@ /// Gives the carp a list of weakrefs of destinations to try and travel between when it has nothing better to do /mob/living/basic/carp/proc/migrate_to(list/datum/weakref/migration_points) + ai_controller.can_idle = FALSE + ai_controller.set_ai_status(AI_STATUS_ON) // We need htem to actually walk to the station var/list/actual_points = list() for(var/datum/weakref/point_ref as anything in migration_points) var/turf/point_resolved = point_ref.resolve() diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm index 9e767bab3af..71017bd2207 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm @@ -21,8 +21,7 @@ if (QDELETED(using_action)) return ..() if (!controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETING] && using_action.IsAvailable()) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED return ..() /** diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm index 27fdb25ee22..9458877af7f 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm @@ -47,10 +47,8 @@ blackboard_points -= migration_point if(get_dist(controller.pawn, migration_point) > CARP_DESTINATION_SEARCH_RANGE) controller.set_blackboard_key(target_key, migration_point) - finish_action(controller, succeeded = TRUE) - return - - finish_action(controller, succeeded = FALSE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED #undef CARP_DESTINATION_SEARCH_RANGE #undef CARP_PORTAL_SEARCH_RANGE diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm index fc6997896b0..84b96ae3ce4 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm @@ -52,21 +52,19 @@ return controller.blackboard[ability_key] && controller.blackboard[target_key] /datum/ai_behavior/make_carp_rift/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) - . = ..() var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = controller.blackboard[ability_key] var/atom/target = controller.blackboard[target_key] if (!validate_target(controller, target, ability)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/turf/target_destination = find_target_turf(controller, target, ability) if (!target_destination) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED - var/result = ability.InterceptClickOn(controller.pawn, null, target_destination) - finish_action(controller, result, ability_key, target_key) + if(ability.InterceptClickOn(controller.pawn, null, target_destination)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /// Return true if your target is valid for the action /datum/ai_behavior/make_carp_rift/proc/validate_target(datum/ai_controller/controller, atom/target, datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability) diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm index 57ea39c94dd..f50fca8c559 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_behavior.dm @@ -1,14 +1,11 @@ /datum/ai_behavior/find_the_blind /datum/ai_behavior/find_the_blind/perform(seconds_per_tick, datum/ai_controller/controller, blind_key, threshold_key) - . = ..() - var/mob/living_pawn = controller.pawn var/list/blind_list = list() var/eye_damage_threshold = controller.blackboard[threshold_key] if(!eye_damage_threshold) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/mob/living/carbon/blind in oview(9, living_pawn)) var/obj/item/organ/internal/eyes/eyes = blind.get_organ_slot(ORGAN_SLOT_EYES) if(isnull(eyes)) @@ -18,11 +15,10 @@ blind_list += blind if(!length(blind_list)) - finish_action(controller, FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(blind_key, pick(blind_list)) - finish_action(controller, TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/heal_eye_damage behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH @@ -35,19 +31,16 @@ set_movement_target(controller, target) /datum/ai_behavior/heal_eye_damage/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/mob/living/carbon/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/obj/item/organ/internal/eyes/eyes = target.get_organ_slot(ORGAN_SLOT_EYES) var/datum/callback/callback = CALLBACK(living_pawn, TYPE_PROC_REF(/mob/living/basic/eyeball, heal_eye_damage), target, eyes) callback.Invoke() - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/heal_eye_damage/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() @@ -77,17 +70,18 @@ var/mob/living/target = controller.blackboard[target_key] if(QDELETED(ability) || QDELETED(target)) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/direction_to_compare = get_dir(target, controller.pawn) var/target_direction = target.dir if(direction_to_compare != target_direction) - finish_action(controller, FALSE, ability_key, target_key) - return + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/result = ability.InterceptClickOn(controller.pawn, null, target) - finish_action(controller, result, ability_key, target_key) + if(result == TRUE) + return AI_BEHAVIOR_INSTANT + else + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED /datum/ai_behavior/hunt_target/unarmed_attack_target/carrot hunt_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm index 28cffa4ed8e..7db7a8913fa 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm @@ -30,19 +30,16 @@ /datum/ai_behavior/relay_message/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - var/mob/living/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(QDELETED(target)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/message_relayed = "" for(var/i in 1 to length_of_message) message_relayed += prob(50) ? "1" : "0" living_pawn.say(message_relayed, forced = "AI Controller") - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/relay_message/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm index 8682c8028e3..20f6ce4baf0 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm @@ -13,19 +13,17 @@ var/scan_range = 3 /datum/ai_behavior/find_unwebbed_turf/perform(seconds_per_tick, datum/ai_controller/controller) - . = ..() var/mob/living/spider = controller.pawn var/atom/current_target = controller.blackboard[target_key] if (current_target && !(locate(/obj/structure/spider/stickyweb) in current_target)) - finish_action(controller, succeeded = FALSE) // Already got a target - return + // Already got a target + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.clear_blackboard_key(target_key) var/turf/our_turf = get_turf(spider) if (is_valid_web_turf(our_turf, spider)) controller.set_blackboard_key(target_key, our_turf) - finish_action(controller, succeeded = TRUE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/list/turfs_by_range = list() for (var/i in 1 to scan_range) @@ -41,11 +39,10 @@ final_turfs = turfs_by_range[turf_list] break if (!length(final_turfs)) - finish_action(controller, succeeded = FALSE) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED controller.set_blackboard_key(target_key, pick(final_turfs)) - finish_action(controller, succeeded = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_unwebbed_turf/proc/is_valid_web_turf(turf/target_turf, mob/living/spider) if (locate(/obj/structure/spider/stickyweb) in target_turf) @@ -82,9 +79,10 @@ return ..() /datum/ai_behavior/spin_web/perform(seconds_per_tick, datum/ai_controller/controller, action_key, target_key) - . = ..() var/datum/action/cooldown/web_action = controller.blackboard[action_key] - finish_action(controller, succeeded = web_action?.Trigger(), action_key = action_key, target_key = target_key) + if(web_action?.Trigger()) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED /datum/ai_behavior/spin_web/finish_action(datum/ai_controller/controller, succeeded, action_key, target_key) controller.clear_blackboard_key(target_key) diff --git a/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm b/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm index 7b6bf6c8399..9710421b408 100644 --- a/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm +++ b/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm @@ -57,14 +57,13 @@ return ismovable(target) && isturf(target.loc) && ismob(controller.pawn) /datum/ai_behavior/face_target_or_face_initial/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() var/atom/movable/target = controller.blackboard[target_key] var/mob/living/we = controller.pawn if(isnull(target) || get_dist(we, target) > 8) we.dir = controller.blackboard[BB_STARTING_DIRECTION] - finish_action(controller, TRUE) - else - we.face_atom(target) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + we.face_atom(target) + return AI_BEHAVIOR_DELAY /mob/living/basic/statue/mannequin/suspicious name = "mannequin?" diff --git a/code/modules/mob/living/basic/trader/trader_ai.dm b/code/modules/mob/living/basic/trader/trader_ai.dm index 5f447ab3229..d79a12a2d29 100644 --- a/code/modules/mob/living/basic/trader/trader_ai.dm +++ b/code/modules/mob/living/basic/trader/trader_ai.dm @@ -61,19 +61,15 @@ return !QDELETED(target) /datum/ai_behavior/setup_shop/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - . = ..() - //We lost track of our costumer or our ability, abort if(!controller.blackboard_key_exists(target_key) || !controller.blackboard_key_exists(BB_SETUP_SHOP)) - finish_action(controller, FALSE, target_key) - return + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/datum/action/setup_shop/shop = controller.blackboard[BB_SETUP_SHOP] shop.Trigger() controller.clear_blackboard_key(BB_FIRST_CUSTOMER) - - finish_action(controller, TRUE, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/idle_behavior/idle_random_walk/not_while_on_target/trader target_key = BB_SHOP_SPOT diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 94a3d70372b..933e6cb86d6 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -116,18 +116,32 @@ Des: Removes all infected images from the alien. span_alertalien("[src] begins to twist and contort!"), span_noticealien("You begin to evolve!"), ) + new_xeno.setDir(dir) - if(numba && unique_name) - new_xeno.numba = numba - new_xeno.set_name() - if(!alien_name_regex.Find(name)) - new_xeno.name = name - new_xeno.real_name = real_name + new_xeno.change_name(name, real_name, numba) + if(mind) mind.name = new_xeno.real_name mind.transfer_to(new_xeno) + 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) + 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 + return + + if(!unique_name) + return + + if(old_number != 0) + numba = old_number + name = initial(name) // prevent chicanery like two different numerical identifiers tied to the same mob + + set_name() + /mob/living/carbon/alien/can_hold_items(obj/item/I) return (I && (I.item_flags & XENOMORPH_HOLDABLE || ISADVANCEDTOOLUSER(src)) && ..()) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index f32e67116b2..9490ea741f0 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -658,12 +658,8 @@ */ /mob/living/carbon/proc/update_tint() var/tint = 0 - if(isclothing(head)) - tint += head.tint - if(isclothing(wear_mask)) - tint += wear_mask.tint - if(isclothing(glasses)) - tint += glasses.tint + for(var/obj/item/clothing/worn_item in get_equipped_items()) + tint += worn_item.tint var/obj/item/organ/internal/eyes/eyes = get_organ_slot(ORGAN_SLOT_EYES) if(eyes) @@ -1260,35 +1256,35 @@ update_worn_back(0) . = TRUE - if(head?.wash(clean_types)) - update_worn_head() - . = TRUE - // Check and wash stuff that can be covered var/obscured = check_obscured_slots() + if(!(obscured & ITEM_SLOT_HEAD) && head?.wash(clean_types)) + update_worn_head() + . = TRUE + // If the eyes are covered by anything but glasses, that thing will be covering any potential glasses as well. - if(glasses && is_eyes_covered(ITEM_SLOT_MASK|ITEM_SLOT_HEAD) && glasses.wash(clean_types)) + if(is_eyes_covered(ITEM_SLOT_MASK|ITEM_SLOT_HEAD) && glasses?.wash(clean_types)) update_worn_glasses() . = TRUE - if(wear_mask && !(obscured & ITEM_SLOT_MASK) && wear_mask.wash(clean_types)) + if(!(obscured & ITEM_SLOT_MASK) && wear_mask?.wash(clean_types)) update_worn_mask() . = TRUE - if(ears && !(obscured & ITEM_SLOT_EARS) && ears.wash(clean_types)) - update_inv_ears() + if(!(obscured & ITEM_SLOT_EARS) && ears?.wash(clean_types)) + update_worn_ears() . = TRUE - if(wear_neck && !(obscured & ITEM_SLOT_NECK) && wear_neck.wash(clean_types)) + if(!(obscured & ITEM_SLOT_NECK) && wear_neck?.wash(clean_types)) update_worn_neck() . = TRUE - if(shoes && !(obscured & ITEM_SLOT_FEET) && shoes.wash(clean_types)) + if(!(obscured & ITEM_SLOT_FEET) && shoes?.wash(clean_types)) update_worn_shoes() . = TRUE - if(gloves && !(obscured & ITEM_SLOT_GLOVES) && gloves.wash(clean_types)) + if(!(obscured & ITEM_SLOT_GLOVES) && gloves?.wash(clean_types)) update_worn_gloves() . = TRUE diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 2a17403a83e..c5862a95e12 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -1,38 +1,7 @@ -/mob/living/carbon/human/update_clothing(slot_flags) - if(slot_flags & ITEM_SLOT_BACK) - update_worn_back() - if(slot_flags & ITEM_SLOT_MASK) - update_worn_mask() - if(slot_flags & ITEM_SLOT_NECK) - update_worn_neck() - if(slot_flags & ITEM_SLOT_HANDCUFFED) - update_worn_handcuffs() - if(slot_flags & ITEM_SLOT_LEGCUFFED) - update_worn_legcuffs() - if(slot_flags & ITEM_SLOT_BELT) - update_worn_belt() - if(slot_flags & ITEM_SLOT_ID) - update_worn_id() - if(slot_flags & ITEM_SLOT_EARS) - update_inv_ears() - if(slot_flags & ITEM_SLOT_EYES) - update_worn_glasses() - if(slot_flags & ITEM_SLOT_GLOVES) - update_worn_gloves() - if(slot_flags & ITEM_SLOT_HEAD) - update_worn_head() - if(slot_flags & ITEM_SLOT_FEET) - update_worn_shoes() - if(slot_flags & ITEM_SLOT_OCLOTHING) - update_worn_oversuit() - if(slot_flags & ITEM_SLOT_ICLOTHING) - update_worn_undersuit() - if(slot_flags & ITEM_SLOT_SUITSTORE) - update_suit_storage() - if(slot_flags & (ITEM_SLOT_LPOCKET|ITEM_SLOT_RPOCKET)) - update_pockets() - if(slot_flags & ITEM_SLOT_HANDS) - update_held_items() +/mob/living/carbon/update_obscured_slots(obscured_flags) + ..() + if(obscured_flags & (HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT|HIDEMUTWINGS)) + update_body() /// Updates features and clothing attached to a specific limb with limb-specific offsets /mob/living/carbon/proc/update_features(feature_key) @@ -46,7 +15,7 @@ if(OFFSET_GLASSES) update_worn_glasses() if(OFFSET_EARS) - update_inv_ears() + update_worn_ears() if(OFFSET_SHOES) update_worn_shoes() if(OFFSET_S_STORE) @@ -357,7 +326,7 @@ //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) /* -/mob/living/carbon/update_worn_mask() +/mob/living/carbon/update_worn_mask(update_obscured = TRUE) remove_overlay(FACEMASK_LAYER) if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated @@ -368,13 +337,15 @@ inv.update_appearance() if(wear_mask) + if(update_obscured) + update_obscured_slots(wear_mask.flags_inv) if(!(check_obscured_slots() & ITEM_SLOT_MASK)) overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/clothing/mask.dmi') update_hud_wear_mask(wear_mask) apply_overlay(FACEMASK_LAYER) -/mob/living/carbon/update_worn_neck() +/mob/living/carbon/update_worn_neck(update_obscured = TRUE) remove_overlay(NECK_LAYER) if(client && hud_used?.inv_slots[TOBITSHIFT(ITEM_SLOT_NECK) + 1]) @@ -382,6 +353,8 @@ inv.update_appearance() if(wear_neck) + if(update_obscured) + update_obscured_slots(wear_neck.flags_inv) if(!(check_obscured_slots() & ITEM_SLOT_NECK)) overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = 'icons/mob/clothing/neck.dmi') update_hud_neck(wear_neck) @@ -392,7 +365,7 @@ //SKYRAT EDIT REMOVAL BEGIN - TESHARI CLOTHES (moved to modular) /* -/mob/living/carbon/update_worn_back() +/mob/living/carbon/update_worn_back(update_obscured = TRUE) remove_overlay(BACK_LAYER) if(client && hud_used?.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]) @@ -400,6 +373,8 @@ inv.update_appearance() if(back) + if(update_obscured) + update_obscured_slots(back.flags_inv) overlays_standing[BACK_LAYER] = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi') update_hud_back(back) @@ -407,10 +382,12 @@ */ //SKYRAT EDIT REMOVAL END -/mob/living/carbon/update_worn_legcuffs() +/mob/living/carbon/update_worn_legcuffs(update_obscured = TRUE) remove_overlay(LEGCUFF_LAYER) clear_alert("legcuffed") if(legcuffed) + if(update_obscured) + update_obscured_slots(legcuffed.flags_inv) overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/simple/mob.dmi', "legcuff1", -LEGCUFF_LAYER) apply_overlay(LEGCUFF_LAYER) throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed) @@ -418,7 +395,7 @@ //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) /* -/mob/living/carbon/update_worn_head() +/mob/living/carbon/update_worn_head(update_obscured = TRUE) remove_overlay(HEAD_LAYER) if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated @@ -429,7 +406,10 @@ inv.update_appearance() if(head) - overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head/default.dmi') + if(update_obscured) + update_obscured_slots(head.flags_inv) + if(!(check_obscured_slots() & ITEM_SLOT_HEAD)) + overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head/default.dmi') update_hud_head(head) apply_overlay(HEAD_LAYER) @@ -437,9 +417,11 @@ //SKYRAT EDIT REMOVAL END -/mob/living/carbon/update_worn_handcuffs() +/mob/living/carbon/update_worn_handcuffs(update_obscured = TRUE) remove_overlay(HANDCUFF_LAYER) if(handcuffed && !(handcuffed.item_flags & ABSTRACT)) //SKYRAT EDIT ADDED !(handcuffed.item_flags & ABSTRACT) + if(update_obscured) + update_obscured_slots(handcuffed.flags_inv) var/mutable_appearance/handcuff_overlay = mutable_appearance('icons/mob/simple/mob.dmi', "handcuff1", -HANDCUFF_LAYER) if(handcuffed.blocks_emissive != EMISSIVE_BLOCK_NONE) handcuff_overlay.overlays += emissive_blocker(handcuff_overlay.icon, handcuff_overlay.icon_state, src, alpha = handcuff_overlay.alpha) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index da43817f849..f549fe654fa 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -431,7 +431,7 @@ GLOBAL_LIST_EMPTY(features_by_species) replacement.Insert(organ_holder, special=TRUE, movement_flags = DELETE_IF_REPLACED) /datum/species/proc/worn_items_fit_body_check(mob/living/carbon/wearer) - for(var/obj/item/equipped_item in wearer.get_all_worn_items()) + for(var/obj/item/equipped_item in wearer.get_equipped_items(include_pockets = TRUE)) var/equipped_item_slot = wearer.get_slot_by_item(equipped_item) if(!equipped_item.mob_can_equip(wearer, equipped_item_slot, bypass_equip_delay_self = TRUE, ignore_equipped = TRUE)) wearer.dropItemToGround(equipped_item, force = TRUE) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 44fe6d1a1c0..193200c1e3a 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -41,7 +41,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) //Instead of just deleting our equipment, we save what we can and reinsert it into SSwardrobe's store //Hopefully this makes preference reloading not the worst thing ever /mob/living/carbon/human/dummy/delete_equipment() - var/list/items_to_check = get_all_worn_items() + held_items + var/list/items_to_check = get_equipped_items(include_pockets = TRUE) + held_items var/list/to_nuke = list() //List of items queued for deletion, can't qdel them before iterating their contents in case they hold something ///Travel to the bottom of the contents chain, expanding it out for(var/i = 1; i <= length(items_to_check); i++) //Needs to be a c style loop since it can expand @@ -68,6 +68,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) qdel(delete) /mob/living/carbon/human/dummy/has_equipped(obj/item/item, slot, initial = FALSE) + item.item_flags |= IN_INVENTORY return item.visual_equipped(src, slot, initial) /mob/living/carbon/human/dummy/proc/wipe_state() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index c6940f1d763..8b2496b045a 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -362,7 +362,7 @@ if(CONSCIOUS) if(HAS_TRAIT(src, TRAIT_DUMB)) msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" - if(get_organ_by_type(/obj/item/organ/internal/brain)) + if(get_organ_by_type(/obj/item/organ/internal/brain) && isnull(ai_controller)) if(!key) msg += "[span_deadsay("[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.")]\n" else if(!client) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 767c09bfa68..4febca81d67 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -88,11 +88,6 @@ /mob/living/carbon/human/Topic(href, href_list) - if(href_list["item"]) //canUseTopic check for this is handled by mob/Topic() - var/slot = text2num(href_list["item"]) - if(check_obscured_slots(TRUE) & slot) - to_chat(usr, span_warning("You can't reach that! Something is covering it.")) - return ///////HUDs/////// if(href_list["hud"]) @@ -620,7 +615,7 @@ // Check and wash stuff that can be covered var/obscured = check_obscured_slots() - if(w_uniform && !(obscured & ITEM_SLOT_ICLOTHING) && w_uniform.wash(clean_types)) + if(!(obscured & ITEM_SLOT_ICLOTHING) && w_uniform?.wash(clean_types)) update_worn_undersuit() . = TRUE @@ -959,7 +954,7 @@ var/carrydelay = 5 SECONDS //if you have latex you are faster at grabbing var/skills_space - var/fitness_level = mind.get_skill_level(/datum/skill/fitness) - 1 + var/fitness_level = mind.get_skill_level(/datum/skill/athletics) - 1 if(HAS_TRAIT(src, TRAIT_QUICKER_CARRY)) carrydelay -= 2 SECONDS else if(HAS_TRAIT(src, TRAIT_QUICK_CARRY)) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index d18c0c800f6..c8912cb72a5 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -75,15 +75,15 @@ return "Unknown" //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when Fluacided or when updating a human's name variable -/mob/living/carbon/human/proc/get_face_name(if_no_face="Unknown") +/mob/living/carbon/human/proc/get_face_name(if_no_face = "Unknown") if(HAS_TRAIT(src, TRAIT_UNKNOWN)) return if_no_face //We're Unknown, no face information for you - if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible + for(var/obj/item/worn_item in get_equipped_items()) + if(!(worn_item.flags_inv & HIDEFACE)) + continue return if_no_face - if( head && (head.flags_inv&HIDEFACE) ) - return if_no_face //Likewise for hats - var/obj/item/bodypart/O = get_bodypart(BODY_ZONE_HEAD) - if( !O || (HAS_TRAIT(src, TRAIT_DISFIGURED)) || (O.brutestate+O.burnstate)>2 || !real_name || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN)) //disfigured. use id-name if possible + var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) + if(isnull(head) || (HAS_TRAIT(src, TRAIT_DISFIGURED)) || (head.brutestate + head.burnstate) > 2 || !real_name || HAS_TRAIT(src, TRAIT_INVISIBLE_MAN)) //disfigured. use id-name if possible return if_no_face return real_name diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index bfb22804ddf..6f1c3f02ddf 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -54,7 +54,7 @@ There are several things that need to be remembered: update_worn_id() update_worn_glasses() update_worn_gloves() - update_inv_ears() + update_worn_ears() update_worn_shoes() update_suit_storage() update_worn_mask() @@ -70,10 +70,19 @@ There are several things that need to be remembered: //damage overlays update_damage_overlays() +/mob/living/carbon/human/update_obscured_slots(obscured_flags) + ..() + if(obscured_flags & HIDEFACE) + sec_hud_set_security_status() + // SKYRAT EDIT ADDITION START - ERP Overlays + if(obscured_flags & HIDESEXTOY) + update_inv_lewd() + // SKYRAT EDIT ADDITION END + /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv -/mob/living/carbon/human/update_worn_undersuit() +/mob/living/carbon/human/update_worn_undersuit(update_obscured = TRUE) remove_overlay(UNIFORM_LAYER) if(client && hud_used) @@ -84,6 +93,9 @@ There are several things that need to be remembered: var/obj/item/clothing/under/uniform = w_uniform update_hud_uniform(uniform) + if(update_obscured) + update_obscured_slots(uniform.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_ICLOTHING) return @@ -153,7 +165,7 @@ There are several things that need to be remembered: update_mutant_bodyparts() -/mob/living/carbon/human/update_worn_id() +/mob/living/carbon/human/update_worn_id(update_obscured = TRUE) remove_overlay(ID_LAYER) if(client && hud_used) @@ -165,6 +177,10 @@ There are several things that need to be remembered: if(wear_id) var/obj/item/worn_item = wear_id update_hud_id(worn_item) + + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + var/icon_file = 'icons/mob/clothing/id.dmi' id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = icon_file) @@ -179,7 +195,7 @@ There are several things that need to be remembered: apply_overlay(ID_LAYER) -/mob/living/carbon/human/update_worn_gloves() +/mob/living/carbon/human/update_worn_gloves(update_obscured = TRUE) remove_overlay(GLOVES_LAYER) if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_GLOVES) + 1]) @@ -202,6 +218,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = gloves update_hud_gloves(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_GLOVES) return @@ -230,7 +249,7 @@ There are several things that need to be remembered: apply_overlay(GLOVES_LAYER) -/mob/living/carbon/human/update_worn_glasses() +/mob/living/carbon/human/update_worn_glasses(update_obscured = TRUE) remove_overlay(GLASSES_LAYER) var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) @@ -245,6 +264,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = glasses update_hud_glasses(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_EYES) return @@ -269,7 +291,7 @@ There are several things that need to be remembered: apply_overlay(GLASSES_LAYER) -/mob/living/carbon/human/update_inv_ears() +/mob/living/carbon/human/update_worn_ears(update_obscured = TRUE) remove_overlay(EARS_LAYER) var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) @@ -284,6 +306,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = ears update_hud_ears(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_EARS) return @@ -307,7 +332,7 @@ There are several things that need to be remembered: overlays_standing[EARS_LAYER] = ears_overlay apply_overlay(EARS_LAYER) -/mob/living/carbon/human/update_worn_neck() +/mob/living/carbon/human/update_worn_neck(update_obscured = TRUE) remove_overlay(NECK_LAYER) if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_NECK) + 1]) @@ -318,6 +343,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = wear_neck update_hud_neck(wear_neck) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_NECK) return @@ -349,7 +377,7 @@ There are several things that need to be remembered: apply_overlay(NECK_LAYER) -/mob/living/carbon/human/update_worn_shoes() +/mob/living/carbon/human/update_worn_shoes(update_obscured = TRUE) remove_overlay(SHOES_LAYER) if(num_legs < 2) @@ -363,6 +391,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = shoes update_hud_shoes(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_FEET) return @@ -407,7 +438,7 @@ There are several things that need to be remembered: update_body_parts() -/mob/living/carbon/human/update_suit_storage() +/mob/living/carbon/human/update_suit_storage(update_obscured = TRUE) remove_overlay(SUIT_STORE_LAYER) if(client && hud_used) @@ -418,6 +449,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = s_store update_hud_s_store(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_SUITSTORE) return @@ -427,7 +461,7 @@ There are several things that need to be remembered: overlays_standing[SUIT_STORE_LAYER] = s_store_overlay apply_overlay(SUIT_STORE_LAYER) -/mob/living/carbon/human/update_worn_head() +/mob/living/carbon/human/update_worn_head(update_obscured = TRUE) remove_overlay(HEAD_LAYER) if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]) var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_HEAD) + 1] @@ -437,6 +471,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = head update_hud_head(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_HEAD) return @@ -465,10 +502,9 @@ There are several things that need to be remembered: // SKYRAT EDIT END overlays_standing[HEAD_LAYER] = head_overlay - update_mutant_bodyparts() apply_overlay(HEAD_LAYER) -/mob/living/carbon/human/update_worn_belt() +/mob/living/carbon/human/update_worn_belt(update_obscured = TRUE) remove_overlay(BELT_LAYER) if(client && hud_used) @@ -479,6 +515,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = belt update_hud_belt(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_BELT) return @@ -504,7 +543,7 @@ There are several things that need to be remembered: apply_overlay(BELT_LAYER) -/mob/living/carbon/human/update_worn_oversuit() +/mob/living/carbon/human/update_worn_oversuit(update_obscured = TRUE) remove_overlay(SUIT_LAYER) if(client && hud_used) @@ -514,6 +553,10 @@ There are several things that need to be remembered: if(wear_suit) var/obj/item/worn_item = wear_suit update_hud_wear_suit(worn_item) + + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + var/icon_file = DEFAULT_SUIT_FILE // SKYRAT EDIT ADDITION @@ -573,7 +616,7 @@ There are several things that need to be remembered: client.screen += r_store update_observer_view(r_store) -/mob/living/carbon/human/update_worn_mask() +/mob/living/carbon/human/update_worn_mask(update_obscured = TRUE) remove_overlay(FACEMASK_LAYER) var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) @@ -588,6 +631,9 @@ There are several things that need to be remembered: var/obj/item/worn_item = wear_mask update_hud_wear_mask(worn_item) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_MASK) return @@ -618,7 +664,7 @@ There are several things that need to be remembered: apply_overlay(FACEMASK_LAYER) update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout -/mob/living/carbon/human/update_worn_back() +/mob/living/carbon/human/update_worn_back(update_obscured = TRUE) remove_overlay(BACK_LAYER) if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]) @@ -629,6 +675,10 @@ There are several things that need to be remembered: var/obj/item/worn_item = back var/mutable_appearance/back_overlay update_hud_back(worn_item) + + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) + var/icon_file = 'icons/mob/clothing/back.dmi' // SKYRAT EDIT ADDITION diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 6cafa38164e..f0dadf5f818 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -69,9 +69,6 @@ return ..() -/mob/living/carbon/human/get_all_worn_items() - . = get_head_slots() | get_body_slots() - /mob/living/carbon/human/proc/get_body_slots() return list( back, @@ -136,15 +133,13 @@ if(ears) return ears = equipping - update_inv_ears() + update_worn_ears() if(ITEM_SLOT_EYES) if(glasses) return glasses = equipping if(glasses.glass_colour_type) update_glasses_color(glasses, 1) - if(glasses.tint) - update_tint() if(glasses.vision_flags || glasses.invis_override || glasses.invis_view || !isnull(glasses.lighting_cutoff)) update_sight() update_worn_glasses() @@ -171,8 +166,6 @@ wear_suit = equipping - if(equipping.flags_inv & HIDEJUMPSUIT) - update_worn_undersuit() if(wear_suit.breakouttime) //when equipping a straightjacket ADD_TRAIT(src, TRAIT_RESTRAINED, SUIT_TRAIT) stop_pulling() //can't pull if restrained @@ -216,6 +209,7 @@ . = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should. if(!. || !I) return + var/not_handled = FALSE //if we actually unequipped an item, this is because we dont want to run this proc twice, once for carbons and once for humans if(I == wear_suit) if(s_store && invdrop) dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit. @@ -225,14 +219,6 @@ update_mob_action_buttons() //certain action buttons may be usable again. wear_suit = null if(!QDELETED(src)) //no need to update we're getting deleted anyway - if(I.flags_inv & HIDEJUMPSUIT) - update_worn_undersuit() - - // SKYRAT EDIT ADDITION START - ERP Overlays - if(I.flags_inv & HIDESEXTOY) - update_inv_lewd() - // SKYRAT EDIT ADDITION END - update_worn_oversuit() else if(I == w_uniform) w_uniform = null @@ -263,8 +249,6 @@ var/obj/item/clothing/glasses/G = I if(G.glass_colour_type) update_glasses_color(G, 0) - if(G.tint) - update_tint() if(G.vision_flags || G.invis_override || G.invis_view || !isnull(G.lighting_cutoff)) update_sight() if(!QDELETED(src)) @@ -272,7 +256,7 @@ else if(I == ears) ears = null if(!QDELETED(src)) - update_inv_ears() + update_worn_ears() else if(I == shoes) shoes = null if(!QDELETED(src)) @@ -298,13 +282,19 @@ s_store = null if(!QDELETED(src)) update_suit_storage() - - update_equipment_speed_mods() + else + not_handled = TRUE // Send a signal for when we unequip an item that used to cover our feet/shoes. Used for bloody feet if((I.body_parts_covered & FEET) || (I.flags_inv | I.transparent_protection) & HIDESHOES) SEND_SIGNAL(src, COMSIG_CARBON_UNEQUIP_SHOECOVER, I, force, newloc, no_move, invdrop, silent) + if(not_handled) + return + + update_equipment_speed_mods() + update_obscured_slots(I.flags_inv) + /mob/living/carbon/human/toggle_internals(obj/item/tank, is_external = FALSE) // Just close the tank if it's the one the mob already has open. var/obj/item/existing_tank = is_external ? external : internal @@ -316,8 +306,8 @@ // Use mask in absence of tube. if(isclothing(wear_mask) && ((wear_mask.visor_flags & MASKINTERNALS) || (wear_mask.clothing_flags & MASKINTERNALS))) // Adjust dishevelled breathing mask back onto face. - if (wear_mask.mask_adjusted) - wear_mask.adjustmask(src) + if (wear_mask.up) + wear_mask.adjust_visor(src) return toggle_open_internals(tank, is_external) // Use helmet in absence of tube or valid mask. if(can_breathe_helmet()) @@ -337,30 +327,6 @@ /mob/living/carbon/human/toggle_externals(obj/item/tank) return toggle_internals(tank, TRUE) -/mob/living/carbon/human/wear_mask_update(obj/item/I, toggle_off = 1) - if((I.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || (initial(I.flags_inv) & (HIDEHAIR|HIDEFACIALHAIR))) - update_body_parts() - // Close internal air tank if mask was the only breathing apparatus. - if(invalid_internals()) - cutoff_internals() - if(I.flags_inv & HIDEEYES) - update_worn_glasses() - sec_hud_set_security_status() - ..() - -/mob/living/carbon/human/head_update(obj/item/I, forced) - if((I.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || forced) - update_body_parts() - // Close internal air tank if helmet was the only breathing apparatus. - if (invalid_internals()) - cutoff_internals() - if(I.flags_inv & HIDEEYES || forced) - update_worn_glasses() - if(I.flags_inv & HIDEEARS || forced) - update_body() - sec_hud_set_security_status() - ..() - /mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE) var/datum/outfit/O = null @@ -394,10 +360,10 @@ //delete all equipment without dropping anything /mob/living/carbon/human/proc/delete_equipment() - for(var/slot in get_all_worn_items())//order matters, dependant slots go first + for(var/slot in get_equipped_items(include_pockets = TRUE))//order matters, dependant slots go first qdel(slot) - for(var/obj/item/I in held_items) - qdel(I) + for(var/obj/item/held_item in held_items) + qdel(held_item) /// take the most recent item out of a slot or place held item in a slot diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index e0a24d0ab51..45ca4487184 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -39,16 +39,6 @@ return ..() -/mob/living/carbon/proc/get_all_worn_items() - return list( - back, - wear_mask, - wear_neck, - head, - handcuffed, - legcuffed, - ) - /// Returns items which are currently visible on the mob /mob/living/carbon/proc/get_visible_items() var/static/list/visible_slots = list( @@ -126,13 +116,13 @@ if(wear_mask) return wear_mask = equipping - wear_mask_update(equipping, toggle_off = 0) + update_worn_mask() if(ITEM_SLOT_HEAD) if(head) return head = equipping SEND_SIGNAL(src, COMSIG_CARBON_EQUIP_HAT, equipping) - head_update(equipping) + update_worn_head() if(ITEM_SLOT_NECK) if(wear_neck) return @@ -162,7 +152,7 @@ return not_handled /mob/living/carbon/get_equipped_speed_mod_items() - return ..() + get_all_worn_items() + return ..() + get_equipped_items() /// This proc is called after an item has been successfully handled and equipped to a slot. /mob/living/carbon/proc/has_equipped(obj/item/item, slot, initial = FALSE) @@ -173,11 +163,12 @@ if(!. || !I) //We don't want to set anything to null if the parent returned 0. return + var/not_handled = FALSE //if we actually unequipped an item, this is because we dont want to run this proc twice, once for carbons and once for humans if(I == head) head = null SEND_SIGNAL(src, COMSIG_CARBON_UNEQUIP_HAT, I, force, newloc, no_move, invdrop, silent) if(!QDELETED(src)) - head_update(I) + update_worn_head() else if(I == back) back = null if(!QDELETED(src)) @@ -185,8 +176,8 @@ else if(I == wear_mask) wear_mask = null if(!QDELETED(src)) - wear_mask_update(I, toggle_off = 1) - if(I == wear_neck) + update_worn_mask() + else if(I == wear_neck) wear_neck = null if(!QDELETED(src)) update_worn_neck(I) @@ -200,6 +191,8 @@ legcuffed = null if(!QDELETED(src)) update_worn_legcuffs() + else + not_handled = TRUE // Not an else-if because we're probably equipped in another slot if(I == internal && (QDELETED(src) || QDELETED(I) || I.loc != src)) @@ -207,7 +200,11 @@ if(!QDELETED(src)) update_mob_action_buttons(UPDATE_BUTTON_STATUS) + if(not_handled) + return + update_equipment_speed_mods() + update_obscured_slots(I.flags_inv) /// Returns TRUE if an air tank compatible helmet is equipped. /mob/living/carbon/proc/can_breathe_helmet() @@ -357,27 +354,6 @@ // Carbons can't open their own externals tanks. return FALSE -/// Handle stuff to update when a mob equips/unequips a mask. -/mob/living/proc/wear_mask_update(obj/item/I, toggle_off = 1) - update_worn_mask() - -/mob/living/carbon/wear_mask_update(obj/item/I, toggle_off = 1) - var/obj/item/clothing/C = I - if(istype(C) && (C.tint || initial(C.tint))) - update_tint() - update_worn_mask() - -/// Handle stuff to update when a mob equips/unequips a headgear. -/mob/living/carbon/proc/head_update(obj/item/I, forced) - if(isclothing(I)) - var/obj/item/clothing/C = I - if(C.tint || initial(C.tint)) - update_tint() - update_sight() - if(I.flags_inv & HIDEMASK || forced) - update_worn_mask() - update_worn_head() - /mob/living/carbon/proc/get_holding_bodypart_of_item(obj/item/I) var/index = get_held_index_of_item(I) return index && hand_bodyparts[index] @@ -475,7 +451,7 @@ SHOULD_NOT_OVERRIDE(TRUE) var/covered_flags = NONE - var/list/all_worn_items = get_all_worn_items() + var/list/all_worn_items = get_equipped_items() for(var/obj/item/worn_item in all_worn_items) covered_flags |= worn_item.body_parts_covered @@ -486,7 +462,7 @@ SHOULD_NOT_OVERRIDE(TRUE) var/covered_flags = NONE - var/list/all_worn_items = get_all_worn_items() + var/list/all_worn_items = get_equipped_items() for(var/obj/item/worn_item in all_worn_items) covered_flags |= worn_item.body_parts_covered diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index b8f1e60a612..2c390c540ce 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -98,7 +98,7 @@ SIGNAL_HANDLER mobility_flags &= ~MOBILITY_MOVE if(living_flags & MOVES_ON_ITS_OWN) - SSmove_manager.stop_looping(src) //stop mid walk //This is also really dumb + DSmove_manager.stop_looping(src) //stop mid walk //This is also really dumb /// Called when [TRAIT_IMMOBILIZED] is removed from the mob. /mob/living/proc/on_immobilized_trait_loss(datum/source) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e37981d038a..cdbbd31abf5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -697,7 +697,9 @@ /mob/living/proc/get_up(instant = FALSE) set waitfor = FALSE - var/get_up_speed = GET_UP_FAST //SKYRAT EDIT CHANGE : if(!instant && !do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback)), interaction_key = DOAFTER_SOURCE_GETTING_UP)) + // if(!instant && !do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback)), interaction_key = DOAFTER_SOURCE_GETTING_UP, hidden = TRUE)) // SKYRAT EDIT REMOVAL + // SKYRAT EDIT ADDITION START + var/get_up_speed = GET_UP_FAST var/stam = getStaminaLoss() switch(FLOOR(stam,1)) if(STAMINA_THRESHOLD_MEDIUM_GET_UP to STAMINA_THRESHOLD_SLOW_GET_UP) @@ -706,20 +708,21 @@ get_up_speed = GET_UP_SLOW if(!instant) if(get_up_speed == GET_UP_SLOW) //Slow getups are easily noticable - visible_message(span_notice("[src] weakily attempts to stand up."), span_notice("You weakily attempt to stand up.")) - if(!do_after(src, get_up_speed SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, /mob/living/proc/rest_checks_callback), interaction_key = DOAFTER_SOURCE_GETTING_UP)) + visible_message(span_notice("[src] weakly attempts to stand up."), span_notice("You weakly attempt to stand up.")) + if(!do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback)), interaction_key = DOAFTER_SOURCE_GETTING_UP, hidden = TRUE)) if(!body_position == STANDING_UP) visible_message(span_warning("[src] fails to stand up."), span_warning("You fail to stand up.")) return else - if(!do_after(src, get_up_speed SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, /mob/living/proc/rest_checks_callback), interaction_key = DOAFTER_SOURCE_GETTING_UP)) + if(!do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback)), interaction_key = DOAFTER_SOURCE_GETTING_UP, hidden = TRUE)) return if(pulledby && pulledby.grab_state) - to_chat(src, span_warning("You fail to stand up, you're restrained!")) //SKYRAT EDIT ADDITION END + to_chat(src, span_warning("You fail to stand up, you're restrained!")) + // NOVA EDIT ADDITION END return if(resting || body_position == STANDING_UP || HAS_TRAIT(src, TRAIT_FLOORED)) return - to_chat(src, span_notice("You stand up.")) //SKYRAT EDIT ADDITION + to_chat(src, span_notice("You stand up.")) // SKYRAT EDIT ADDITION set_body_position(STANDING_UP) set_lying_angle(0) @@ -1396,7 +1399,8 @@ if(!Adjacent(target) && (target.loc != src) && !recursive_loc_check(src, target)) if(HAS_SILICON_ACCESS(src) && !ispAI(src)) if(!(action_bitflags & ALLOW_SILICON_REACH)) // silicons can ignore range checks (except pAIs) - to_chat(src, span_warning("You are too far away!")) + if(!(action_bitflags & SILENT_ADJACENCY)) + to_chat(src, span_warning("You are too far away!")) return FALSE else // just a normal carbon mob if((action_bitflags & FORBID_TELEKINESIS_REACH)) @@ -1888,7 +1892,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) user.put_in_hands(holder) /mob/living/proc/set_name() - if(!numba) + if(numba == 0) numba = rand(1, 1000) name = "[name] ([numba])" real_name = name diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 52e4f9304be..7e13fb2375d 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -421,7 +421,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( var/mob/living/carbon/human/human_speaker = src if(istype(human_speaker.wear_mask, /obj/item/clothing/mask)) var/obj/item/clothing/mask/worn_mask = human_speaker.wear_mask - if(!worn_mask.mask_adjusted) + if(!worn_mask.up) if(worn_mask.voice_override) voice_to_use = worn_mask.voice_override if(worn_mask.voice_filter) diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 2a9631339fc..0f1cbfa65a5 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -18,7 +18,7 @@ /mob/living/silicon/robot/proc/use_energy(seconds_per_tick, times_fired) if(cell?.charge) - if(cell.charge <= (10 KILO JOULES)) + if(cell.charge <= 0.01 * STANDARD_CELL_CHARGE) drop_all_held_items() var/energy_consumption = max(lamp_power_consumption * lamp_enabled * lamp_intensity * seconds_per_tick, BORG_MINIMUM_POWER_CONSUMPTION * seconds_per_tick) //Lamp will use a max of 5 * [BORG_LAMP_POWER_CONSUMPTION], depending on brightness of lamp. If lamp is off, borg systems consume [BORG_MINIMUM_POWER_CONSUMPTION], or the rest of the cell if it's lower than that. cell.use(energy_consumption, force = TRUE) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 9272e63e7ff..799d603996d 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -234,7 +234,7 @@ if(!ionpulse_on) return - if(!cell.use(10 KILO JOULES)) + if(!cell.use(0.01 * STANDARD_CELL_CHARGE)) toggle_ionpulse() return return TRUE diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index a737de7f99e..54d3377dd38 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -386,9 +386,11 @@ /obj/item/pipe_dispenser, /obj/item/extinguisher, /obj/item/weldingtool/largetank/cyborg, - /obj/item/screwdriver/cyborg/power, // Skyrat Removal/Edit - Combines Screwdriver and Wrench into one - /obj/item/crowbar/cyborg/power, // Skyrat Removal/Edit - Combines Crowbar and Wirecutters into one - /obj/item/multitool/cyborg, + /obj/item/screwdriver/cyborg/power, // Skyrat ADDITION - Combines Screwdriver and Wrench into one + /obj/item/crowbar/cyborg/power, // Skyrat ADDITION - Combines Crowbar and Wirecutters into one + /obj/item/multitool/cyborg, //Skyrat ADDITION - Adds multitool for easier access + /obj/item/borg/cyborg_omnitool/engineering, + ///obj/item/borg/cyborg_omnitool/engineering, //Skyrat REMOVAL /obj/item/t_scanner, /obj/item/analyzer, /obj/item/holosign_creator/atmos, // Skyrat Edit - Adds Holofans to engineering borgos @@ -681,14 +683,8 @@ /obj/item/borg/apparatus/beaker, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, - /obj/item/surgical_drapes, - /obj/item/retractor, - /obj/item/hemostat, - /obj/item/cautery, - /obj/item/surgicaldrill, - /obj/item/scalpel, - /obj/item/circular_saw, - /obj/item/bonesetter, + /obj/item/borg/cyborg_omnitool/medical, + /obj/item/borg/cyborg_omnitool/medical, /obj/item/blood_filter, /obj/item/extinguisher/mini, /obj/item/emergency_bed/silicon, @@ -889,15 +885,10 @@ /obj/item/reagent_containers/borghypo/syndicate, /obj/item/shockpaddles/syndicate/cyborg, /obj/item/healthanalyzer, - /obj/item/surgical_drapes, - /obj/item/retractor, - /obj/item/hemostat, - /obj/item/cautery, - /obj/item/surgicaldrill, - /obj/item/scalpel, - /obj/item/melee/energy/sword/cyborg/saw, - /obj/item/bonesetter, + /obj/item/borg/cyborg_omnitool/medical, + /obj/item/borg/cyborg_omnitool/medical, /obj/item/blood_filter, + /obj/item/melee/energy/sword/cyborg/saw, /obj/item/emergency_bed/silicon, /obj/item/crowbar/cyborg, /obj/item/extinguisher/mini, @@ -922,12 +913,9 @@ /obj/item/restraints/handcuffs/cable/zipties, /obj/item/extinguisher, /obj/item/weldingtool/largetank/cyborg, - /obj/item/screwdriver/nuke, - /obj/item/wrench/cyborg, - /obj/item/crowbar/cyborg, - /obj/item/wirecutters/cyborg, /obj/item/analyzer, - /obj/item/multitool/cyborg, + /obj/item/borg/cyborg_omnitool/engineering, + /obj/item/borg/cyborg_omnitool/engineering, /obj/item/stack/sheet/iron, /obj/item/stack/sheet/glass, /obj/item/borg/apparatus/sheet_manipulator, diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index fb201faeeee..4fbd1b55234 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -306,7 +306,7 @@ ///Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. /mob/living/silicon/proc/checklaws() laws_sanity_check() - var/list = "Which laws do you want to include when stating them for the crew?

    " + var/list = "Which laws do you want to include when stating them for the crew?

    " var/law_display = "Yes" if (laws.zeroth) diff --git a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm index a0c9a964fb3..6d85b9c1867 100644 --- a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm +++ b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm @@ -71,7 +71,7 @@ switch(mode) if(BOT_IDLE) // idle update_appearance() - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) look_for_perp() // see if any criminals are in range if(!mode && bot_mode_flags & BOT_MODE_AUTOPATROL) // still idle, and set to patrol mode = BOT_START_PATROL // switch to patrol mode @@ -80,7 +80,7 @@ playsound(src,'sound/effects/beepskyspinsabre.ogg',100,TRUE,-1) // general beepsky doesn't give up so easily, jedi scum if(frustration >= 20) - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) back_to_idle() return if(target) // make sure target exists @@ -91,7 +91,7 @@ return else // not next to perp var/turf/olddist = get_dist(src, target) - SSmove_manager.move_to(src, target, 1, 4) + DSmove_manager.move_to(src, target, 1, 4) if((get_dist(src, target)) >= (olddist)) frustration++ else diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index ec204dbc82b..944a00af9b6 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -204,6 +204,7 @@ pa_system = new(src, automated_announcements = automated_announcements) pa_system.Grant(src) + RegisterSignal(src, COMSIG_MOB_TRIED_ACCESS, PROC_REF(attempt_access)) /mob/living/simple_animal/bot/Destroy() GLOB.bots_list -= src @@ -951,13 +952,13 @@ Pass a positive integer as an argument to override a bot's default speed. calc_summon_path() tries = 0 -/mob/living/simple_animal/bot/Bump(atom/A) //Leave no door unopened! - . = ..() - if((istype(A, /obj/machinery/door/airlock) || istype(A, /obj/machinery/door/window)) && (!isnull(access_card))) - var/obj/machinery/door/D = A - if(D.check_access(access_card)) - D.open() - frustration = 0 +/mob/living/simple_animal/bot/proc/attempt_access(mob/bot, obj/door_attempt) + SIGNAL_HANDLER + + if(door_attempt.check_access(access_card)) + frustration = 0 + return ACCESS_ALLOWED + return ACCESS_DISALLOWED /mob/living/simple_animal/bot/ui_data(mob/user) var/list/data = list() diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 45c9802a8f3..8c933e8f83a 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -164,7 +164,7 @@ target = null oldtarget_name = null set_anchored(FALSE) - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) last_found = world.time /mob/living/simple_animal/bot/secbot/proc/on_saboteur(datum/source, disrupt_duration) @@ -389,7 +389,7 @@ switch(mode) if(BOT_IDLE) // idle - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) look_for_perp() // see if any criminals are in range if((mode == BOT_IDLE) && bot_mode_flags & BOT_MODE_AUTOPATROL) // didn't start hunting during look_for_perp, and set to patrol mode = BOT_START_PATROL // switch to patrol mode @@ -397,7 +397,7 @@ if(BOT_HUNT) // hunting for perp // if can't reach perp for long enough, go idle if(frustration >= 8) - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) back_to_idle() return @@ -415,7 +415,7 @@ // not next to perp var/turf/olddist = get_dist(src, target) - SSmove_manager.move_to(src, target, 1, 4) + DSmove_manager.move_to(src, target, 1, 4) if((get_dist(src, target)) >= (olddist)) frustration++ else diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 3ff8f04fb92..86fc82d77e0 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -104,7 +104,7 @@ /mob/living/simple_animal/hostile/Life(seconds_per_tick = SSMOBS_DT, times_fired) . = ..() if(!.) //dead - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) /mob/living/simple_animal/hostile/handle_automated_action() if(AIStatus == AI_OFF || QDELETED(src)) @@ -339,11 +339,11 @@ if(!target.Adjacent(target_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown OpenFire(target) if(!Process_Spacemove(0)) //Drifting - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) return 1 if(retreat_distance != null) //If we have a retreat distance, check if we need to run from our target if(target_distance <= retreat_distance) //If target's closer than our retreat distance, run - SSmove_manager.move_away(src, target, retreat_distance, move_to_delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) + DSmove_manager.move_away(src, target, retreat_distance, move_to_delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) else Goto(target,move_to_delay,minimum_distance) //Otherwise, get to our minimum distance so we chase them else @@ -378,7 +378,7 @@ approaching_target = TRUE else approaching_target = FALSE - SSmove_manager.move_to(src, target, minimum_distance, delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) + DSmove_manager.move_to(src, target, minimum_distance, delay, flags = MOVEMENT_LOOP_IGNORE_GLIDE) return TRUE /mob/living/simple_animal/hostile/adjustHealth(amount, updating_health = TRUE, forced = FALSE) @@ -418,7 +418,7 @@ GiveTarget(null) approaching_target = FALSE in_melee = FALSE - SSmove_manager.stop_looping(src) + DSmove_manager.stop_looping(src) LoseAggro() SEND_SIGNAL(src, COMSIG_HOSTILE_MOB_LOST_TARGET) // SKYRAT EDIT ADDITION diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 40f7f3abd0d..414cf97eab2 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -330,7 +330,7 @@ . = ..() if(!.) return FALSE - + for(var/atom/thing as anything in range(1, src)) if(isturf(thing)) new /obj/effect/decal/cleanable/confetti(thing) @@ -340,7 +340,7 @@ continue var/mob/living/carbon/human/new_clown = thing - + if(new_clown.stat != DEAD) continue @@ -349,12 +349,12 @@ var/clown_ref = REF(new_clown) if(clown_ref in clowned_mob_refs) //one clowning per person continue - + for(var/obj/item/to_strip in new_clown.get_equipped_items()) new_clown.dropItemToGround(to_strip) new_clown.dress_up_as_job(SSjob.GetJobType(/datum/job/clown)) clowned_mob_refs += clown_ref - + return TRUE /// Transforms the area to look like a new one @@ -370,7 +370,7 @@ /obj/machinery/anomalous_crystal/theme_warp/Initialize(mapload) . = ..() - terrain_theme = SSmaterials.dimensional_themes[pick(subtypesof(/datum/dimension_theme))] + terrain_theme = DSmaterials.dimensional_themes[pick(subtypesof(/datum/dimension_theme))] observer_desc = "This crystal changes the area around it to match the theme of \"[terrain_theme.name]\"." /obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method) @@ -423,18 +423,18 @@ if(!ishuman(thing)) continue - + var/mob/living/carbon/human/to_revive = thing - + if(to_revive.stat != DEAD) continue - + to_revive.set_species(/datum/species/shadow, TRUE) to_revive.revive(ADMIN_HEAL_ALL, force_grab_ghost = TRUE) //Free revives, but significantly limits your options for reviving except via the crystal //except JK who cares about BADDNA anymore. this even heals suicides. ADD_TRAIT(to_revive, TRAIT_BADDNA, MAGIC_TRAIT) - + return TRUE /obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm index 3a838ac58cd..b2555309f8a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm @@ -45,7 +45,7 @@ /mob/living/simple_animal/hostile/asteroid/curseblob/proc/move_loop(move_target, delay) if(our_loop) return - our_loop = SSmove_manager.force_move(src, move_target, delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + our_loop = DSmove_manager.force_move(src, move_target, delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) if(!our_loop) return RegisterSignal(move_target, COMSIG_MOB_STATCHANGE, PROC_REF(stat_change)) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 47d3ddcf20f..4cfe68b2b96 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -539,7 +539,7 @@ /mob/living/simple_animal/proc/Goto(target, delay, minimum_distance) if(prevent_goto_movement) return FALSE - SSmove_manager.move_to(src, target, minimum_distance, delay) + DSmove_manager.move_to(src, target, minimum_distance, delay) return TRUE //Makes this mob hunt the prey, be it living or an object. Will kill living creatures, and delete objects. diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index ceff6e95658..35ef05ec40f 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -315,7 +315,7 @@ if(rebound.last_pushoff == world.time) continue if(continuous_move && !pass_allowed) - var/datum/move_loop/move/rebound_engine = SSmove_manager.processing_on(rebound, SSspacedrift) + var/datum/move_loop/move/rebound_engine = DSmove_manager.processing_on(rebound, SSspacedrift) // If you're moving toward it and you're both going the same direction, stop if(moving_direction == get_dir(src, pushover) && rebound_engine && moving_direction == rebound_engine.direction) continue @@ -545,7 +545,7 @@ to_chat(src, span_warning("You are not Superman.")) return balloon_alert(src, "moving up...") - if(!do_after(src, 1 SECONDS)) + if(!do_after(src, 1 SECONDS, hidden = TRUE)) return if(zMove(UP, z_move_flags = ZMOVE_FLIGHT_FLAGS|ZMOVE_FEEDBACK|ventcrawling_flag)) to_chat(src, span_notice("You move upwards.")) @@ -571,7 +571,7 @@ var/ventcrawling_flag = HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING) ? ZMOVE_VENTCRAWLING : 0 balloon_alert(src, "moving down...") - if(!do_after(src, 1 SECONDS)) + if(!do_after(src, 1 SECONDS, hidden = TRUE)) return if(zMove(DOWN, z_move_flags = ZMOVE_FLIGHT_FLAGS|ZMOVE_FEEDBACK|ventcrawling_flag)) to_chat(src, span_notice("You move down.")) diff --git a/code/modules/mob/mob_update_icons.dm b/code/modules/mob/mob_update_icons.dm index b8b84f8782a..a355a385d9f 100644 --- a/code/modules/mob/mob_update_icons.dm +++ b/code/modules/mob/mob_update_icons.dm @@ -7,21 +7,75 @@ ///Updates every item slot passed into it. /mob/proc/update_clothing(slot_flags) - return + if(slot_flags & ITEM_SLOT_BACK) + update_worn_back() + if(slot_flags & ITEM_SLOT_MASK) + update_worn_mask() + if(slot_flags & ITEM_SLOT_NECK) + update_worn_neck() + if(slot_flags & ITEM_SLOT_HANDCUFFED) + update_worn_handcuffs() + if(slot_flags & ITEM_SLOT_LEGCUFFED) + update_worn_legcuffs() + if(slot_flags & ITEM_SLOT_BELT) + update_worn_belt() + if(slot_flags & ITEM_SLOT_ID) + update_worn_id() + if(slot_flags & ITEM_SLOT_EARS) + update_worn_ears() + if(slot_flags & ITEM_SLOT_EYES) + update_worn_glasses() + if(slot_flags & ITEM_SLOT_GLOVES) + update_worn_gloves() + if(slot_flags & ITEM_SLOT_HEAD) + update_worn_head() + if(slot_flags & ITEM_SLOT_FEET) + update_worn_shoes() + if(slot_flags & ITEM_SLOT_OCLOTHING) + update_worn_oversuit() + if(slot_flags & ITEM_SLOT_ICLOTHING) + update_worn_undersuit() + if(slot_flags & ITEM_SLOT_SUITSTORE) + update_suit_storage() + if(slot_flags & (ITEM_SLOT_LPOCKET|ITEM_SLOT_RPOCKET)) + update_pockets() + if(slot_flags & ITEM_SLOT_HANDS) + update_held_items() + +///Updates item slots obscured by this item (or using an override of flags to check) +/mob/proc/update_obscured_slots(obscured_flags) + if(obscured_flags & HIDEGLOVES) + update_worn_gloves(update_obscured = FALSE) + if(obscured_flags & HIDESUITSTORAGE) + update_suit_storage(update_obscured = FALSE) + if(obscured_flags & HIDEJUMPSUIT) + update_worn_undersuit(update_obscured = FALSE) + if(obscured_flags & HIDESHOES) + update_worn_shoes(update_obscured = FALSE) + if(obscured_flags & HIDEMASK) + update_worn_mask(update_obscured = FALSE) + if(obscured_flags & HIDEEARS) + update_worn_ears(update_obscured = FALSE) + if(obscured_flags & HIDEEYES) + update_worn_glasses(update_obscured = FALSE) + if(obscured_flags & HIDENECK) + update_worn_neck(update_obscured = FALSE) + if(obscured_flags & HIDEHEADGEAR) + update_worn_head(update_obscured = FALSE) /mob/proc/update_icons() return ///Updates the handcuff overlay & HUD element. -/mob/proc/update_worn_handcuffs() +/mob/proc/update_worn_handcuffs(update_obscured = FALSE) return ///Updates the legcuff overlay & HUD element. -/mob/proc/update_worn_legcuffs() +/mob/proc/update_worn_legcuffs(update_obscured = FALSE) return ///Updates the back overlay & HUD element. -/mob/proc/update_worn_back() +/mob/proc/update_worn_back(update_obscured = FALSE) return ///Updates the held items overlay(s) & HUD element. @@ -30,27 +84,27 @@ SEND_SIGNAL(src, COMSIG_MOB_UPDATE_HELD_ITEMS) ///Updates the mask overlay & HUD element. -/mob/proc/update_worn_mask() +/mob/proc/update_worn_mask(update_obscured = FALSE) return ///Updates the neck overlay & HUD element. -/mob/proc/update_worn_neck() +/mob/proc/update_worn_neck(update_obscured = FALSE) return ///Updates the oversuit overlay & HUD element. -/mob/proc/update_worn_oversuit() +/mob/proc/update_worn_oversuit(update_obscured = FALSE) return ///Updates the undersuit/uniform overlay & HUD element. -/mob/proc/update_worn_undersuit() +/mob/proc/update_worn_undersuit(update_obscured = FALSE) return ///Updates the belt overlay & HUD element. -/mob/proc/update_worn_belt() +/mob/proc/update_worn_belt(update_obscured = FALSE) return ///Updates the on-head overlay & HUD element. -/mob/proc/update_worn_head() +/mob/proc/update_worn_head(update_obscured = FALSE) return ///Updates every part of a carbon's body. Including parts, mutant parts, lips, underwear, and socks. @@ -61,29 +115,29 @@ return ///Updates the glasses overlay & HUD element. -/mob/proc/update_worn_glasses() +/mob/proc/update_worn_glasses(update_obscured = FALSE) return ///Updates the id overlay & HUD element. -/mob/proc/update_worn_id() +/mob/proc/update_worn_id(update_obscured = FALSE) return ///Updates the shoes overlay & HUD element. -/mob/proc/update_worn_shoes() +/mob/proc/update_worn_shoes(update_obscured = FALSE) return ///Updates the glasses overlay & HUD element. -/mob/proc/update_worn_gloves() +/mob/proc/update_worn_gloves(update_obscured = FALSE) return -///Updates the handcuff overlay & HUD element. -/mob/proc/update_suit_storage() +///Updates the suit storage overlay & HUD element. +/mob/proc/update_suit_storage(update_obscured = FALSE) return -///Updates the handcuff overlay & HUD element. +///Updates the pocket overlay & HUD element. /mob/proc/update_pockets() return -///Updates the handcuff overlay & HUD element. -/mob/proc/update_inv_ears() +///Updates the headset overlay & HUD element. +/mob/proc/update_worn_ears(update_obscured = FALSE) return diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index 7d698aa5a75..303d556843e 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -169,23 +169,23 @@ if (ai_assistant) to_chat(ai_assistant, span_notice("MODsuit [active ? "shutting down" : "starting up"].")) - if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)))) + if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)), hidden = TRUE)) to_chat(wearer, span_notice("[boots] [active ? "relax their grip on your legs" : "seal around your feet"].")) playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) seal_part(boots, seal = !active) - if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)))) + if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)), hidden = TRUE)) to_chat(wearer, span_notice("[gauntlets] [active ? "become loose around your fingers" : "tighten around your fingers and wrists"].")) playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) seal_part(gauntlets, seal = !active) - if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)))) + if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)), hidden = TRUE)) to_chat(wearer, span_notice("[chestplate] [active ? "releases your chest" : "cinches tightly against your chest"].")) playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) seal_part(chestplate, seal = !active) - if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)))) + if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)), hidden = TRUE)) to_chat(wearer, span_notice("[helmet] hisses [active ? "open" : "closed"].")) playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) seal_part(helmet, seal = !active) - if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)))) + if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer)), hidden = TRUE)) to_chat(wearer, span_notice("Systems [active ? "shut down. Parts unsealed. Goodbye" : "started up. Parts sealed. Welcome"], [wearer].")) if(ai_assistant) to_chat(ai_assistant, span_notice("SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[ai_assistant]\"")) @@ -218,21 +218,10 @@ part.heat_protection = NONE part.cold_protection = NONE part.alternate_worn_layer = mod_parts[part] - if(part == boots) - wearer.update_worn_shoes() - if(part == gauntlets) - wearer.update_worn_gloves() - if(part == chestplate) - wearer.update_worn_oversuit() - wearer.update_worn_undersuit() - if(part == helmet) - wearer.update_worn_head() - wearer.update_worn_mask() - wearer.update_worn_glasses() - wearer.update_body_parts() - // Close internal air tank if MOD helmet is unsealed and was the only breathing apparatus. - if (!seal && wearer?.invalid_internals()) - wearer.cutoff_internals() + wearer.update_clothing(part.slot_flags) + wearer.update_obscured_slots(part.visor_flags_inv) + if((part.clothing_flags & (MASKINTERNALS|HEADINTERNALS)) && wearer.invalid_internals()) + wearer.cutoff_internals() /// Finishes the suit's activation /obj/item/mod/control/proc/finish_activation(on) diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm index c3d5040c815..eab60af15df 100644 --- a/code/modules/mod/mod_link.dm +++ b/code/modules/mod/mod_link.dm @@ -203,7 +203,7 @@ /obj/item/clothing/neck/link_scryer/process(seconds_per_tick) if(!mod_link.link_call) return - cell.use(20 KILO WATTS * seconds_per_tick, force = TRUE) + cell.use(0.02 * STANDARD_CELL_RATE * seconds_per_tick, force = TRUE) /obj/item/clothing/neck/link_scryer/attackby(obj/item/attacked_by, mob/user, params) . = ..() diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 2aec3e361c4..adbcc2064f8 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -834,7 +834,7 @@ . = ..() if(!length(accepted_mats)) - accepted_mats = SSmaterials.materials_by_category[MAT_CATEGORY_SILO] + accepted_mats = DSmaterials.materials_by_category[MAT_CATEGORY_SILO] container = AddComponent( \ /datum/component/material_container, \ diff --git a/code/modules/mod/modules/modules_medical.dm b/code/modules/mod/modules/modules_medical.dm index 6068b18fe10..0e04de51c86 100644 --- a/code/modules/mod/modules/modules_medical.dm +++ b/code/modules/mod/modules/modules_medical.dm @@ -328,7 +328,7 @@ balloon_alert(mod.wearer, "interrupted!") return var/target_zones = body_zone2cover_flags(mod.wearer.zone_selected) - for(var/obj/item/clothing as anything in carbon_target.get_all_worn_items()) + for(var/obj/item/clothing as anything in carbon_target.get_equipped_items()) if(!clothing) continue var/shared_flags = target_zones & clothing.body_parts_covered diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index 868b4a79500..d52a5e1fb4c 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -133,10 +133,6 @@ icon_state = "hacker" removable = FALSE incompatible_modules = list(/obj/item/mod/module/hacker) - /// Minimum amount of energy we can drain in a single drain action - var/mindrain = 200 KILO JOULES - /// Maximum amount of energy we can drain in a single drain action - var/maxdrain = 400 KILO JOULES /// Whether or not the communication console hack was used to summon another antagonist. var/communication_console_hack_success = FALSE /// How many times the module has been used to force open doors. diff --git a/code/modules/modular_computers/file_system/programs/techweb.dm b/code/modules/modular_computers/file_system/programs/techweb.dm index a72eef1bc9a..2103e0d4a22 100644 --- a/code/modules/modular_computers/file_system/programs/techweb.dm +++ b/code/modules/modular_computers/file_system/programs/techweb.dm @@ -218,7 +218,7 @@ logname = "[id_card_of_human_user.registered_name]" stored_research.research_logs += list(list( "node_name" = tech_node.display_name, - "node_cost" = price["General Research"], + "node_cost" = price[TECHWEB_POINT_TYPE_GENERIC], "node_researcher" = logname, "node_research_location" = "[get_area(computer)] ([user.x],[user.y],[user.z])", )) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index e1bddd6feff..605e88f1e48 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -30,7 +30,7 @@ grind_results = list(/datum/reagent/cellulose = 3) color = COLOR_WHITE item_flags = SKIP_FANTASY_ON_SPAWN - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING /// Lazylist of raw, unsanitised, unparsed text inputs that have been made to the paper. var/list/datum/paper_input/raw_text_inputs diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm index 8baf59508b8..e3f9486bee9 100644 --- a/code/modules/plumbing/plumbers/_plumb_machinery.dm +++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm @@ -8,7 +8,8 @@ icon = 'icons/obj/pipes_n_cables/hydrochem/plumbers.dmi' icon_state = "pump" density = TRUE - idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 7.5 + processing_flags = START_PROCESSING_MANUALLY + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2.75 resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF ///Plumbing machinery is always gonna need reagents, so we might aswell put it here var/buffer = 50 @@ -26,11 +27,17 @@ . = ..() . += span_notice("The maximum volume display reads: [reagents.maximum_volume] units.") - /obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/tool) - . = ..() - default_unfasten_wrench(user, tool) - return ITEM_INTERACT_SUCCESS + if(user.combat_mode) + return NONE + + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + if(anchored) + begin_processing() + else + end_processing() + return ITEM_INTERACT_SUCCESS /obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) user.balloon_alert_to_viewers("furiously plunging...") diff --git a/code/modules/plumbing/plumbers/acclimator.dm b/code/modules/plumbing/plumbers/acclimator.dm index 79b525d3504..014ff849901 100644 --- a/code/modules/plumbing/plumbers/acclimator.dm +++ b/code/modules/plumbing/plumbers/acclimator.dm @@ -14,7 +14,6 @@ icon_state = "acclimator" base_icon_state = "acclimator" buffer = 200 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 ///towards wich temperature do we build? var/target_temperature = 300 @@ -32,7 +31,7 @@ AddComponent(/datum/component/plumbing/acclimator, bolt, layer) /obj/machinery/plumbing/acclimator/process(seconds_per_tick) - if(machine_stat & NOPOWER || !enabled || !reagents.total_volume || reagents.chem_temp == target_temperature) + if(!is_operational || !enabled || !reagents.total_volume || reagents.chem_temp == target_temperature) if(acclimate_state != NEUTRAL) acclimate_state = NEUTRAL update_appearance() diff --git a/code/modules/plumbing/plumbers/bottler.dm b/code/modules/plumbing/plumbers/bottler.dm index 1acbed37a74..5f63a3070bd 100644 --- a/code/modules/plumbing/plumbers/bottler.dm +++ b/code/modules/plumbing/plumbers/bottler.dm @@ -4,10 +4,8 @@ icon_state = "bottler" layer = ABOVE_ALL_MOB_LAYER plane = ABOVE_GAME_PLANE - reagent_flags = TRANSPARENT | DRAINABLE buffer = 100 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 ///how much do we fill var/wanted_amount = 10 @@ -71,7 +69,7 @@ to_chat(user, span_notice(" The [src] will now fill for [wanted_amount]u.")) /obj/machinery/plumbing/bottler/process(seconds_per_tick) - if(machine_stat & NOPOWER) + if(!is_operational) return // Sanity check the result locations and stop processing if they don't exist if(goodspot == null || badspot == null || inputspot == null) diff --git a/code/modules/plumbing/plumbers/destroyer.dm b/code/modules/plumbing/plumbers/destroyer.dm index 5f81e24eaf2..503b3e76223 100644 --- a/code/modules/plumbing/plumbers/destroyer.dm +++ b/code/modules/plumbing/plumbers/destroyer.dm @@ -3,7 +3,6 @@ desc = "Breaks down chemicals and annihilates them." icon_state = "disposal" pass_flags_self = PASSMACHINE | LETPASSTHROW // Small - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 ///we remove 5 reagents per second var/disposal_rate = 5 @@ -13,7 +12,7 @@ AddComponent(/datum/component/plumbing/simple_demand, bolt, layer) /obj/machinery/plumbing/disposer/process(seconds_per_tick) - if(machine_stat & NOPOWER) + if(!is_operational) return if(reagents.total_volume) if(icon_state != initial(icon_state) + "_working") //threw it here instead of update icon since it only has two states diff --git a/code/modules/plumbing/plumbers/fermenter.dm b/code/modules/plumbing/plumbers/fermenter.dm index 8800029779d..ac421bce740 100644 --- a/code/modules/plumbing/plumbers/fermenter.dm +++ b/code/modules/plumbing/plumbers/fermenter.dm @@ -6,7 +6,6 @@ plane = ABOVE_GAME_PLANE reagent_flags = TRANSPARENT | DRAINABLE buffer = 400 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 ///input dir var/eat_dir = SOUTH @@ -36,7 +35,7 @@ /// uses fermentation proc similar to fermentation barrels /obj/machinery/plumbing/fermenter/proc/ferment(atom/AM) - if(machine_stat & NOPOWER) + if(!is_operational) return if(reagents.holder_full()) return diff --git a/code/modules/plumbing/plumbers/grinder_chemical.dm b/code/modules/plumbing/plumbers/grinder_chemical.dm index ae356fef089..f75ec94f21c 100644 --- a/code/modules/plumbing/plumbers/grinder_chemical.dm +++ b/code/modules/plumbing/plumbers/grinder_chemical.dm @@ -4,10 +4,8 @@ icon_state = "grinder_chemical" layer = ABOVE_ALL_MOB_LAYER plane = ABOVE_GAME_PLANE - reagent_flags = TRANSPARENT | DRAINABLE buffer = 400 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 /obj/machinery/plumbing/grinder_chemical/Initialize(mapload, bolt, layer) . = ..() @@ -47,7 +45,7 @@ * * [AM][atom] - the atom to grind or juice */ /obj/machinery/plumbing/grinder_chemical/proc/grind(atom/AM) - if(machine_stat & NOPOWER) + if(!is_operational) return if(reagents.holder_full()) return @@ -56,11 +54,10 @@ var/obj/item/I = AM var/result - if(I.grind_results || I.juice_typepath) + if(I.grind_results) + result = I.grind(reagents, usr) + else + result = I.juice(reagents, usr) + if(result) use_energy(active_power_usage) - if(I.grind_results) - result = I.grind(reagents, usr) - else if (I.juice_typepath) - result = I.juice(reagents, usr) - if(result) - qdel(I) + qdel(I) diff --git a/code/modules/plumbing/plumbers/iv_drip.dm b/code/modules/plumbing/plumbers/iv_drip.dm index f9a5ae47598..6e258555384 100644 --- a/code/modules/plumbing/plumbers/iv_drip.dm +++ b/code/modules/plumbing/plumbers/iv_drip.dm @@ -6,6 +6,7 @@ base_icon_state = "plumb" density = TRUE use_internal_storage = TRUE + processing_flags = START_PROCESSING_MANUALLY /obj/machinery/iv_drip/plumbing/Initialize(mapload, bolt, layer) . = ..() @@ -29,10 +30,14 @@ reagents.expose(get_turf(src), TOUCH) //splash on the floor reagents.clear_reagents() - /obj/machinery/iv_drip/plumbing/wrench_act(mob/living/user, obj/item/tool) - if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) - return ITEM_INTERACT_SUCCESS + if(user.combat_mode) + return NONE -/obj/machinery/iv_drip/plumbing/on_deconstruction(disassembled) - qdel(src) + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + if(anchored) + begin_processing() + else + end_processing() + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/plumbing/plumbers/pill_press.dm b/code/modules/plumbing/plumbers/pill_press.dm index 5761474a959..dad5ad943b1 100644 --- a/code/modules/plumbing/plumbers/pill_press.dm +++ b/code/modules/plumbing/plumbers/pill_press.dm @@ -10,7 +10,6 @@ name = "chemical press" desc = "A press that makes pills, patches and bottles." icon_state = "pill_press" - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 /// current operating product (pills or patches) var/product = "pill" @@ -80,7 +79,7 @@ return container /obj/machinery/plumbing/pill_press/process(seconds_per_tick) - if(machine_stat & NOPOWER) + if(!is_operational) return //shift & check to account for floating point inaccuracies diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm index 9bdac2f98b2..59fcfaf7caf 100644 --- a/code/modules/plumbing/plumbers/reaction_chamber.dm +++ b/code/modules/plumbing/plumbers/reaction_chamber.dm @@ -9,7 +9,6 @@ icon_state = "reaction_chamber" buffer = 200 reagent_flags = TRANSPARENT | NO_REACT - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 /** * list of set reagents that the reaction_chamber allows in, and must all be present before mixing is enabled. @@ -49,23 +48,18 @@ return NONE /obj/machinery/plumbing/reaction_chamber/process(seconds_per_tick) - //half the power for getting reagents in - var/power_usage = active_power_usage * 0.5 + if(!is_operational || !reagents.total_volume) + return if(!emptying || reagents.is_reacting) //adjust temperature of final solution - var/temp_diff = target_temperature - reagents.chem_temp - if(abs(temp_diff) > 0.01) //if we are not close enough keep going - reagents.adjust_thermal_energy(temp_diff * HEATER_COEFFICIENT * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater + var/energy = (target_temperature - reagents.chem_temp) * HEATER_COEFFICIENT * seconds_per_tick * reagents.heat_capacity() + reagents.adjust_thermal_energy(energy) + use_energy(active_power_usage + abs(ROUND_UP(energy) / 120)) //do other stuff with final solution handle_reagents(seconds_per_tick) - //full power for doing reactions - power_usage *= 2 - - use_energy(power_usage * seconds_per_tick) - ///For subtypes that want to do additional reagent handling /obj/machinery/plumbing/reaction_chamber/proc/handle_reagents(seconds_per_tick) return diff --git a/code/modules/plumbing/plumbers/splitters.dm b/code/modules/plumbing/plumbers/splitters.dm index de279227009..b87a07d694c 100644 --- a/code/modules/plumbing/plumbers/splitters.dm +++ b/code/modules/plumbing/plumbers/splitters.dm @@ -3,7 +3,6 @@ name = "chemical splitter" desc = "A chemical splitter for smart chemical factorization. Waits till a set of conditions is met and then stops all input and splits the buffer evenly or other in two ducts." icon_state = "splitter" - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 buffer = 100 density = FALSE diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm index d7a5d83a251..0399ad85f3c 100644 --- a/code/modules/plumbing/plumbers/synthesizer.dm +++ b/code/modules/plumbing/plumbers/synthesizer.dm @@ -4,7 +4,6 @@ desc = "Produces a single chemical at a given volume. Must be plumbed. Most effective when working in unison with other chemical synthesizers, heaters and filters." icon_state = "synthesizer" icon = 'icons/obj/pipes_n_cables/hydrochem/plumbers.dmi' - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 ///Amount we produce for every process. Ideally keep under 5 since thats currently the standard duct capacity var/amount = 1 @@ -49,7 +48,7 @@ dispensable_reagents = default_reagents /obj/machinery/plumbing/synthesizer/process(seconds_per_tick) - if(machine_stat & NOPOWER || !reagent_id || !amount) + if(!is_operational || !reagent_id || !amount) return //otherwise we get leftovers, and we need this to be precise @@ -57,7 +56,7 @@ return reagents.add_reagent(reagent_id, amount) - use_energy(active_power_usage) + use_energy(active_power_usage * seconds_per_tick) /obj/machinery/plumbing/synthesizer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/modules/plumbing/plumbers/teleporter.dm b/code/modules/plumbing/plumbers/teleporter.dm index e1aa26532dc..df79220d15a 100644 --- a/code/modules/plumbing/plumbers/teleporter.dm +++ b/code/modules/plumbing/plumbers/teleporter.dm @@ -77,7 +77,7 @@ return TRUE /obj/machinery/plumbing/receiver/process(seconds_per_tick) - if(machine_stat & NOPOWER || panel_open) + if(!is_operational || panel_open) return if(senders.len) diff --git a/code/modules/plumbing/plumbers/vatgrower.dm b/code/modules/plumbing/plumbers/vatgrower.dm index ab2a732c9c5..7327a648dad 100644 --- a/code/modules/plumbing/plumbers/vatgrower.dm +++ b/code/modules/plumbing/plumbers/vatgrower.dm @@ -27,7 +27,7 @@ return NONE ///When we process, we make use of our reagents to try and feed the samples we have. -/obj/machinery/plumbing/growing_vat/process() +/obj/machinery/plumbing/growing_vat/process(seconds_per_tick) if(!is_operational) return if(!biological_sample) @@ -37,6 +37,7 @@ return playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE) audible_message(pick(list(span_notice("[src] grumbles!"), span_notice("[src] makes a splashing noise!"), span_notice("[src] sloshes!")))) + use_energy(active_power_usage * seconds_per_tick) ///Handles the petri dish depositing into the vat. /obj/machinery/plumbing/growing_vat/attacked_by(obj/item/I, mob/living/user) diff --git a/code/modules/power/apc/apc_main.dm b/code/modules/power/apc/apc_main.dm index 3dd2df590e1..3e09ff89205 100644 --- a/code/modules/power/apc/apc_main.dm +++ b/code/modules/power/apc/apc_main.dm @@ -17,6 +17,7 @@ damage_deflection = 10 resistance_flags = FIRE_PROOF interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON + interaction_flags_click = ALLOW_SILICON_REACH processing_flags = START_PROCESSING_MANUALLY ///Range of the light emitted when on @@ -636,7 +637,7 @@ /obj/machinery/power/apc/proc/overload_lighting() if(!operating || shorted) return - if(cell && cell.use(20 KILO JOULES)) + if(cell && cell.use(0.02 * STANDARD_CELL_CHARGE)) INVOKE_ASYNC(src, PROC_REF(break_lights)) /obj/machinery/power/apc/proc/break_lights() diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm index 6a8835cd5b7..0116205fdd4 100644 --- a/code/modules/power/apc/apc_tool_act.dm +++ b/code/modules/power/apc/apc_tool_act.dm @@ -168,7 +168,7 @@ if(machine_stat & BROKEN) balloon_alert(user, "frame is too damaged!") return ITEM_INTERACT_BLOCKING - if(!pseudocircuit.adapt_circuit(user, circuit_cost = 50 KILO JOULES)) + if(!pseudocircuit.adapt_circuit(user, circuit_cost = 0.05 * STANDARD_CELL_CHARGE)) return ITEM_INTERACT_BLOCKING user.visible_message( span_notice("[user] fabricates a circuit and places it into [src]."), @@ -182,7 +182,7 @@ if(machine_stat & MAINT) balloon_alert(user, "no board for a cell!") return ITEM_INTERACT_BLOCKING - if(!pseudocircuit.adapt_circuit(user, circuit_cost = 500 KILO JOULES)) + if(!pseudocircuit.adapt_circuit(user, circuit_cost = 0.5 * STANDARD_CELL_CHARGE)) return ITEM_INTERACT_BLOCKING var/obj/item/stock_parts/cell/crap/empty/bad_cell = new(src) bad_cell.forceMove(src) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 00b332e6608..59f1775f4e3 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -31,7 +31,7 @@ ///If the power cell was damaged by an explosion, chance for it to become corrupted and function the same as rigged. var/corrupted = FALSE ///How much power is given per second in a recharger. - var/chargerate = STANDARD_CELL_CHARGE * 0.05 + var/chargerate = STANDARD_CELL_RATE * 0.05 ///If true, the cell will state it's maximum charge in it's description var/ratingdesc = TRUE ///If it's a grown that acts as a battery, add a wire overlay to it. @@ -334,7 +334,7 @@ desc = "A power cell with a slightly higher capacity than normal!" maxcharge = STANDARD_CELL_CHARGE * 2.5 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.5) - chargerate = STANDARD_CELL_CHARGE * 0.5 + chargerate = STANDARD_CELL_RATE * 0.5 /obj/item/stock_parts/cell/upgraded/plus name = "upgraded power cell+" @@ -360,7 +360,7 @@ /obj/item/stock_parts/cell/pulse //200 pulse shots name = "pulse rifle power cell" maxcharge = STANDARD_CELL_CHARGE * 40 - chargerate = STANDARD_CELL_CHARGE * 0.75 + chargerate = STANDARD_CELL_RATE * 0.75 /obj/item/stock_parts/cell/pulse/carbine //25 pulse shots name = "pulse carbine power cell" @@ -375,14 +375,14 @@ icon_state = "bscell" maxcharge = STANDARD_CELL_CHARGE * 10 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.6) - chargerate = STANDARD_CELL_CHARGE + chargerate = STANDARD_CELL_RATE /obj/item/stock_parts/cell/high name = "high-capacity power cell" icon_state = "hcell" maxcharge = STANDARD_CELL_CHARGE * 10 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.6) - chargerate = STANDARD_CELL_CHARGE * 0.75 + chargerate = STANDARD_CELL_RATE * 0.75 /obj/item/stock_parts/cell/high/empty empty = TRUE @@ -392,7 +392,7 @@ icon_state = "scell" maxcharge = STANDARD_CELL_CHARGE * 20 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT * 3) - chargerate = STANDARD_CELL_CHARGE + chargerate = STANDARD_CELL_RATE /obj/item/stock_parts/cell/super/empty empty = TRUE @@ -402,7 +402,7 @@ icon_state = "hpcell" maxcharge = STANDARD_CELL_CHARGE * 30 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT * 4) - chargerate = STANDARD_CELL_CHARGE * 1.5 + chargerate = STANDARD_CELL_RATE * 1.5 /obj/item/stock_parts/cell/hyper/empty empty = TRUE @@ -413,7 +413,7 @@ icon_state = "bscell" maxcharge = STANDARD_CELL_CHARGE * 40 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*6) - chargerate = STANDARD_CELL_CHARGE * 2 + chargerate = STANDARD_CELL_RATE * 2 /obj/item/stock_parts/cell/bluespace/empty empty = TRUE @@ -486,7 +486,7 @@ name = "beam rifle capacitor" desc = "A high powered capacitor that can provide huge amounts of energy in an instant." maxcharge = STANDARD_CELL_CHARGE * 50 - chargerate = STANDARD_CELL_CHARGE * 2.5 //Extremely energy intensive + chargerate = STANDARD_CELL_RATE * 2.5 //Extremely energy intensive /obj/item/stock_parts/cell/beam_rifle/corrupt() return diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index 15135bee1a5..ec2139ad5d0 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -43,7 +43,7 @@ /obj/item/ammo_box/Initialize(mapload) . = ..() - custom_materials = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1) + custom_materials = DSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1) if(!start_empty) top_off(starting=TRUE) update_icon_state() diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index c584359b8ce..7481443bade 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -85,7 +85,7 @@ w_class = WEIGHT_CLASS_HUGE semi_auto = TRUE accepted_magazine_type = /obj/item/ammo_box/magazine/internal/shot/tube - interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING /// If defined, the secondary tube is this type, if you want different shell loads var/alt_mag_type /// If TRUE, we're drawing from the alternate_magazine diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 523f41af752..b9c8b7de41f 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -78,6 +78,9 @@ ammo_type = list(/obj/item/ammo_casing/energy/mindflayer) ammo_x_offset = 2 +/// amount of charge used up to start action (multiplied by amount) and per progress_flash_divisor ticks of welding +#define PLASMA_CUTTER_CHARGE_WELD (0.025 * STANDARD_CELL_CHARGE) + /obj/item/gun/energy/plasmacutter name = "plasma cutter" desc = "A mining tool capable of expelling concentrated plasma bursts. You could use it to cut limbs off xenos! Or, you know, mine stuff." @@ -91,13 +94,10 @@ sharpness = SHARP_EDGED can_charge = FALSE gun_flags = NOT_A_REAL_GUN - heat = 3800 usesound = list('sound/items/welder.ogg', 'sound/items/welder2.ogg') tool_behaviour = TOOL_WELDER toolspeed = 0.7 //plasmacutters can be used as welders, and are faster than standard welders - /// amount of charge used up to start action (multiplied by amount) and per progress_flash_divisor ticks of welding - var/charge_weld = 25 KILO JOULES /obj/item/gun/energy/plasmacutter/Initialize(mapload) AddElement(/datum/element/update_icon_blocker) @@ -126,7 +126,7 @@ balloon_alert(user, "already fully charged!") return I.use(1) - cell.give(500 KILO JOULES * charge_multiplier) + cell.give(0.5 * STANDARD_CELL_CHARGE * charge_multiplier) balloon_alert(user, "cell recharged") else ..() @@ -148,14 +148,14 @@ // Amount cannot be used if drain is made continuous, e.g. amount = 5, charge_weld = 25 // Then it'll drain 125 at first and 25 periodically, but fail if charge dips below 125 even though it still can finish action // Alternately it'll need to drain amount*charge_weld every period, which is either obscene or makes it free for other uses - if(amount ? cell.charge < charge_weld * amount : cell.charge < charge_weld) + if(amount ? cell.charge < PLASMA_CUTTER_CHARGE_WELD * amount : cell.charge < PLASMA_CUTTER_CHARGE_WELD) balloon_alert(user, "not enough charge!") return FALSE return TRUE /obj/item/gun/energy/plasmacutter/use(used) - return (!QDELETED(cell) && cell.use(used ? used * charge_weld : charge_weld)) + return (!QDELETED(cell) && cell.use(used ? used * PLASMA_CUTTER_CHARGE_WELD : PLASMA_CUTTER_CHARGE_WELD)) /obj/item/gun/energy/plasmacutter/use_tool(atom/target, mob/living/user, delay, amount=1, volume=0, datum/callback/extra_checks) @@ -169,6 +169,8 @@ else . = ..(amount=1) +#undef PLASMA_CUTTER_CHARGE_WELD + /obj/item/gun/energy/plasmacutter/adv name = "advanced plasma cutter" icon_state = "adv_plasmacutter" @@ -407,7 +409,7 @@ COOLDOWN_START(src, coin_regen_cd, coin_regen_rate) /obj/item/gun/energy/marksman_revolver/afterattack_secondary(atom/target, mob/living/user, params) - if(!can_see(user, get_turf(target), length = 9)) + if(!CAN_THEY_SEE(target, user)) return ..() if(max_coins && coin_count <= 0) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 76b2dbf7f96..3cf5b752400 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -31,8 +31,12 @@ QDEL_NULL(beaker) return ..() -/obj/machinery/chem_heater/on_deconstruction(disassembled) - beaker?.forceMove(drop_location()) +/obj/machinery/chem_heater/Exited(atom/movable/gone, direction) + . = ..() + if(gone == beaker) + UnregisterSignal(beaker.reagents, COMSIG_REAGENTS_REACTION_STEP) + beaker = null + update_appearance() /obj/machinery/chem_heater/add_context(atom/source, list/context, obj/item/held_item, mob/user) if(isnull(held_item) || (held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) @@ -58,7 +62,6 @@ return NONE - /obj/machinery/chem_heater/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) @@ -80,25 +83,17 @@ icon_state = "[base_icon_state][beaker ? 1 : 0]b" return ..() -/obj/machinery/chem_heater/Exited(atom/movable/gone, direction) - . = ..() - if(gone == beaker) - UnregisterSignal(beaker.reagents, COMSIG_REAGENTS_REACTION_STEP) - beaker = null - update_appearance() - /obj/machinery/chem_heater/RefreshParts() . = ..() heater_coefficient = 0.1 for(var/datum/stock_part/micro_laser/micro_laser in component_parts) heater_coefficient *= micro_laser.tier - /obj/machinery/chem_heater/item_interaction(mob/living/user, obj/item/held_item, list/modifiers) - if((held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) + if(user.combat_mode || (held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1) || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH)) return NONE - if(QDELETED(beaker)) + if(!QDELETED(beaker)) if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe)) var/obj/item/reagent_containers/injector = held_item injector.afterattack(beaker, user, proximity_flag = TRUE) @@ -113,16 +108,25 @@ return NONE /obj/machinery/chem_heater/wrench_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + . = ITEM_INTERACT_BLOCKING if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) return ITEM_INTERACT_SUCCESS /obj/machinery/chem_heater/screwdriver_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + . = ITEM_INTERACT_BLOCKING if(default_deconstruction_screwdriver(user, "mixer0b", "[base_icon_state][beaker ? 1 : 0]b", tool)) return ITEM_INTERACT_SUCCESS /obj/machinery/chem_heater/crowbar_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + . = ITEM_INTERACT_BLOCKING if(default_deconstruction_crowbar(tool)) return ITEM_INTERACT_SUCCESS @@ -174,12 +178,13 @@ PRIVATE_PROC(TRUE) //must be on and beaker must have something inside to heat - if(!on || (machine_stat & NOPOWER) || QDELETED(beaker) || !beaker.reagents.total_volume) + if(!on || !is_operational || QDELETED(beaker) || !beaker.reagents.total_volume) return FALSE //heat the beaker and use some power. we want to use only a small amount of power since this proc gets called frequently - beaker.reagents.adjust_thermal_energy((target_temperature - beaker.reagents.chem_temp) * heater_coefficient * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume) - use_energy(active_power_usage * seconds_per_tick * 0.3) + var/energy = (target_temperature - beaker.reagents.chem_temp) * heater_coefficient * seconds_per_tick * beaker.reagents.heat_capacity() + beaker.reagents.adjust_thermal_energy(energy) + use_energy(active_power_usage + abs(ROUND_UP(energy) / 120)) return TRUE /obj/machinery/chem_heater/proc/on_reaction_step(datum/reagents/holder, num_reactions, seconds_per_tick) diff --git a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm index ca75736db03..e11910a13af 100644 --- a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm +++ b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm @@ -241,11 +241,11 @@ lower_mass_range = calculate_mass(smallest = TRUE) upper_mass_range = calculate_mass(smallest = FALSE) estimate_time() - else //replace output beaker if(!QDELETED(beaker2)) try_put_in_hand(beaker2, user) beaker2 = new_beaker + log.Cut() update_appearance() @@ -258,8 +258,8 @@ return for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - //we don't bother about impure chems - if(istype(reagent, /datum/reagent/inverse) || (reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem)) + //we don't deal chems that are so impure that they are about to become inverted + if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) continue //out of our selected range if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) @@ -300,10 +300,7 @@ var/purity = target.purity var/is_inverse = FALSE - if(istype(reagent, /datum/reagent/inverse)) - log = "Too impure to use" //we don't bother about impure chems - is_inverse = TRUE - else if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) + if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) purity = target.get_inverse_purity() target = GLOB.chemical_reagents_list[reagent.inverse_chem] log = "Too impure to use" //we don't bother about impure chems @@ -352,13 +349,9 @@ /obj/machinery/chem_mass_spec/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() - if(.) + if(. || processing_reagents) return - if(processing_reagents) - balloon_alert(ui.user, "still processing") - return ..() - switch(action) if("activate") if(QDELETED(beaker1)) @@ -454,10 +447,7 @@ if(!processing_reagents) return PROCESS_KILL - if(!is_operational || panel_open || !anchored || (machine_stat & (BROKEN | NOPOWER))) - return - - if(!use_energy(active_power_usage * seconds_per_tick)) + if(!is_operational || panel_open || !anchored) return progress_time += seconds_per_tick @@ -467,8 +457,8 @@ log.Cut() for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - //we don't bother about impure chems - if(istype(reagent, /datum/reagent/inverse) || (reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem)) + //we don't deal chems that are so impure that they are about to become inverted + if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) continue //out of our selected range if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) @@ -489,3 +479,5 @@ estimate_time() update_appearance() return PROCESS_KILL + + use_energy(active_power_usage * seconds_per_tick) diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index c87a6196835..9bb645254e8 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -945,7 +945,7 @@ optimal_ph_min = 3 optimal_ph_max = 12 required_temp = 50 - reaction_flags = NONE //SKYRAT CHANGE, REACTION_INSTANT TO NONE + reaction_flags = REAGENT_SPLITRETAINVOL //SKYRAT EDIT CHANGE - ORIGINAL: reaction_flags = REACTION_INSTANT | REAGENT_SPLITRETAINVOL reaction_tags = REACTION_TAG_EASY | REACTION_TAG_UNIQUE /datum/chemical_reaction/ant_slurry // We're basically gluing ants together with synthflesh & maint sludge to make a bigger ant. diff --git a/code/modules/reagents/reagent_containers/misc.dm b/code/modules/reagents/reagent_containers/misc.dm index fa8d8cd3628..f631e8e28a0 100644 --- a/code/modules/reagents/reagent_containers/misc.dm +++ b/code/modules/reagents/reagent_containers/misc.dm @@ -32,7 +32,7 @@ if(on && (!cell || cell.charge <= 0)) //Check if we ran out of power change_power_status(FALSE) return FALSE - cell.use(5 KILO WATTS * seconds_per_tick) //Basic cell goes for like 200 seconds, bluespace for 8000 + cell.use(0.005 * STANDARD_CELL_RATE * seconds_per_tick) //Basic cell goes for like 200 seconds, bluespace for 8000 if(!reagents.total_volume) return FALSE var/max_temp = min(500 + (500 * (0.2 * cell.rating)), 1000) // 373 to 1000 diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 350f51492cf..e35a71e5d9b 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -100,7 +100,7 @@ reagent_puff.end_life() return - var/datum/move_loop/our_loop = SSmove_manager.move_towards_legacy(reagent_puff, target, wait_step, timeout = range * wait_step, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/our_loop = DSmove_manager.move_towards_legacy(reagent_puff, target, wait_step, timeout = range * wait_step, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) reagent_puff.RegisterSignal(our_loop, COMSIG_QDELETING, TYPE_PROC_REF(/obj/effect/decal/chempuff, loop_ended)) reagent_puff.RegisterSignal(our_loop, COMSIG_MOVELOOP_POSTPROCESS, TYPE_PROC_REF(/obj/effect/decal/chempuff, check_move)) diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm index 3c04bd924ec..6d5b270cd71 100644 --- a/code/modules/recycling/conveyor.dm +++ b/code/modules/recycling/conveyor.dm @@ -241,7 +241,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /obj/machinery/conveyor/proc/conveyable_enter(datum/source, atom/convayable) SIGNAL_HANDLER if(operating == CONVEYOR_OFF) - SSmove_manager.stop_looping(convayable, SSconveyors) + DSmove_manager.stop_looping(convayable, SSconveyors) return start_conveying(convayable) @@ -249,12 +249,12 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) SIGNAL_HANDLER var/has_conveyor = neighbors["[direction]"] if(convayable.z != z || !has_conveyor || !isturf(convayable.loc)) //If you've entered something on us, stop moving - SSmove_manager.stop_looping(convayable, SSconveyors) + DSmove_manager.stop_looping(convayable, SSconveyors) /obj/machinery/conveyor/proc/start_conveying(atom/movable/moving) if(QDELETED(moving)) return - var/datum/move_loop/move/moving_loop = SSmove_manager.processing_on(moving, SSconveyors) + var/datum/move_loop/move/moving_loop = DSmove_manager.processing_on(moving, SSconveyors) if(moving_loop) moving_loop.direction = movedir moving_loop.delay = speed * 1 SECONDS @@ -268,7 +268,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /obj/machinery/conveyor/proc/stop_conveying(atom/movable/thing) if(!ismovable(thing)) return - SSmove_manager.stop_looping(thing, SSconveyors) + DSmove_manager.stop_looping(thing, SSconveyors) // attack with item, place item on conveyor /obj/machinery/conveyor/attackby(obj/item/attacking_item, mob/living/user, params) diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index fff78f74bef..ecc33c240bf 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -78,7 +78,7 @@ /// Starts the movement process, persists while the holder is moving through pipes /obj/structure/disposalholder/proc/start_moving() var/delay = world.tick_lag - var/datum/move_loop/our_loop = SSmove_manager.move_disposals(src, delay = delay, timeout = delay * count) + var/datum/move_loop/our_loop = DSmove_manager.move_disposals(src, delay = delay, timeout = delay * count) if(our_loop) RegisterSignal(our_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(our_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(try_expel)) diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm index 16cd82c5650..5d5d3909ec7 100644 --- a/code/modules/religion/religion_sects.dm +++ b/code/modules/religion/religion_sects.dm @@ -200,11 +200,11 @@ if(!istype(power_cell)) return - if(power_cell.charge < 0.3 * STANDARD_CELL_CHARGE) + if(power_cell.charge() < 0.3 * STANDARD_CELL_CHARGE) to_chat(chap, span_notice("[GLOB.deity] does not accept pity amounts of power.")) return - adjust_favor(round(power_cell.charge/300), chap) + adjust_favor(round(power_cell.charge() / (0.3 * STANDARD_CELL_CHARGE)), chap) to_chat(chap, span_notice("You offer [power_cell]'s power to [GLOB.deity], pleasing them.")) qdel(power_cell) return TRUE diff --git a/code/modules/religion/rites.dm b/code/modules/religion/rites.dm index d907191c33d..af02fa72117 100644 --- a/code/modules/religion/rites.dm +++ b/code/modules/religion/rites.dm @@ -391,7 +391,7 @@ /datum/religion_rites/ceremonial_weapon/perform_rite(mob/living/user, atom/religious_tool) for(var/obj/item/stack/sheet/could_blade in get_turf(religious_tool)) - if(!(GET_MATERIAL_REF(could_blade.material_type) in SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL])) + if(!(GET_MATERIAL_REF(could_blade.material_type) in DSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL])) continue if(could_blade.amount < 5) continue diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 4532ec0d43d..987cbe77184 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -1411,6 +1411,36 @@ RND_CATEGORY_MECHFAB_CYBORG_MODULES + RND_SUBCATEGORY_MECHFAB_CYBORG_MODULES_MEDICAL ) +/datum/design/borg_upgrade_surgicalomnitool + name = "Advanced Surgical Omnitool Upgrade" + id = "borg_upgrade_surgicalomnitool" + build_type = MECHFAB + build_path = /obj/item/borg/upgrade/surgery_omnitool + materials = list( + /datum/material/iron=SHEET_MATERIAL_AMOUNT*5, + /datum/material/titanium=SHEET_MATERIAL_AMOUNT*3, + /datum/material/silver=SHEET_MATERIAL_AMOUNT*2, + ) + construction_time = 4 SECONDS + category = list( + RND_CATEGORY_MECHFAB_CYBORG_MODULES + RND_SUBCATEGORY_MECHFAB_CYBORG_MODULES_MEDICAL + ) + +/datum/design/borg_upgrade_engineeringomnitool + name = "Advanced Engineering Omnitool Upgrade" + id = "borg_upgrade_engineeringomnitool" + build_type = MECHFAB + build_path = /obj/item/borg/upgrade/engineering_omnitool + materials = list( + /datum/material/iron=SHEET_MATERIAL_AMOUNT*5, + /datum/material/titanium=SHEET_MATERIAL_AMOUNT*3, + /datum/material/gold=SHEET_MATERIAL_AMOUNT*2, + ) + construction_time = 4 SECONDS + category = list( + RND_CATEGORY_MECHFAB_CYBORG_MODULES + RND_SUBCATEGORY_MECHFAB_CYBORG_MODULES_ENGINEERING, + ) + /datum/design/borg_upgrade_trashofholding name = "Trash Bag of Holding" id = "borg_upgrade_trashofholding" diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index c7a7b320345..48afd76f624 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -1,8 +1,8 @@ /obj/machinery/rnd/production name = "technology fabricator" desc = "Makes researched and prototype items with materials and energy." - // Energy cost per full stack of materials spent. Material insertion is 40% of this. - active_power_usage = 50 * BASE_MACHINE_ACTIVE_CONSUMPTION + /// Energy cost per full stack of materials spent. Material insertion is 40% of this. + active_power_usage = 0.05 * STANDARD_CELL_RATE /// The efficiency coefficient. Material costs and print times are multiplied by this number; var/efficiency_coeff = 1 @@ -22,10 +22,6 @@ var/drop_direction = 0 /obj/machinery/rnd/production/Initialize(mapload) - . = ..() - - cached_designs = list() - materials = AddComponent( /datum/component/remote_materials, \ mapload, \ @@ -34,6 +30,10 @@ ) \ ) + . = ..() + + cached_designs = list() + RegisterSignal(src, COMSIG_SILO_ITEM_CONSUMED, TYPE_PROC_REF(/obj/machinery/rnd/production, silo_material_insert)) AddComponent( @@ -182,11 +182,10 @@ /obj/machinery/rnd/production/RefreshParts() . = ..() - if(materials) - var/total_storage = 0 - for(var/datum/stock_part/matter_bin/bin in component_parts) - total_storage += bin.tier * 37.5 * SHEET_MATERIAL_AMOUNT - materials.set_local_size(total_storage) + var/total_storage = 0 + for(var/datum/stock_part/matter_bin/bin in component_parts) + total_storage += bin.tier * 37.5 * SHEET_MATERIAL_AMOUNT + materials.set_local_size(total_storage) efficiency_coeff = compute_efficiency() diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 04d0c30d9e0..8e13c63f792 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -129,7 +129,7 @@ Nothing else in the console has ID requirements. logname = "[ID.registered_name]" stored_research.research_logs += list(list( "node_name" = TN.display_name, - "node_cost" = price["General Research"], + "node_cost" = price[TECHWEB_POINT_TYPE_GENERIC], "node_researcher" = logname, "node_research_location" = "[get_area(src)] ([src.x],[src.y],[src.z])", )) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 7d64e1878b8..8cadca9e134 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1022,6 +1022,7 @@ "borg_upgrade_rped", "borg_upgrade_hypermod", "borg_upgrade_inducer", + "borg_upgrade_engineeringomnitool", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) @@ -1037,6 +1038,7 @@ "borg_upgrade_piercinghypospray", "borg_upgrade_pinpointer", "borg_upgrade_surgicalprocessor", + "borg_upgrade_surgicalomnitool", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) diff --git a/code/modules/shuttle/assault_pod.dm b/code/modules/shuttle/assault_pod.dm index b628d7c5d84..d9a21cf5e23 100644 --- a/code/modules/shuttle/assault_pod.dm +++ b/code/modules/shuttle/assault_pod.dm @@ -28,6 +28,7 @@ var/width = 7 var/height = 7 var/lz_dir = 1 + var/lzname = "assault_pod" /obj/item/assault_pod/attack_self(mob/living/user) @@ -45,8 +46,8 @@ return var/turf/T = pick(turfs) var/obj/docking_port/stationary/landing_zone = new /obj/docking_port/stationary(T) - landing_zone.shuttle_id = "assault_pod([REF(src)])" - landing_zone.port_destinations = "assault_pod([REF(src)])" + landing_zone.shuttle_id = "[lzname]([REF(src)])" + landing_zone.port_destinations = "[lzname]([REF(src)])" landing_zone.name = "Landing Zone" landing_zone.dwidth = dwidth landing_zone.dheight = dheight @@ -61,3 +62,23 @@ to_chat(user, span_notice("Landing zone set.")) qdel(src) + +/obj/item/assault_pod/medieval //for the medieval pirates + name = "Shuttle placement designator" + icon = 'icons/obj/scrolls.dmi' + icon_state = "blueprints" + inhand_icon_state = null + desc = "A map of the station used to select where you want to land your shuttle." + shuttle_id = "pirate" + dwidth = 1 + dheight = 1 + width = 15 + height = 9 + lzname = "pirate" + +/obj/item/assault_pod/medieval/Initialize(mapload) + . = ..() + var/counter = length(SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/shuttle/pirate)) + if(counter != 1) + shuttle_id = "[shuttle_id]_[counter]" + lzname = "[lzname] [counter]" diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index a55bee71eb3..67f7a1b3588 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -6,8 +6,8 @@ //NORTH default dir /obj/docking_port invisibility = INVISIBILITY_ABSTRACT - icon = 'icons/obj/devices/tracker.dmi' - icon_state = "pinonfar" + icon = 'icons/effects/docking_ports.dmi' + icon_state = "static" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF anchored = TRUE @@ -436,7 +436,7 @@ /obj/docking_port/mobile name = "shuttle" - icon_state = "pinonclose" + icon_state = "mobile" area_type = SHUTTLE_DEFAULT_SHUTTLE_AREA_TYPE diff --git a/code/modules/surgery/bodyparts/head_hair_and_lips.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm index fbe219ba01f..bfe70f0f574 100644 --- a/code/modules/surgery/bodyparts/head_hair_and_lips.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -9,25 +9,10 @@ hair_hidden = FALSE facial_hair_hidden = FALSE if(human_head_owner) - if(human_head_owner.head) - var/obj/item/hat = human_head_owner.head - if(hat.flags_inv & HIDEHAIR) + for(var/obj/item/worn_item in human_head_owner.get_equipped_items()) + if(worn_item.flags_inv & HIDEHAIR) hair_hidden = TRUE - if(hat.flags_inv & HIDEFACIALHAIR) - facial_hair_hidden = TRUE - - if(human_head_owner.wear_mask) - var/obj/item/mask = human_head_owner.wear_mask - if(mask.flags_inv & HIDEHAIR) - hair_hidden = TRUE - if(mask.flags_inv & HIDEFACIALHAIR) - facial_hair_hidden = TRUE - - if(human_head_owner.w_uniform) - var/obj/item/item_uniform = human_head_owner.w_uniform - if(item_uniform.flags_inv & HIDEHAIR) - hair_hidden = TRUE - if(item_uniform.flags_inv & HIDEFACIALHAIR) + if(worn_item.flags_inv & HIDEFACIALHAIR) facial_hair_hidden = TRUE //invisibility and husk stuff if(HAS_TRAIT(human_head_owner, TRAIT_INVISIBLE_MAN) || HAS_TRAIT(human_head_owner, TRAIT_HUSK)) diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm index 87fc3db0af2..ae4ef6e4330 100644 --- a/code/modules/surgery/bone_mending.dm +++ b/code/modules/surgery/bone_mending.dm @@ -48,7 +48,7 @@ /datum/surgery_step/repair_bone_hairline name = "repair hairline fracture (bonesetter/bone gel/tape)" implements = list( - /obj/item/bonesetter = 100, + TOOL_BONESET = 100, /obj/item/stack/medical/bone_gel = 100, /obj/item/stack/sticky_tape/surgical = 100, /obj/item/stack/sticky_tape/super = 50, @@ -98,7 +98,7 @@ /datum/surgery_step/reset_compound_fracture name = "reset bone (bonesetter)" implements = list( - /obj/item/bonesetter = 100, + TOOL_BONESET = 100, /obj/item/stack/sticky_tape/surgical = 60, /obj/item/stack/sticky_tape/super = 40, /obj/item/stack/sticky_tape = 20) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index c2c23e9adad..2199e426440 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -114,6 +114,9 @@ fail_prob = min(max(0, modded_time - (time * SURGERY_SLOWDOWN_CAP_MULTIPLIER)),99)//if modded_time > time * modifier, then fail_prob = modded_time - time*modifier. starts at 0, caps at 99 modded_time = min(modded_time, time * SURGERY_SLOWDOWN_CAP_MULTIPLIER)//also if that, then cap modded_time at time*modifier + if(iscyborg(user))//any immunities to surgery slowdown should go in this check. + modded_time = time * tool.toolspeed + var/was_sleeping = (target.stat != DEAD && target.IsSleeping()) // Skyrat Edit Addition - reward for doing surgery on calm patients, and for using surgery rooms(ie. surgerying alone) @@ -129,10 +132,6 @@ modded_time *= SURGERY_SPEEDUP_AREA to_chat(user, span_notice("You are able to work faster due to the quiet environment!")) // Skyrat Edit End - // Skyrat Edit: Cyborgs are no longer immune to surgery speedups. - //if(iscyborg(user))//any immunities to surgery slowdown should go in this check. - //modded_time = time - // Skyrat Edit End if(do_after(user, modded_time, target = target, interaction_key = user.has_status_effect(/datum/status_effect/hippocratic_oath) ? target : DOAFTER_SOURCE_SURGERY)) //If we have the hippocratic oath, we can perform one surgery on each target, otherwise we can only do one surgery in total. diff --git a/code/modules/tgui_input/list.dm b/code/modules/tgui_input/list.dm index 174f16fc7b5..22c6d48edfc 100644 --- a/code/modules/tgui_input/list.dm +++ b/code/modules/tgui_input/list.dm @@ -111,7 +111,7 @@ /datum/tgui_list_input/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "ListInputModal") + ui = new(user, src, "ListInputWindow") ui.open() /datum/tgui_list_input/ui_close(mob/user) diff --git a/code/modules/unit_tests/lootpanel.dm b/code/modules/unit_tests/lootpanel.dm index c0bec13288c..1903c22d546 100644 --- a/code/modules/unit_tests/lootpanel.dm +++ b/code/modules/unit_tests/lootpanel.dm @@ -21,7 +21,7 @@ TEST_ASSERT_EQUAL(length(panel.contents), 1, "Contents should update on searchobj deleted") TEST_ASSERT_EQUAL(length(panel.to_image), 1, "to_image should update on searchobj deleted") - var/obj/item/storage/toolbox/new_box = allocate(/obj/item/storage/toolbox, one_over) + allocate(/obj/item/storage/toolbox, one_over) TEST_ASSERT_EQUAL(length(panel.contents), 1, "Contents shouldn't update, we're dumb") TEST_ASSERT_EQUAL(length(panel.to_image), 1, "to_image shouldn't update, we're dumb") @@ -32,3 +32,4 @@ TEST_ASSERT_EQUAL(length(panel.contents), 2, "Panel shouldnt dupe searchables if reopened") mock_client.mob = null + diff --git a/code/modules/unit_tests/organ_set_bonus.dm b/code/modules/unit_tests/organ_set_bonus.dm index b1a314ccda7..8e2c65270f7 100644 --- a/code/modules/unit_tests/organ_set_bonus.dm +++ b/code/modules/unit_tests/organ_set_bonus.dm @@ -22,7 +22,7 @@ /datum/infuser_entry/fly, )) // Fetch the globally instantiated DNA Infuser entries. - for(var/datum/infuser_entry/infuser_entry as anything in GLOB.infuser_entries) + for(var/datum/infuser_entry/infuser_entry as anything in flatten_list(GLOB.infuser_entries)) var/output_organs = infuser_entry.output_organs var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent) lab_rat.dna.mutant_bodyparts["moth_antennae"] = list(MUTANT_INDEX_NAME = "Plain", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF"), MUTANT_INDEX_EMISSIVE_LIST = list(FALSE)) // SKYRAT EDIT - Customization diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png index c8aaa0a7120..2c100632d34 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png differ diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index 995764e0bb7..9d059ba7e22 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -36,11 +36,11 @@ hud_possible = list(DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD) mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi' ///How much energy the mech will consume each time it moves. this is the current active energy consumed - var/step_energy_drain = 8 KILO JOULES + var/step_energy_drain = 0.008 * STANDARD_CELL_CHARGE ///How much energy we drain each time we mechpunch someone - var/melee_energy_drain = 15 KILO JOULES + var/melee_energy_drain = 0.015 * STANDARD_CELL_CHARGE ///Power we use to have the lights on - var/light_power_drain = 2 KILO WATTS + var/light_power_drain = 0.002 * STANDARD_CELL_RATE ///Modifiers for directional damage reduction var/list/facing_modifiers = list(MECHA_FRONT_ARMOUR = 0.5, MECHA_SIDE_ARMOUR = 1, MECHA_BACK_ARMOUR = 1.5) ///if we cant use our equipment(such as due to EMP) @@ -707,6 +707,26 @@ target.mech_melee_attack(src, user) TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown) + +/// Driver alt clicks anything while in mech +/obj/vehicle/sealed/mecha/proc/on_click_alt(mob/user, atom/target, params) + SIGNAL_HANDLER + + . = COMSIG_MOB_CANCEL_CLICKON // Cancel base_click_alt + + if(target != src) + return + + if(!(user in occupants)) + return + + if(!(user in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))) + to_chat(user, span_warning("You're in the wrong seat to control movement.")) + return + + toggle_strafe() + + /// middle mouse click signal wrapper for AI users /obj/vehicle/sealed/mecha/proc/on_middlemouseclick(mob/user, atom/target, params) SIGNAL_HANDLER diff --git a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm index 25fd2879a6b..8343dc85a54 100644 --- a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm @@ -10,7 +10,7 @@ desc = "Equipment for engineering and combat exosuits. This is the drill that'll pierce the heavens!" icon_state = "mecha_drill" equip_cooldown = 15 - energy_drain = 10 KILO JOULES + energy_drain = 0.01 * STANDARD_CELL_CHARGE force = 15 harmful = TRUE range = MECHA_MELEE diff --git a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm index 067ad2250f0..61853ef1cdc 100644 --- a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm @@ -9,7 +9,7 @@ desc = "An exosuit module that allows exosuits to teleport to any position in view." icon_state = "mecha_teleport" equip_cooldown = 150 - energy_drain = 1 MEGA JOULES + energy_drain = STANDARD_CELL_CHARGE range = MECHA_RANGED var/teleport_range = 7 @@ -129,7 +129,7 @@ /obj/item/mecha_parts/mecha_equipment/gravcatapult/proc/do_scatter(atom/movable/scatter, atom/movable/target) var/dist = 5 - get_dist(scatter, target) var/delay = 2 - SSmove_manager.move_away(scatter, target, delay = delay, timeout = delay * dist, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + DSmove_manager.move_away(scatter, target, delay = delay, timeout = delay * dist, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) /obj/item/mecha_parts/mecha_equipment/gravcatapult/get_snowflake_data() return list( @@ -285,7 +285,7 @@ ///Maximum fuel capacity of the generator, in units var/max_fuel = 75 * SHEET_MATERIAL_AMOUNT ///Energy recharged per second - var/rechargerate = 5 KILO WATTS + var/rechargerate = 0.005 * STANDARD_CELL_RATE /obj/item/mecha_parts/mecha_equipment/generator/Initialize(mapload) . = ..() diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm index e04a40b05f6..c10df9a139c 100644 --- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm @@ -7,7 +7,7 @@ desc = "Equipment for engineering exosuits. Lifts objects and loads them into cargo." icon_state = "mecha_clamp" equip_cooldown = 15 - energy_drain = 10 KILO JOULES + energy_drain = 0.01 * STANDARD_CELL_CHARGE tool_behaviour = TOOL_RETRACTOR range = MECHA_MELEE toolspeed = 0.8 diff --git a/code/modules/vehicles/mecha/mech_bay.dm b/code/modules/vehicles/mecha/mech_bay.dm index 1f468565625..1a6ce31e284 100644 --- a/code/modules/vehicles/mecha/mech_bay.dm +++ b/code/modules/vehicles/mecha/mech_bay.dm @@ -12,7 +12,7 @@ ///Ref to charge console for seeing charge for this port, cyclical reference var/obj/machinery/computer/mech_bay_power_console/recharge_console ///Power unit per second to charge by - var/recharge_power = 25 KILO WATTS + var/recharge_power = 0.025 * STANDARD_CELL_RATE ///turf that will be checked when a mech wants to charge. directly one turf in the direction it is facing var/turf/recharging_turf @@ -46,7 +46,7 @@ var/total_rating = 0 for(var/datum/stock_part/capacitor/capacitor in component_parts) total_rating += capacitor.tier - recharge_power = total_rating * 12.5 KILO WATTS + recharge_power = total_rating * 0.0125 * STANDARD_CELL_RATE /obj/machinery/mech_bay_recharge_port/examine(mob/user) . = ..() @@ -65,7 +65,7 @@ if(!recharging_mech?.cell) return if(recharging_mech.cell.charge < recharging_mech.cell.maxcharge) - if(!use_energy(active_power_usage * seconds_per_tick)) + if(!use_energy(active_power_usage * seconds_per_tick, force = FALSE)) return charge_cell(recharge_power * seconds_per_tick, recharging_mech.cell, grid_only = TRUE) else diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm index d544c829667..322a1189053 100644 --- a/code/modules/vehicles/mecha/mecha_actions.dm +++ b/code/modules/vehicles/mecha/mecha_actions.dm @@ -91,15 +91,6 @@ chassis.toggle_strafe() -/obj/vehicle/sealed/mecha/click_alt(mob/living/user) - if(!(user in occupants)) - return CLICK_ACTION_BLOCKING - if(!(user in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))) - to_chat(user, span_warning("You're in the wrong seat to control movement.")) - return CLICK_ACTION_BLOCKING - - toggle_strafe() - return CLICK_ACTION_SUCCESS /obj/vehicle/sealed/mecha/proc/toggle_strafe() if(!(mecha_flags & CAN_STRAFE)) @@ -108,7 +99,9 @@ strafe = !strafe - to_chat(occupants, "strafing mode [strafe?"on":"off"].") + for(var/mob/occupant in occupants) + balloon_alert(occupant, "strafing [strafe?"on":"off"]") + occupant.playsound_local(src, 'sound/machines/terminal_eject.ogg', 50, TRUE) log_message("Toggled strafing mode [strafe?"on":"off"].", LOG_MECHA) for(var/occupant in occupants) diff --git a/code/modules/vehicles/mecha/mecha_mob_interaction.dm b/code/modules/vehicles/mecha/mecha_mob_interaction.dm index 7accab008f1..d16e4af1541 100644 --- a/code/modules/vehicles/mecha/mecha_mob_interaction.dm +++ b/code/modules/vehicles/mecha/mecha_mob_interaction.dm @@ -159,24 +159,26 @@ setDir(SOUTH) return ..() -/obj/vehicle/sealed/mecha/add_occupant(mob/M, control_flags) - RegisterSignal(M, COMSIG_MOB_CLICKON, PROC_REF(on_mouseclick), TRUE) - RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(display_speech_bubble), TRUE) - RegisterSignal(M, COMSIG_MOVABLE_KEYBIND_FACE_DIR, PROC_REF(on_turn), TRUE) +/obj/vehicle/sealed/mecha/add_occupant(mob/driver, control_flags) + RegisterSignal(driver, COMSIG_MOB_CLICKON, PROC_REF(on_mouseclick), TRUE) + RegisterSignal(driver, COMSIG_MOB_SAY, PROC_REF(display_speech_bubble), TRUE) + RegisterSignal(driver, COMSIG_MOVABLE_KEYBIND_FACE_DIR, PROC_REF(on_turn), TRUE) + RegisterSignal(driver, COMSIG_MOB_ALTCLICKON, PROC_REF(on_click_alt)) . = ..() update_appearance() -/obj/vehicle/sealed/mecha/remove_occupant(mob/M) - UnregisterSignal(M, list( +/obj/vehicle/sealed/mecha/remove_occupant(mob/driver) + UnregisterSignal(driver, list( COMSIG_MOB_CLICKON, COMSIG_MOB_SAY, COMSIG_MOVABLE_KEYBIND_FACE_DIR, + COMSIG_MOB_ALTCLICKON, )) - M.clear_alert(ALERT_CHARGE) - M.clear_alert(ALERT_MECH_DAMAGE) - if(M.client) - M.update_mouse_pointer() - M.client.view_size.resetToDefault() + driver.clear_alert(ALERT_CHARGE) + driver.clear_alert(ALERT_MECH_DAMAGE) + if(driver.client) + driver.update_mouse_pointer() + driver.client.view_size.resetToDefault() zoom_mode = FALSE . = ..() update_appearance() diff --git a/code/modules/vehicles/motorized_wheelchair.dm b/code/modules/vehicles/motorized_wheelchair.dm index 128530968e2..8dbdfd93e8f 100644 --- a/code/modules/vehicles/motorized_wheelchair.dm +++ b/code/modules/vehicles/motorized_wheelchair.dm @@ -10,7 +10,7 @@ ///Self explanatory, ratio of how much power we use var/power_efficiency = 1 ///How much energy we use - var/energy_usage = 100 KILO JOULES + var/energy_usage = 0.1 * STANDARD_CELL_CHARGE ///whether the panel is open so a user can take out the cell var/panel_open = FALSE ///Parts used in building the wheelchair diff --git a/code/modules/wiremod/shell/gun.dm b/code/modules/wiremod/shell/gun.dm index ff581536713..9f196e6c1fc 100644 --- a/code/modules/wiremod/shell/gun.dm +++ b/code/modules/wiremod/shell/gun.dm @@ -82,6 +82,6 @@ if(!parent?.cell) return var/obj/item/gun/energy/fired_gun = source - var/totransfer = min(100 KILO JOULES, parent.cell.charge) - var/transferred = fired_gun.cell.give(totransfer) - parent.cell.use(transferred) + var/transferred = fired_gun.cell.give(min(0.1 * STANDARD_CELL_CHARGE, parent.cell.charge)) + if(transferred) + parent.cell.use(transferred, force = TRUE) diff --git a/icons/effects/docking_ports.dmi b/icons/effects/docking_ports.dmi new file mode 100644 index 00000000000..96909d7bd0f Binary files /dev/null and b/icons/effects/docking_ports.dmi differ diff --git a/icons/effects/vent_overlays.dmi b/icons/effects/vent_overlays.dmi index 54ac3d7a819..375117f4c79 100644 Binary files a/icons/effects/vent_overlays.dmi and b/icons/effects/vent_overlays.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 1b597f0d33d..30469c85dae 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index 65ec3828d42..b0e74178ce1 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/belt_mirror.dmi b/icons/mob/clothing/belt_mirror.dmi index 4f7f64db8c6..37658b154db 100644 Binary files a/icons/mob/clothing/belt_mirror.dmi and b/icons/mob/clothing/belt_mirror.dmi differ diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi index d0e5093d459..a670c33b7dc 100644 Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi index 317edb56796..74df620a572 100644 Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ diff --git a/icons/mob/clothing/suits/armor.dmi b/icons/mob/clothing/suits/armor.dmi index 90be12b694a..3f51d089d9b 100644 Binary files a/icons/mob/clothing/suits/armor.dmi and b/icons/mob/clothing/suits/armor.dmi differ diff --git a/icons/mob/clothing/under/costume.dmi b/icons/mob/clothing/under/costume.dmi index a3b6c7e5050..34703c07058 100644 Binary files a/icons/mob/clothing/under/costume.dmi and b/icons/mob/clothing/under/costume.dmi differ diff --git a/icons/mob/inhands/equipment/shields_lefthand.dmi b/icons/mob/inhands/equipment/shields_lefthand.dmi index ce99a16d476..1aa27021b9e 100644 Binary files a/icons/mob/inhands/equipment/shields_lefthand.dmi and b/icons/mob/inhands/equipment/shields_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_righthand.dmi b/icons/mob/inhands/equipment/shields_righthand.dmi index 1c9c990b43d..4227ba00792 100644 Binary files a/icons/mob/inhands/equipment/shields_righthand.dmi and b/icons/mob/inhands/equipment/shields_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/axes_lefthand.dmi b/icons/mob/inhands/weapons/axes_lefthand.dmi index 7a0f4fdd592..8352626ce27 100644 Binary files a/icons/mob/inhands/weapons/axes_lefthand.dmi and b/icons/mob/inhands/weapons/axes_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/axes_righthand.dmi b/icons/mob/inhands/weapons/axes_righthand.dmi index 42cb6350746..7c026e12b66 100644 Binary files a/icons/mob/inhands/weapons/axes_righthand.dmi and b/icons/mob/inhands/weapons/axes_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/polearms_lefthand.dmi b/icons/mob/inhands/weapons/polearms_lefthand.dmi index f9b43790df7..a1355ed9c40 100644 Binary files a/icons/mob/inhands/weapons/polearms_lefthand.dmi and b/icons/mob/inhands/weapons/polearms_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/polearms_righthand.dmi b/icons/mob/inhands/weapons/polearms_righthand.dmi index 9f7e6239895..05665fbaf95 100644 Binary files a/icons/mob/inhands/weapons/polearms_righthand.dmi and b/icons/mob/inhands/weapons/polearms_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi index e0a33fbcee3..6a0520ac9da 100644 Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi index fcdac64bdca..29db3057a2a 100644 Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ diff --git a/icons/mob/silicon/robot_items.dmi b/icons/mob/silicon/robot_items.dmi index e18a9d08f86..5ad091d6c9f 100644 Binary files a/icons/mob/silicon/robot_items.dmi and b/icons/mob/silicon/robot_items.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index d8a2fc0bd13..d5099c64e7f 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi index 3bea00dcdc3..02281abe6a3 100644 Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ diff --git a/icons/obj/clothing/suits/armor.dmi b/icons/obj/clothing/suits/armor.dmi index 4fb7248dbd8..480d6d9102c 100644 Binary files a/icons/obj/clothing/suits/armor.dmi and b/icons/obj/clothing/suits/armor.dmi differ diff --git a/icons/obj/clothing/under/costume.dmi b/icons/obj/clothing/under/costume.dmi index 90bdc205d52..85a49d1b330 100644 Binary files a/icons/obj/clothing/under/costume.dmi and b/icons/obj/clothing/under/costume.dmi differ diff --git a/icons/obj/devices/tracker.dmi b/icons/obj/devices/tracker.dmi index 0508fe816bc..59884c0aff8 100644 Binary files a/icons/obj/devices/tracker.dmi and b/icons/obj/devices/tracker.dmi differ diff --git a/icons/obj/items_cyborg.dmi b/icons/obj/items_cyborg.dmi index f43d9615313..39624fce676 100644 Binary files a/icons/obj/items_cyborg.dmi and b/icons/obj/items_cyborg.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 1bb6689becf..cf6cdbdf0d8 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/obj/weapons/fireaxe.dmi b/icons/obj/weapons/fireaxe.dmi index c89ea533cbe..a4743f680ad 100644 Binary files a/icons/obj/weapons/fireaxe.dmi and b/icons/obj/weapons/fireaxe.dmi differ diff --git a/icons/obj/weapons/shields.dmi b/icons/obj/weapons/shields.dmi index 7c4be107566..99e9b06aa40 100644 Binary files a/icons/obj/weapons/shields.dmi and b/icons/obj/weapons/shields.dmi differ diff --git a/icons/obj/weapons/spear.dmi b/icons/obj/weapons/spear.dmi index 7262da01c45..7c044d362a7 100644 Binary files a/icons/obj/weapons/spear.dmi and b/icons/obj/weapons/spear.dmi differ diff --git a/icons/obj/weapons/sword.dmi b/icons/obj/weapons/sword.dmi index 255c3b0cffd..5dca921bd5b 100644 Binary files a/icons/obj/weapons/sword.dmi and b/icons/obj/weapons/sword.dmi differ diff --git a/modular_skyrat/master_files/code/modules/antagonists/pirate/pirate_outfits.dm b/modular_skyrat/master_files/code/modules/antagonists/pirate/pirate_outfits.dm index 95d1e38dae6..5899a5948a0 100644 --- a/modular_skyrat/master_files/code/modules/antagonists/pirate/pirate_outfits.dm +++ b/modular_skyrat/master_files/code/modules/antagonists/pirate/pirate_outfits.dm @@ -7,3 +7,6 @@ /datum/outfit/pirate/irs back = /obj/item/storage/backpack/satchel/leather + +/datum/outfit/pirate/medieval/warlord + backpack_contents = null diff --git a/modular_skyrat/master_files/code/modules/clothing/head/_head.dm b/modular_skyrat/master_files/code/modules/clothing/head/_head.dm index 970d1ec8caf..8351337d602 100644 --- a/modular_skyrat/master_files/code/modules/clothing/head/_head.dm +++ b/modular_skyrat/master_files/code/modules/clothing/head/_head.dm @@ -8,7 +8,7 @@ return if(slot & ITEM_SLOT_HEAD) if(user.ears && (flags_inv & HIDEEARS)) - user.update_inv_ears() + user.update_worn_ears() if(!(user.bodyshape & BODYSHAPE_ALT_FACEWEAR_LAYER)) return if(!isnull(alternate_worn_layer) && alternate_worn_layer < BODY_FRONT_LAYER) // if the alternate worn layer was already lower than snouts then leave it be @@ -27,7 +27,7 @@ /obj/item/clothing/head/proc/update_on_removed(mob/living/carbon/user, obj/item/hat) SIGNAL_HANDLER if(istype(user) && user.ears) - user.update_inv_ears() + user.update_worn_ears() UnregisterSignal(user, COMSIG_CARBON_UNEQUIP_HAT) /obj/item/clothing/head/bio_hood diff --git a/modular_skyrat/master_files/code/modules/clothing/head/hardhat.dm b/modular_skyrat/master_files/code/modules/clothing/head/hardhat.dm new file mode 100644 index 00000000000..d43fddb414d --- /dev/null +++ b/modular_skyrat/master_files/code/modules/clothing/head/hardhat.dm @@ -0,0 +1,12 @@ +/obj/item/clothing/head/utility/hardhat/welding + /// The path to the visor sprite, used for muzzled visors + var/visor_sprite_path + +// Lets the visor not smush the snout +/obj/item/clothing/head/utility/hardhat/welding/adjust_visor(mob/living/user) + . = ..() + var/mob/living/carbon/carbon_user = user + if(carbon_user.dna.species.mutant_bodyparts["snout"]) + visor_sprite_path = 'modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi' + else + visor_sprite_path = 'icons/mob/clothing/head/utility.dmi' diff --git a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm index 64e199150f2..e7e760a6f27 100644 --- a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm +++ b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm @@ -68,7 +68,7 @@ /obj/machinery/ammo_workbench/Initialize(mapload) AddComponent( \ /datum/component/material_container, \ - SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ + DSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], \ 200000, \ MATCONTAINER_EXAMINE, \ allowed_items = /obj/item/stack, \ diff --git a/modular_skyrat/modules/borgs/code/robot_model.dm b/modular_skyrat/modules/borgs/code/robot_model.dm index 8c94520ad0d..3f660d87956 100644 --- a/modular_skyrat/modules/borgs/code/robot_model.dm +++ b/modular_skyrat/modules/borgs/code/robot_model.dm @@ -383,9 +383,9 @@ /obj/item/borg/sight/thermal, /obj/item/extinguisher, /obj/item/weldingtool/electric, - /obj/item/screwdriver/cyborg/power, + /obj/item/borg/cyborg_omnitool/engineering, /obj/item/crowbar/cyborg/power, - /obj/item/multitool/cyborg, + /obj/item/screwdriver/cyborg/power, /obj/item/construction/rcd/borg/syndicate, /obj/item/lightreplacer/cyborg, /obj/item/stack/sheet/iron, @@ -528,9 +528,9 @@ /obj/item/restraints/handcuffs/cable/zipties, /obj/item/extinguisher, /obj/item/weldingtool/electric, - /obj/item/screwdriver/cyborg/power, + /obj/item/borg/cyborg_omnitool/engineering, /obj/item/crowbar/cyborg/power, - /obj/item/multitool/cyborg, + /obj/item/screwdriver/cyborg/power, /obj/item/stack/sheet/iron, /obj/item/stack/sheet/glass, /obj/item/borg/apparatus/sheet_manipulator, diff --git a/modular_skyrat/modules/clock_cult/code/items/clothing.dm b/modular_skyrat/modules/clock_cult/code/items/clothing.dm index c2e9fca5478..9580234ea3f 100644 --- a/modular_skyrat/modules/clock_cult/code/items/clothing.dm +++ b/modular_skyrat/modules/clock_cult/code/items/clothing.dm @@ -191,7 +191,7 @@ if(iscarbon(user)) var/mob/living/carbon/carbon_user = user - carbon_user.head_update(src, forced = TRUE) + carbon_user.update_worn_head() /// "enable" the spectacles, flipping them down and applying their effects, calling on_toggle_eyes() if someone is wearing them @@ -294,7 +294,7 @@ if(iscarbon(user)) var/mob/living/carbon/carbon_user = user - carbon_user.head_update(src, forced = TRUE) + carbon_user.update_worn_head() /// Turn on the visor, calling apply_to_wearer() and changing the icon state diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm b/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm index 57365317844..25f8e9237ce 100644 --- a/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm +++ b/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm @@ -38,7 +38,7 @@ to_chat(user, "You pull the balaclava up to cover your whole head.") open = 0 user.update_body_parts() - user.update_inv_ears() + user.update_worn_ears() user.update_worn_mask() //Updates mob icons /obj/item/clothing/mask/balaclavaadjust/attack_self(mob/user) diff --git a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm index b68119246c1..c24656d17b2 100644 --- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm +++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm @@ -283,10 +283,10 @@ interaction_flags_click = NEED_DEXTERITY /obj/item/clothing/mask/gas/nightlight/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) /obj/item/clothing/mask/gas/nightlight/click_alt(mob/user) - adjustmask(user) + adjust_visor(user) return CLICK_ACTION_SUCCESS /obj/item/clothing/mask/gas/nightlight/examine(mob/user) @@ -489,7 +489,7 @@ to_chat(user, span_notice("You focus all your willpower to put the goggles down on your eyes.")) goggles = !goggles if(user) - user.head_update(src, forced = 1) + user.update_worn_head() user.update_mob_action_buttons() /obj/item/clothing/head/avipilot/ui_action_click(mob/living/carbon/user, action) @@ -923,7 +923,7 @@ slot_flags = up ? ITEM_SLOT_EYES | ITEM_SLOT_HEAD : ITEM_SLOT_EYES toggle_vision_effects() -/obj/item/clothing/glasses/welding/steampunk_goggles/weldingvisortoggle(mob/user) +/obj/item/clothing/glasses/welding/steampunk_goggles/adjust_visor(mob/user) . = ..() handle_sight_updating(user) @@ -950,7 +950,7 @@ playsound(user, shutters_sound, 100, TRUE) if(iscarbon(user)) var/mob/living/carbon/carbon_user = user - carbon_user.head_update(src, forced = 1) + carbon_user.update_worn_head() update_item_action_buttons() return TRUE @@ -982,7 +982,7 @@ if(iscarbon(user)) var/mob/living/carbon/carbon_user = user carbon_user.update_tint() - carbon_user.head_update(src, forced = TRUE) + carbon_user.update_worn_head() /obj/item/clothing/glasses/welding/steampunk_goggles/ui_action_click(mob/user, actiontype, is_welding_toggle = FALSE) if(!is_welding_toggle) diff --git a/modular_skyrat/modules/ghostcafe/code/robot_ghostcafe.dm b/modular_skyrat/modules/ghostcafe/code/robot_ghostcafe.dm index 760ec0fd526..d8f9ca2ce28 100644 --- a/modular_skyrat/modules/ghostcafe/code/robot_ghostcafe.dm +++ b/modular_skyrat/modules/ghostcafe/code/robot_ghostcafe.dm @@ -39,8 +39,8 @@ /obj/item/assembly/flash/cyborg, /obj/item/extinguisher/mini, /obj/item/weldingtool/largetank/cyborg, - /obj/item/screwdriver/cyborg/power, // Combines Screwdriver and Wrench into one - /obj/item/crowbar/cyborg/power, // Combines Crowbar and Wirecutters into one + /obj/item/borg/cyborg_omnitool/engineering, + /obj/item/borg/cyborg_omnitool/engineering, /obj/item/multitool/cyborg, /obj/item/stack/sheet/iron, /obj/item/stack/sheet/glass, diff --git a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm index ba8ea2defbb..2e27eb71d4d 100644 --- a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm +++ b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm @@ -256,7 +256,7 @@ user.update_worn_head() if(iscarbon(user)) var/mob/living/carbon/carbon_user = user - carbon_user.head_update(src, forced = TRUE) + carbon_user.update_worn_head() //Beret replacement diff --git a/modular_skyrat/modules/implants/code/augments_arms.dm b/modular_skyrat/modules/implants/code/augments_arms.dm index 4cc168247f4..aefb5c076fd 100644 --- a/modular_skyrat/modules/implants/code/augments_arms.dm +++ b/modular_skyrat/modules/implants/code/augments_arms.dm @@ -148,7 +148,7 @@ name = "hacking arm implant" desc = "An small arm implant containing an advanced screwdriver, wirecutters, and multitool designed for engineers and on-the-field machine modification. Actually legal, despite what the name may make you think." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "multitool_cyborg" + icon_state = "toolkit_engiborg_multitool" items_to_create = list(/obj/item/screwdriver/cyborg, /obj/item/wirecutters/cyborg, /obj/item/multitool/abductor/implant) /obj/item/organ/internal/cyberimp/arm/botany @@ -188,7 +188,7 @@ name = "multitool" desc = "An optimized, highly advanced stripped-down multitool able to interface with electronics far better than its standard counterpart." icon = 'icons/obj/items_cyborg.dmi' - icon_state = "multitool_cyborg" + icon_state = "toolkit_engiborg_multitool" /obj/item/organ/internal/cyberimp/arm/janitor name = "janitorial tools implant" diff --git a/modular_skyrat/modules/medical/code/anesthetic_machine.dm b/modular_skyrat/modules/medical/code/anesthetic_machine.dm index eb42dda946e..e15fcc09062 100644 --- a/modular_skyrat/modules/medical/code/anesthetic_machine.dm +++ b/modular_skyrat/modules/medical/code/anesthetic_machine.dm @@ -151,7 +151,7 @@ return PROCESS_KILL // Attempt to restart airflow if it was temporarily interrupted after mask adjustment. - if(attached_tank && istype(carbon_target) && !carbon_target.external && !attached_mask.mask_adjusted) + if(attached_tank && istype(carbon_target) && !carbon_target.external && !attached_mask.up) carbon_target.open_internals(attached_tank, is_external = TRUE) /obj/machinery/anesthetic_machine/Destroy() @@ -210,12 +210,12 @@ to_chat(user, span_notice("[src] retracts back into the [our_machine].")) our_machine.retract_mask() -/obj/item/clothing/mask/breath/anesthetic/adjustmask(mob/living/carbon/user) +/obj/item/clothing/mask/breath/anesthetic/adjust_visor(mob/living/carbon/user) . = ..() // Air only goes through the mask, so temporarily pause airflow if mask is getting adjusted. // Since the mask is NODROP, the only possible user is the wearer var/mob/living/carbon/carbon_target = loc - if(mask_adjusted && carbon_target.external) + if(up && carbon_target.external) carbon_target.close_externals() /// A boxed version of the Anesthetic Machine. This is what is printed from the medical prolathe. diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/washing_machine.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/washing_machine.dm index 4da5f240d41..176750d8d64 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/washing_machine.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/washing_machine.dm @@ -20,7 +20,7 @@ continue var/covered = FALSE - for (var/obj/item/clothing/iter_clothing in buckled_human.get_all_worn_items()) + for (var/obj/item/clothing/iter_clothing in buckled_human.get_equipped_items()) if (!(iter_clothing.body_parts_covered & GROIN)) continue if (iter_clothing.clothing_flags & THICKMATERIAL) diff --git a/modular_skyrat/modules/primitive_catgirls/code/clothing.dm b/modular_skyrat/modules/primitive_catgirls/code/clothing.dm index 9c7a378c3ff..a053558992b 100644 --- a/modular_skyrat/modules/primitive_catgirls/code/clothing.dm +++ b/modular_skyrat/modules/primitive_catgirls/code/clothing.dm @@ -125,7 +125,7 @@ actions_types = list(/datum/action/item_action/adjust) /obj/item/clothing/mask/primitive_catgirl_greyscale_gaiter/attack_self(mob/user) - adjustmask(user) + adjust_visor(user) // Head diff --git a/strings/pirates.json b/strings/pirates.json index 22e0e9861b9..191cc927de7 100644 --- a/strings/pirates.json +++ b/strings/pirates.json @@ -270,5 +270,22 @@ "Mass of Fermenting Dregs", "Bloody Valentine", "Wild Nothing" + ], + "medieval_names":[ + "Head Reaper", + "The Lords Judgement", + "The Judgement", + "Peasant Smiter", + "Wicked Ravager", + "Sheep Reaver", + "Never-ending Crusade", + "Locus Invicta", + "Memento Morieris", + "God Conqueror", + "Omnium Contra Omnes", + "Aries Duo", + "Dark Ages Bringer", + "Merciless Barricade", + "Murder Mcmurderface" ] } diff --git a/tgstation.dme b/tgstation.dme index 7554d956cbc..e84d081e917 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -180,6 +180,7 @@ #include "code\__DEFINES\procpath.dm" #include "code\__DEFINES\profile.dm" #include "code\__DEFINES\projectiles.dm" +#include "code\__DEFINES\pronouns.dm" #include "code\__DEFINES\qdel.dm" #include "code\__DEFINES\quirks.dm" #include "code\__DEFINES\radiation.dm" @@ -721,13 +722,11 @@ #include "code\controllers\subsystem\atoms.dm" #include "code\controllers\subsystem\augury.dm" #include "code\controllers\subsystem\ban_cache.dm" -#include "code\controllers\subsystem\battle_royale.dm" #include "code\controllers\subsystem\bitrunning.dm" #include "code\controllers\subsystem\blackbox.dm" #include "code\controllers\subsystem\blackmarket.dm" #include "code\controllers\subsystem\chat.dm" #include "code\controllers\subsystem\circuit_component.dm" -#include "code\controllers\subsystem\communications.dm" #include "code\controllers\subsystem\dbcore.dm" #include "code\controllers\subsystem\dcs.dm" #include "code\controllers\subsystem\discord.dm" @@ -751,7 +750,6 @@ #include "code\controllers\subsystem\lua.dm" #include "code\controllers\subsystem\machines.dm" #include "code\controllers\subsystem\mapping.dm" -#include "code\controllers\subsystem\materials.dm" #include "code\controllers\subsystem\minor_mapping.dm" #include "code\controllers\subsystem\mobs.dm" #include "code\controllers\subsystem\modular_computers.dm" @@ -818,7 +816,6 @@ #include "code\controllers\subsystem\movement\ai_movement.dm" #include "code\controllers\subsystem\movement\cliff_falling.dm" #include "code\controllers\subsystem\movement\hyperspace_drift.dm" -#include "code\controllers\subsystem\movement\move_handler.dm" #include "code\controllers\subsystem\movement\movement.dm" #include "code\controllers\subsystem\movement\movement_types.dm" #include "code\controllers\subsystem\movement\spacedrift.dm" @@ -1869,9 +1866,9 @@ #include "code\datums\shuttles\starfury.dm" #include "code\datums\shuttles\whiteship.dm" #include "code\datums\skills\_skill.dm" +#include "code\datums\skills\athletics.dm" #include "code\datums\skills\cleaning.dm" #include "code\datums\skills\fishing.dm" -#include "code\datums\skills\fitness.dm" #include "code\datums\skills\gaming.dm" #include "code\datums\skills\mining.dm" #include "code\datums\station_traits\_station_trait.dm" @@ -1947,6 +1944,12 @@ #include "code\datums\storage\subtypes\rped.dm" #include "code\datums\storage\subtypes\surgery_tray.dm" #include "code\datums\storage\subtypes\trash.dm" +#include "code\datums\systems\_system.dm" +#include "code\datums\systems\manager.dm" +#include "code\datums\systems\ds\battle_royale.dm" +#include "code\datums\systems\ds\communications.dm" +#include "code\datums\systems\ds\materials.dm" +#include "code\datums\systems\ds\move_handler.dm" #include "code\datums\votes\_vote_datum.dm" #include "code\datums\votes\custom_vote.dm" #include "code\datums\votes\map_vote.dm" @@ -2180,6 +2183,7 @@ #include "code\game\machinery\computer\records\records.dm" #include "code\game\machinery\computer\records\security.dm" #include "code\game\machinery\dna_infuser\dna_infuser.dm" +#include "code\game\machinery\dna_infuser\dna_infusion.dm" #include "code\game\machinery\dna_infuser\infuser_book.dm" #include "code\game\machinery\dna_infuser\infuser_entry.dm" #include "code\game\machinery\dna_infuser\infuser_entries\infuser_tier_one_entries.dm" @@ -3006,6 +3010,7 @@ #include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" #include "code\modules\admin\view_variables\admin_delete.dm" #include "code\modules\admin\view_variables\color_matrix_editor.dm" +#include "code\modules\admin\view_variables\debug_variable_appearance.dm" #include "code\modules\admin\view_variables\debug_variables.dm" #include "code\modules\admin\view_variables\filterrific.dm" #include "code\modules\admin\view_variables\get_variables.dm" @@ -4637,6 +4642,7 @@ #include "code\modules\mining\equipment\miningradio.dm" #include "code\modules\mining\equipment\resonator.dm" #include "code\modules\mining\equipment\survival_pod.dm" +#include "code\modules\mining\equipment\vent_pointer.dm" #include "code\modules\mining\equipment\wormhole_jaunter.dm" #include "code\modules\mining\equipment\monster_organs\brimdust_sac.dm" #include "code\modules\mining\equipment\monster_organs\monster_organ.dm" @@ -6482,6 +6488,7 @@ #include "modular_skyrat\master_files\code\modules\clothing\head\_head.dm" #include "modular_skyrat\master_files\code\modules\clothing\head\akula_official.dm" #include "modular_skyrat\master_files\code\modules\clothing\head\cowboy.dm" +#include "modular_skyrat\master_files\code\modules\clothing\head\hardhat.dm" #include "modular_skyrat\master_files\code\modules\clothing\head\monkey_magnification_helmet.dm" #include "modular_skyrat\master_files\code\modules\clothing\masks\_masks.dm" #include "modular_skyrat\master_files\code\modules\clothing\outfits\ert.dm" diff --git a/tgui/packages/common/type-utils.ts b/tgui/packages/common/type-utils.ts new file mode 100644 index 00000000000..a73c0c1d595 --- /dev/null +++ b/tgui/packages/common/type-utils.ts @@ -0,0 +1,41 @@ +/** + * Helps visualize highly complex ui data on the fly. + * @example + * ```tsx + * const { data } = useBackend(); + * logger.log(getShallowTypes(data)); + * ``` + */ +export function getShallowTypes( + data: Record, +): Record { + const output = {}; + + for (const key in data) { + if (Array.isArray(data[key])) { + const arr: any[] = data[key]; + + // Return the first array item if it exists + if (data[key].length > 0) { + output[key] = arr[0]; + continue; + } + + output[key] = 'emptyarray'; + } else if (typeof data[key] === 'object' && data[key] !== null) { + // Please inspect it further and make a new type for it + output[key] = 'object (inspect) || Record'; + } else if (typeof data[key] === 'number') { + const num = Number(data[key]); + + // 0 and 1 could be booleans from byond + if (num === 1 || num === 0) { + output[key] = `${num}, BooleanLike?`; + continue; + } + output[key] = data[key]; + } + } + + return output; +} diff --git a/tgui/packages/tgui/components/Dropdown.tsx b/tgui/packages/tgui/components/Dropdown.tsx index a103a7466d3..1cf2b53ecfd 100644 --- a/tgui/packages/tgui/components/Dropdown.tsx +++ b/tgui/packages/tgui/components/Dropdown.tsx @@ -1,12 +1,12 @@ import { classes } from 'common/react'; -import { ReactNode, useCallback, useEffect, useRef, useState } from 'react'; +import { ReactNode, useEffect, useRef, useState } from 'react'; import { BoxProps, unit } from './Box'; import { Button } from './Button'; import { Icon } from './Icon'; import { Popper } from './Popper'; -type DropdownEntry = { +export type DropdownEntry = { displayText: ReactNode; value: string | number; }; @@ -19,7 +19,11 @@ type Props = { options: DropdownOption[]; /** Called when a value is picked from the list, `value` is the value that was picked */ onSelected: (value: any) => void; + /** Currently selected entry to display. Can be left stateless to permanently display this value. */ + selected: DropdownOption | null | undefined; } & Partial<{ + /** Whether to scroll automatically on open. Defaults to true */ + autoScroll: boolean; /** Whether to display previous / next buttons */ buttons: boolean; /** Whether to clip the selected text */ @@ -28,7 +32,7 @@ type Props = { color: string; /** Disables the dropdown */ disabled: boolean; - /** Text to always display in place of the selected text */ + /** Overwrites selection text with this. Good for objects etc. */ displayText: ReactNode; /** Icon to display in dropdown button */ icon: string; @@ -44,17 +48,26 @@ type Props = { onClick: (event) => void; /** Dropdown renders over instead of below */ over: boolean; - /** Currently selected entry */ - selected: string | number; + /** Text to show when nothing has been selected. */ + placeholder: string; }> & BoxProps; +enum DIRECTION { + Previous = 'previous', + Next = 'next', + Current = 'current', +} + +const NONE = -1; + function getOptionValue(option: DropdownOption) { return typeof option === 'string' ? option : option.value; } export function Dropdown(props: Props) { const { + autoScroll = true, buttons, className, clipSelectedText = true, @@ -70,46 +83,64 @@ export function Dropdown(props: Props) { onSelected, options = [], over, + placeholder = 'Select...', selected, - width, + width = '15rem', } = props; const [open, setOpen] = useState(false); const adjustedOpen = over ? !open : open; const innerRef = useRef(null); + const selectedIndex = + options.findIndex((option) => getOptionValue(option) === selected) || 0; + + function scrollTo(position: number) { + let scrollPos = position; + if (position < selectedIndex) { + scrollPos = position < 2 ? 0 : position - 2; + } else { + scrollPos = + position > options.length - 3 ? options.length - 1 : position - 2; + } + + const element = innerRef.current?.children[scrollPos]; + element?.scrollIntoView({ block: 'nearest' }); + } + /** Update the selected value when clicking the left/right buttons */ - const updateSelected = useCallback( - (direction: 'previous' | 'next') => { - if (options.length < 1 || disabled) { - return; - } - const startIndex = 0; - const endIndex = options.length - 1; + function updateSelected(direction: DIRECTION) { + if (options.length < 1 || disabled) { + return; + } - let selectedIndex = options.findIndex( - (option) => getOptionValue(option) === selected, - ); + const startIndex = 0; + const endIndex = options.length - 1; - if (selectedIndex < 0) { - selectedIndex = direction === 'next' ? endIndex : startIndex; - } + let newIndex: number; + if (selectedIndex < 0) { + newIndex = direction === 'next' ? endIndex : startIndex; // No selection yet + } else if (direction === 'next') { + newIndex = selectedIndex === endIndex ? startIndex : selectedIndex + 1; // Move to next option + } else { + newIndex = selectedIndex === startIndex ? endIndex : selectedIndex - 1; // Move to previous option + } - let newIndex = selectedIndex; - if (direction === 'next') { - newIndex = selectedIndex === endIndex ? startIndex : ++selectedIndex; - } else { - newIndex = selectedIndex === startIndex ? endIndex : --selectedIndex; - } - - onSelected?.(getOptionValue(options[newIndex])); - }, - [disabled, onSelected, options, selected], - ); + if (open && autoScroll) { + scrollTo(newIndex); + } + onSelected?.(getOptionValue(options[newIndex])); + } /** Allows the menu to be scrollable on open */ useEffect(() => { - if (!open) return; + if (!open) { + return; + } + + if (autoScroll && selectedIndex !== NONE) { + scrollTo(selectedIndex); + } innerRef.current?.focus(); }, [open]); @@ -151,69 +182,64 @@ export function Dropdown(props: Props) { } > -
    -
    -
    { - if (disabled && !open) { - return; - } - setOpen(!open); - onClick?.(event); +
    +
    { + if (disabled && !open) { + return; + } + setOpen(!open); + onClick?.(event); + }} + > + {icon && ( + + )} + - {icon && ( - - )} - - {displayText || selected} + {displayText || + (selected && getOptionValue(selected)) || + placeholder} + + {!noChevron && ( + + - {!noChevron && ( - - - - )} -
    - {buttons && ( - <> -
    + {buttons && ( + <> +
    ); diff --git a/tgui/packages/tgui/components/Stack.tsx b/tgui/packages/tgui/components/Stack.tsx index 18ae34c09e8..3f5cf72123c 100644 --- a/tgui/packages/tgui/components/Stack.tsx +++ b/tgui/packages/tgui/components/Stack.tsx @@ -17,14 +17,23 @@ import { } from './Flex'; type Props = Partial<{ - vertical: boolean; + /** Fills available space. */ fill: boolean; + /** Reverses the stack. */ + reverse: boolean; + /** Flex column */ + vertical: boolean; + /** Adds zebra striping to the stack. */ zebra: boolean; }> & FlexProps; -export const Stack = (props: Props) => { - const { className, vertical, fill, zebra, ...rest } = props; +export function Stack(props: Props) { + const { className, vertical, fill, reverse, zebra, ...rest } = props; + + const directionPrefix = vertical ? 'column' : 'row'; + const directionSuffix = reverse ? '-reverse' : ''; + return (
    { fill && 'Stack--fill', vertical ? 'Stack--vertical' : 'Stack--horizontal', zebra && 'Stack--zebra', + reverse && `Stack--reverse${vertical ? '--vertical' : ''}`, className, computeFlexClassName(props), ])} {...computeFlexProps({ - direction: vertical ? 'column' : 'row', + direction: `${directionPrefix}${directionSuffix}`, ...rest, })} /> ); -}; +} type StackItemProps = FlexItemProps & Partial<{ innerRef: RefObject; }>; -const StackItem = (props: StackItemProps) => { +function StackItem(props: StackItemProps) { const { className, innerRef, ...rest } = props; + return (
    { {...computeFlexItemProps(rest)} /> ); -}; +} Stack.Item = StackItem; @@ -70,8 +81,9 @@ type StackDividerProps = FlexItemProps & hidden: boolean; }>; -const StackDivider = (props: StackDividerProps) => { +function StackDivider(props: StackDividerProps) { const { className, hidden, ...rest } = props; + return (
    { {...computeFlexItemProps(rest)} /> ); -}; +} Stack.Divider = StackDivider; diff --git a/tgui/packages/tgui/interfaces/AdminFax.jsx b/tgui/packages/tgui/interfaces/AdminFax.jsx index 9aeef3247a3..3e6026d4ce4 100644 --- a/tgui/packages/tgui/interfaces/AdminFax.jsx +++ b/tgui/packages/tgui/interfaces/AdminFax.jsx @@ -63,10 +63,9 @@ export const FaxMainPanel = (props) => { setFax(value)} /> diff --git a/tgui/packages/tgui/interfaces/AdminPDA.jsx b/tgui/packages/tgui/interfaces/AdminPDA.jsx index 09570265a20..fa83f200e52 100644 --- a/tgui/packages/tgui/interfaces/AdminPDA.jsx +++ b/tgui/packages/tgui/interfaces/AdminPDA.jsx @@ -33,7 +33,8 @@ const ReceiverChoice = (props) => { showInvisible || !rcvr.invisible) .map((rcvr) => ({ diff --git a/tgui/packages/tgui/interfaces/AiVoiceChanger.tsx b/tgui/packages/tgui/interfaces/AiVoiceChanger.tsx index 9e248a01033..09c1aa04e57 100644 --- a/tgui/packages/tgui/interfaces/AiVoiceChanger.tsx +++ b/tgui/packages/tgui/interfaces/AiVoiceChanger.tsx @@ -5,37 +5,40 @@ import { Button, Dropdown, Input, LabeledList, Section } from '../components'; import { Window } from '../layouts'; type Data = { - on: BooleanLike; - voices: string[]; - say_verb: string; loud: BooleanLike; name: string; + on: BooleanLike; + say_verb: string; + selected: string; + voices: string[]; }; -export const AiVoiceChanger = (props) => { +export function AiVoiceChanger(props) { const { act, data } = useBackend(); - const { loud, name, on, say_verb, voices } = data; + const { loud, name, on, say_verb, voices, selected } = data; return ( -
    +
    + onSelected={(value) => { act('look', { look: value, - }) - } + }); + }} + selected={selected} /> @@ -51,10 +54,11 @@ export const AiVoiceChanger = (props) => { {
    ); -}; +} diff --git a/tgui/packages/tgui/interfaces/AlertModal.tsx b/tgui/packages/tgui/interfaces/AlertModal.tsx index d5b931dc08c..62b6e8bbbc3 100644 --- a/tgui/packages/tgui/interfaces/AlertModal.tsx +++ b/tgui/packages/tgui/interfaces/AlertModal.tsx @@ -1,33 +1,29 @@ -import { useState } from 'react'; +import { KEY } from 'common/keys'; +import { BooleanLike } from 'common/react'; +import { KeyboardEvent, useState } from 'react'; -import { - KEY_ENTER, - KEY_ESCAPE, - KEY_LEFT, - KEY_RIGHT, - KEY_SPACE, - KEY_TAB, -} from '../../common/keycodes'; import { useBackend } from '../backend'; -import { Autofocus, Box, Button, Flex, Section, Stack } from '../components'; +import { Autofocus, Box, Button, Section, Stack } from '../components'; import { Window } from '../layouts'; import { Loader } from './common/Loader'; -type AlertModalData = { - autofocus: boolean; +type Data = { + autofocus: BooleanLike; buttons: string[]; - large_buttons: boolean; + large_buttons: BooleanLike; message: string; - swapped_buttons: boolean; + swapped_buttons: BooleanLike; timeout: number; title: string; }; -const KEY_DECREMENT = -1; -const KEY_INCREMENT = 1; +enum DIRECTION { + Increment = 1, + Decrement = -1, +} -export const AlertModal = (props) => { - const { act, data } = useBackend(); +export function AlertModal(props) { + const { act, data } = useBackend(); const { autofocus, buttons = [], @@ -36,128 +32,148 @@ export const AlertModal = (props) => { timeout, title, } = data; + const [selected, setSelected] = useState(0); + + // At least one of the buttons has a long text message + const isVerbose = buttons.some((button) => button.length > 10); + const largeSpacing = isVerbose && large_buttons ? 20 : 15; + // Dynamically sets window dimensions const windowHeight = - 115 + + 120 + + (isVerbose ? largeSpacing * buttons.length : 0) + (message.length > 30 ? Math.ceil(message.length / 4) : 0) + (message.length && large_buttons ? 5 : 0); - const windowWidth = 325 + (buttons.length > 2 ? 55 : 0); - const onKey = (direction: number) => { - if (selected === 0 && direction === KEY_DECREMENT) { - setSelected(buttons.length - 1); - } else if (selected === buttons.length - 1 && direction === KEY_INCREMENT) { - setSelected(0); - } else { - setSelected(selected + direction); + + const windowWidth = 345 + (buttons.length > 2 ? 55 : 0); + + /** Changes button selection, etc */ + function keyDownHandler(event: KeyboardEvent) { + switch (event.key) { + case KEY.Space: + case KEY.Enter: + act('choose', { choice: buttons[selected] }); + return; + case KEY.Escape: + act('cancel'); + return; + case KEY.Left: + event.preventDefault(); + onKey(DIRECTION.Decrement); + return; + case KEY.Tab: + case KEY.Right: + event.preventDefault(); + onKey(DIRECTION.Increment); + return; } - }; + } + + /** Manages iterating through the buttons */ + function onKey(direction: DIRECTION) { + const newIndex = (selected + direction + buttons.length) % buttons.length; + setSelected(newIndex); + } return ( {!!timeout && } - { - const keyCode = window.event ? e.which : e.keyCode; - /** - * Simulate a click when pressing space or enter, - * allow keyboard navigation, override tab behavior - */ - if (keyCode === KEY_SPACE || keyCode === KEY_ENTER) { - act('choose', { choice: buttons[selected] }); - } else if (keyCode === KEY_ESCAPE) { - act('cancel'); - } else if (keyCode === KEY_LEFT) { - e.preventDefault(); - onKey(KEY_DECREMENT); - } else if (keyCode === KEY_TAB || keyCode === KEY_RIGHT) { - e.preventDefault(); - onKey(KEY_INCREMENT); - } - }} - > +
    - + {message} - + {!!autofocus && } - + {isVerbose ? ( + + ) : ( + + )}
    ); +} + +type ButtonDisplayProps = { + selected: number; }; /** * Displays a list of buttons ordered by user prefs. - * Technically this handles more than 2 buttons, but you - * should just be using a list input in that case. */ -const ButtonDisplay = (props) => { - const { data } = useBackend(); +function HorizontalButtons(props: ButtonDisplayProps) { + const { act, data } = useBackend(); const { buttons = [], large_buttons, swapped_buttons } = data; const { selected } = props; return ( - - {buttons?.map((button, index) => - !!large_buttons && buttons.length < 3 ? ( - - - - ) : ( - - - - ), - )} - + + {buttons.map((button, index) => ( + + + + ))} + ); -}; +} /** - * Displays a button with variable sizing. + * Technically the parent handles more than 2 buttons, but you + * should just be using a list input in that case. */ -const AlertButton = (props) => { - const { act, data } = useBackend(); - const { large_buttons } = data; - const { button, selected } = props; - const buttonWidth = button.length > 7 ? button.length : 7; +function VerticalButtons(props: ButtonDisplayProps) { + const { act, data } = useBackend(); + const { buttons = [], large_buttons, swapped_buttons } = data; + const { selected } = props; return ( - + {buttons.map((button, index) => ( + + + + ))} + ); -}; +} diff --git a/tgui/packages/tgui/interfaces/Cargo.jsx b/tgui/packages/tgui/interfaces/Cargo.jsx deleted file mode 100644 index cbc0f5b112b..00000000000 --- a/tgui/packages/tgui/interfaces/Cargo.jsx +++ /dev/null @@ -1,576 +0,0 @@ -import { filter, sortBy } from 'common/collections'; - -import { useBackend, useSharedState } from '../backend'; -import { - AnimatedNumber, - Box, - Button, - Flex, - Icon, - Input, - LabeledList, - NoticeBox, - RestrictedInput, - Section, - Stack, - Table, - Tabs, -} from '../components'; -import { formatMoney } from '../format'; -import { Window } from '../layouts'; - -export const Cargo = (props) => { - return ( - - - - - - ); -}; - -export const CargoContent = (props) => { - /* SKYRAT EDIT BELOW - ADDS act */ - const { act, data } = useBackend(); - /* SKYRAT EDIT END */ - const [tab, setTab] = useSharedState('tab', 'catalog'); - const { cart = [], requests = [], requestonly } = data; - const cart_length = cart.reduce((total, entry) => total + entry.amount, 0); - - return ( - - -
    - - setTab('catalog')} - > - Catalog - - 0 && 'yellow'} - selected={tab === 'requests'} - onClick={() => setTab('requests')} - > - Requests ({requests.length}) - - act('company_import_window')} - > - Company Imports - - {!requestonly && ( - <> - 0 && 'yellow'} - selected={tab === 'cart'} - onClick={() => setTab('cart')} - > - Checkout ({cart_length}) - - setTab('help')} - > - Help - - - )} - -
    - {tab === 'catalog' && } - {tab === 'requests' && } - {tab === 'cart' && } - {tab === 'help' && } - {tab === 'company_import_window' && tab === 'catalog'} -
    - ); -}; - -const CargoStatus = (props) => { - const { act, data } = useBackend(); - const { - department, - grocery, - away, - docked, - loan, - loan_dispatched, - location, - message, - points, - requestonly, - can_send, - } = data; - - return ( -
    - formatMoney(value)} - /> - {' credits'} - - } - > - - - {(docked && !requestonly && can_send && ( -
    - ); -}; - -/** - * Take entire supplies tree - * and return a flat supply pack list that matches search, - * sorted by name and only the first page. - * @param {any[]} supplies Supplies list. - * @param {string} search The search term - * @returns {any[]} The flat list of supply packs. - */ -const searchForSupplies = (supplies, search) => { - search = search.toLowerCase(); - - const queriedSupplies = sortBy( - filter( - supplies.flatMap((category) => category.packs), - (pack) => - pack.name?.toLowerCase().includes(search.toLowerCase()) || - pack.desc?.toLowerCase().includes(search.toLowerCase()), - ), - (pack) => pack.name, - ); - - return queriedSupplies.slice(0, 25); -}; - -export const CargoCatalog = (props) => { - const { express } = props; - const { act, data } = useBackend(); - - const { self_paid, app_cost } = data; - - const supplies = Object.values(data.supplies); - const { amount_by_name = [], max_order } = data; - - const [activeSupplyName, setActiveSupplyName] = useSharedState( - 'supply', - supplies[0]?.name, - ); - - const [searchText, setSearchText] = useSharedState('search_text', ''); - - const activeSupply = - activeSupplyName === 'search_results' - ? { packs: searchForSupplies(supplies, searchText) } - : supplies.find((supply) => supply.name === activeSupplyName); - - return ( -
    - - act('toggleprivate')} - /> - - ) - } - > - - - - - - - - - - { - if (value === searchText) { - return; - } - - if (value.length) { - // Start showing results - setActiveSupplyName('search_results'); - } else if (activeSupplyName === 'search_results') { - // return to normal category - setActiveSupplyName(supplies[0]?.name); - } - setSearchText(value); - }} - /> - - - - {supplies.map((supply) => ( - { - setActiveSupplyName(supply.name); - setSearchText(''); - }} - > - {supply.name} ({supply.packs.length}) - - ))} - - - - - {activeSupply?.packs.map((pack) => { - const tags = []; - if (pack.small_item) { - tags.push('Small'); - } - if (pack.access) { - tags.push('Restricted'); - } - return ( - - {pack.name} - - {tags.join(', ')} - - - - - - ); - })} -
    -
    -
    -
    - ); -}; - -const CargoRequests = (props) => { - const { act, data } = useBackend(); - const { requestonly, can_send, can_approve_requests } = data; - const requests = data.requests || []; - // Labeled list reimplementation to squeeze extra columns out of it - return ( -
    act('denyall')} - /> - ) - } - > - {requests.length === 0 && No Requests} - {requests.length > 0 && ( - - {requests.map((request) => ( - - - #{request.id} - - {request.object} - - {request.orderer} - - - {request.reason} - - - {formatMoney(request.cost)} cr - - {(!requestonly || can_send) && can_approve_requests && ( - -
    - )} -
    - ); -}; - -const CargoCartButtons = (props) => { - const { act, data } = useBackend(); - const { requestonly, can_send, can_approve_requests } = data; - const cart = data.cart || []; - const total = cart.reduce((total, entry) => total + entry.cost, 0); - return ( - <> - - {cart.length === 0 && 'Cart is empty'} - {cart.length === 1 && '1 item'} - {cart.length >= 2 && cart.length + ' items'}{' '} - {total > 0 && `(${formatMoney(total)} cr)`} - - {!requestonly && !!can_send && !!can_approve_requests && ( -
    - ); -}; - -const CargoHelp = (props) => { - return ( - <> -
    - Each department on the station will order crates from their own personal - consoles. These orders are ENTIRELY FREE! They do not come out of - cargo's budget, and rather put the consoles on cooldown. So - here's where you come in: The ordered crates will show up on your - supply console, and you need to deliver the crates to the orderers. - You'll actually be paid the full value of the department crate on - delivery if the crate was not tampered with, making the system a good - source of income. -
    - - Examine a department order crate to get specific details about where - the crate needs to go. - -
    -
    - MULEbots are slow but loyal delivery bots that will get crates delivered - with minimal technician effort required. It is slow, though, and can be - tampered with while en route. -
    - Setting up a MULEbot is easy: -
    - 1. Drag the crate you want to deliver next to the MULEbot. -
    - 2. Drag the crate on top of MULEbot. It should load on. -
    - 3. Open your PDA. -
    - 4. Click Delivery Bot Control.
    - 5. Click Scan for Active Bots.
    - 6. Choose your MULE. -
    - 7. Click on Destination: (set).
    - 8. Choose a destination and click OK. -
    - 9. Click Proceed. -
    -
    - In addition to MULEs and hand-deliveries, you can also make use of the - disposals mailing system. Note that a break in the disposal piping could - cause your package to be lost (this hardly ever happens), so this is not - always the most secure ways to deliver something. You can wrap up a - piece of paper and mail it the same way if you (or someone at the desk) - wants to mail a letter. -
    - Using the Disposals Delivery System is even easier: -
    - 1. Wrap your item/crate in packaging paper. -
    - 2. Use the destinations tagger to choose where to send it. -
    - 3. Tag the package. -
    - 4. Stick it on the conveyor and let the system handle it. -
    -
    - - Pondering something not included here? When in doubt, ask the QM! - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoButtons.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoButtons.tsx new file mode 100644 index 00000000000..82c0d51a1f4 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/CargoButtons.tsx @@ -0,0 +1,39 @@ +import { useBackend } from '../../backend'; +import { Box, Button } from '../../components'; +import { formatMoney } from '../../format'; +import { CargoData } from './types'; + +export function CargoCartButtons(props) { + const { act, data } = useBackend(); + const { cart = [], requestonly, can_send, can_approve_requests } = data; + + let total = 0; + let amount = 0; + for (let i = 0; i < cart.length; i++) { + amount += cart[i].amount; + total += cart[i].cost; + } + + const canClear = + !requestonly && !!can_send && !!can_approve_requests && cart.length > 0; + + return ( + <> + + {amount === 0 && 'Cart is empty'} + {amount === 1 && '1 item'} + {amount >= 2 && amount + ' items'}{' '} + {total > 0 && `(${formatMoney(total)} cr)`} + + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx new file mode 100644 index 00000000000..a595d5c0e3b --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx @@ -0,0 +1,130 @@ +import { useBackend } from '../../backend'; +import { + Button, + Icon, + Input, + NoticeBox, + RestrictedInput, + Section, + Stack, + Table, +} from '../../components'; +import { formatMoney } from '../../format'; +import { CargoCartButtons } from './CargoButtons'; +import { CargoData } from './types'; + +export function CargoCart(props) { + const { act, data } = useBackend(); + const { requestonly, away, cart = [], docked, location } = data; + + const sendable = !away && !!docked; + + return ( + + +
    }> + +
    +
    + + {cart.length > 0 && !requestonly && ( +
    + + + {!sendable && } + + + + + +
    + )} +
    +
    + ); +} + +function CheckoutItems(props) { + const { act, data } = useBackend(); + const { amount_by_name = {}, can_send, cart = [], max_order } = data; + + if (cart.length === 0) { + return Nothing in cart; + } + + return ( + + + ID + Supply Type + Amount + + + Cost + + + + {cart.map((entry) => ( + + + #{entry.id} + + {entry.object} + + + {can_send && entry.can_be_cancelled ? ( + + act('modify', { + order_name: entry.object, + amount: value, + }) + } + /> + ) : ( + + )} + + {!!can_send && !!entry.can_be_cancelled && ( + <> +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx new file mode 100644 index 00000000000..baccf90c4bd --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx @@ -0,0 +1,238 @@ +import { sortBy } from 'common/collections'; +import { useMemo } from 'react'; + +import { useBackend, useSharedState } from '../../backend'; +import { + Button, + Icon, + Input, + Section, + Stack, + Table, + Tabs, + Tooltip, +} from '../../components'; +import { formatMoney } from '../../format'; +import { CargoCartButtons } from './CargoButtons'; +import { searchForSupplies } from './helpers'; +import { CargoData, Supply, SupplyCategory } from './types'; + +type Props = { + express?: boolean; +}; + +export function CargoCatalog(props: Props) { + const { express } = props; + const { act, data } = useBackend(); + const { self_paid } = data; + + const supplies = Object.values(data.supplies); + + const [activeSupplyName, setActiveSupplyName] = useSharedState( + 'supply', + supplies[0]?.name, + ); + + const [searchText, setSearchText] = useSharedState('search_text', ''); + + const packs = useMemo(() => { + let fetched: Supply[] | undefined; + + if (activeSupplyName === 'search_results') { + fetched = searchForSupplies(supplies, searchText); + } else { + fetched = supplies.find( + (supply) => supply.name === activeSupplyName, + )?.packs; + } + + if (!fetched) return []; + + fetched = sortBy(fetched, (pack: Supply) => pack.name); + + return fetched; + }, [activeSupplyName, supplies, searchText]); + + return ( +
    + + + + ) + } + > + + + + + + + + + +
    + ); +} + +type CatalogTabsProps = { + activeSupplyName: string; + categories: SupplyCategory[]; + searchText: string; + setActiveSupplyName: (name: string) => void; + setSearchText: (text: string) => void; +}; + +function CatalogTabs(props: CatalogTabsProps) { + const { + activeSupplyName, + categories, + searchText, + setActiveSupplyName, + setSearchText, + } = props; + + const sorted = sortBy(categories, (supply) => supply.name); + + return ( + + + + + + + + { + if (value === searchText) { + return; + } + + if (value.length) { + // Start showing results + setActiveSupplyName('search_results'); + } else if (activeSupplyName === 'search_results') { + // return to normal category + setActiveSupplyName(sorted[0]?.name); + } + setSearchText(value); + }} + /> + + + + + {sorted.map((supply) => ( + { + setActiveSupplyName(supply.name); + setSearchText(''); + }} + > +
    + {supply.name} + {supply.packs.length} +
    +
    + ))} +
    + ); +} + +type CatalogListProps = { + packs: SupplyCategory['packs']; +}; + +function CatalogList(props: CatalogListProps) { + const { act, data } = useBackend(); + const { amount_by_name = {}, max_order, self_paid, app_cost } = data; + const { packs = [] } = props; + + return ( +
    + + {packs.map((pack) => { + let color = ''; + const digits = Math.floor(Math.log10(pack.cost) + 1); + if (self_paid) { + color = 'caution'; + } else if (digits >= 5 && digits <= 6) { + color = 'yellow'; + } else if (digits > 6) { + color = 'bad'; + } + + return ( + + {pack.name} + + {!!pack.small_item && ( + + + + )} + + + {!!pack.access && ( + + + + )} + + + + + + ); + })} +
    +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoHelp.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoHelp.tsx new file mode 100644 index 00000000000..841ded71fb7 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/CargoHelp.tsx @@ -0,0 +1,80 @@ +import { Box, NoticeBox, Section, Stack } from '../../components'; + +const ORDER_TEXT = `Each department on the station will order crates from their own personal + consoles. These orders are ENTIRELY FREE! They do not come out of + cargo's budget, and rather put the consoles on cooldown. So + here's where you come in: The ordered crates will show up on your + supply console, and you need to deliver the crates to the orderers. + You'll actually be paid the full value of the department crate on + delivery if the crate was not tampered with, making the system a good + source of income.`; + +const DISPOSAL_TEXT = `In addition to MULEs and hand-deliveries, you can also make use of the + disposals mailing system. Note that a break in the disposal piping could + cause your package to be lost (this hardly ever happens), so this is not + always the most secure ways to deliver something. You can wrap up a + piece of paper and mail it the same way if you (or someone at the desk) + wants to mail a letter.`; + +export function CargoHelp(props) { + return ( + + +
    +
    + {ORDER_TEXT} +
    +
    + Examine a department order crate to get specific details about where + the crate needs to go. +
    +
    + + MULEbots are slow but loyal delivery bots that will get crates + delivered with minimal technician effort required. It is slow, + though, and can be tampered with while en route. + +
    + + Setting up a MULEbot is easy: + + 1. Drag the crate you want to deliver next to the MULEbot. +
    + 2. Drag the crate on top of MULEbot. It should load on. +
    + 3. Open your PDA. +
    + 4. Click Delivery Bot Control.
    + 5. Click Scan for Active Bots.
    + 6. Choose your MULE. +
    + 7. Click on Destination: (set).
    + 8. Choose a destination and click OK. +
    + 9. Click Proceed. +
    +
    + {DISPOSAL_TEXT} +
    + + Using the Disposals Delivery System is even easier: + + 1. Wrap your item/crate in packaging paper. +
    + 2. Use the destinations tagger to choose where to send it. +
    + 3. Tag the package. +
    + 4. Stick it on the conveyor and let the system handle it. +
    +
    +
    +
    + + + Pondering something not included here? When in doubt, ask the QM! + + +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoRequests.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoRequests.tsx new file mode 100644 index 00000000000..3a53efb45e9 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/CargoRequests.tsx @@ -0,0 +1,85 @@ +import { decodeHtmlEntities } from 'common/string'; + +import { useBackend } from '../../backend'; +import { Button, NoticeBox, Section, Table } from '../../components'; +import { TableCell, TableRow } from '../../components/Table'; +import { formatMoney } from '../../format'; +import { CargoData } from './types'; + +export function CargoRequests(props) { + const { act, data } = useBackend(); + const { requests = [], requestonly, can_send, can_approve_requests } = data; + + return ( +
    act('denyall')} + > + Clear + + ) + } + > + {requests.length === 0 && No Requests} + {requests.length > 0 && ( + + + ID + Object + Orderer + Reason + Cost + {(!requestonly || !!can_send) && !!can_approve_requests && ( + Actions + )} + + + {requests.map((request) => ( + + #{request.id} + {request.object} + + {request.orderer} + + + {decodeHtmlEntities(request.reason)} + + + {formatMoney(request.cost)} cr + + {(!requestonly || !!can_send) && !!can_approve_requests && ( + +
    + )} +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoStatus.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoStatus.tsx new file mode 100644 index 00000000000..b230400e4e3 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/CargoStatus.tsx @@ -0,0 +1,75 @@ +import { useBackend } from '../../backend'; +import { + AnimatedNumber, + Box, + Button, + LabeledList, + Section, +} from '../../components'; +import { formatMoney } from '../../format'; +import { CargoData } from './types'; + +export function CargoStatus(props) { + const { act, data } = useBackend(); + const { + department, + grocery, + away, + docked, + loan, + loan_dispatched, + location, + message, + points, + requestonly, + can_send, + } = data; + + return ( +
    + formatMoney(value)} + /> + {' credits'} + + } + > + + + {!!docked && !requestonly && !!can_send ? ( + + ) : ( + String(location) + )} + + {message} + {!!loan && !requestonly && ( + + {!loan_dispatched ? ( + + ) : ( + Loaned to Centcom + )} + + )} + +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/helpers.ts b/tgui/packages/tgui/interfaces/Cargo/helpers.ts new file mode 100644 index 00000000000..e6b67f8ff6d --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/helpers.ts @@ -0,0 +1,35 @@ +import { filter } from 'common/collections'; +import { flow } from 'common/fp'; + +import { Supply, SupplyCategory } from './types'; + +/** + * Take entire supplies tree + * and return a flat supply pack list that matches search, + * sorted by name and only the first page. + * @param {Supply[]} supplies Supplies list, aka Object.values(data.supplies) + * @param {string} search The search term + * @returns {Supply[]} The flat list of supply packs. + */ +export function searchForSupplies( + supplies: SupplyCategory[], + search: string, +): Supply[] { + const lowerSearch = search.toLowerCase(); + + return flow([ + // Flat categories + (initialSupplies: SupplyCategory[]) => + initialSupplies.flatMap((category) => category.packs), + // Filter by name or desc + (flatMapped: Supply[]) => + filter( + flatMapped, + (pack: Supply) => + pack.name?.toLowerCase().includes(lowerSearch) || + pack.desc?.toLowerCase().includes(lowerSearch), + ), + // Just the first page + (filtered: Supply[]) => filtered.slice(0, 25), + ])(supplies); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/index.tsx b/tgui/packages/tgui/interfaces/Cargo/index.tsx new file mode 100644 index 00000000000..d39435f4cd9 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/index.tsx @@ -0,0 +1,91 @@ +import { useBackend, useSharedState } from '../../backend'; +import { Stack, Tabs } from '../../components'; +import { Window } from '../../layouts'; +import { CargoCart } from './CargoCart'; +import { CargoCatalog } from './CargoCatalog'; +import { CargoHelp } from './CargoHelp'; +import { CargoRequests } from './CargoRequests'; +import { CargoStatus } from './CargoStatus'; +import { CargoData } from './types'; + +enum TAB { + Catalog = 'catalog', + Requests = 'requests', + Cart = 'cart', + Help = 'help', +} + +export function Cargo(props) { + return ( + + + + + + ); +} + +export function CargoContent(props) { + const { data } = useBackend(); + + const { cart = [], requests = [], requestonly } = data; + + const [tab, setTab] = useSharedState('cargotab', TAB.Catalog); + + let amount = 0; + for (let i = 0; i < cart.length; i++) { + amount += cart[i].amount; + } + + return ( + + + + + + + setTab(TAB.Catalog)} + > + Catalog + + 0 && 'yellow'} + selected={tab === TAB.Requests} + onClick={() => setTab(TAB.Requests)} + > + Requests ({requests.length}) + + {!requestonly && ( + <> + 0 && 'yellow'} + selected={tab === TAB.Cart} + onClick={() => setTab(TAB.Cart)} + > + Checkout ({amount}) + + setTab(TAB.Help)} + > + Help + + + )} + + + + {tab === TAB.Catalog && } + {tab === TAB.Requests && } + {tab === TAB.Cart && } + {tab === TAB.Help && } + + + ); +} diff --git a/tgui/packages/tgui/interfaces/Cargo/types.ts b/tgui/packages/tgui/interfaces/Cargo/types.ts new file mode 100644 index 00000000000..4d9e2817d61 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Cargo/types.ts @@ -0,0 +1,58 @@ +import { BooleanLike } from 'common/react'; + +export type CargoData = { + amount_by_name: Record | undefined; + app_cost?: number; + away: BooleanLike; + can_approve_requests: BooleanLike; + can_send: BooleanLike; + cart: CartEntry[]; + department: string; + docked: BooleanLike; + grocery: number; + loan_dispatched: BooleanLike; + loan: BooleanLike; + location: string; + max_order: number; + message: string; + points: number; + requests: Request[]; + requestonly: BooleanLike; + self_paid: BooleanLike; + supplies: Record; +}; + +export type SupplyCategory = { + name: string; + packs: Supply[]; +}; + +export type Supply = { + access: BooleanLike; + cost: number; + desc: string; + goody: BooleanLike; + id: string; + name: string; + small_item: BooleanLike; +}; + +type CartEntry = { + amount: number; + can_be_cancelled: BooleanLike; + cost_type: string; + cost: number; + dep_order: BooleanLike; + id: string; + object: string; + orderer: string; + paid: BooleanLike; +}; + +type Request = { + cost: number; + id: string; + object: string; + orderer: string; + reason: string; +}; diff --git a/tgui/packages/tgui/interfaces/CargoExpress.tsx b/tgui/packages/tgui/interfaces/CargoExpress.tsx index 0983e685f7d..83947b5adc4 100644 --- a/tgui/packages/tgui/interfaces/CargoExpress.tsx +++ b/tgui/packages/tgui/interfaces/CargoExpress.tsx @@ -9,7 +9,7 @@ import { Section, } from '../components'; import { Window } from '../layouts'; -import { CargoCatalog } from './Cargo'; +import { CargoCatalog } from './Cargo/CargoCatalog'; import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; type Data = { @@ -24,7 +24,7 @@ type Data = { message: string; }; -export const CargoExpress = (props) => { +export function CargoExpress(props) { const { data } = useBackend(); const { locked } = data; @@ -36,9 +36,9 @@ export const CargoExpress = (props) => {
    ); -}; +} -const CargoExpressContent = (props) => { +function CargoExpressContent(props) { const { act, data } = useBackend(); const { hasBeacon, @@ -64,11 +64,9 @@ const CargoExpressContent = (props) => { > - - {message} @@ -88,4 +84,4 @@ const CargoExpressContent = (props) => { ); -}; +} diff --git a/tgui/packages/tgui/interfaces/Changelog.jsx b/tgui/packages/tgui/interfaces/Changelog.jsx index 6eb4ba1b020..d892d769351 100644 --- a/tgui/packages/tgui/interfaces/Changelog.jsx +++ b/tgui/packages/tgui/interfaces/Changelog.jsx @@ -141,7 +141,7 @@ export class Changelog extends Component { { const index = dateChoices.indexOf(value); @@ -157,7 +157,7 @@ export class Changelog extends Component { return this.getData(dates[index]); }} selected={selectedDate} - width={'150px'} + width="150px" /> diff --git a/tgui/packages/tgui/interfaces/CircuitModule.jsx b/tgui/packages/tgui/interfaces/CircuitModule.jsx index 799fea9d15f..bbb323e5e5a 100644 --- a/tgui/packages/tgui/interfaces/CircuitModule.jsx +++ b/tgui/packages/tgui/interfaces/CircuitModule.jsx @@ -130,7 +130,7 @@ const PortEntry = (props) => { diff --git a/tgui/packages/tgui/interfaces/CircuitSignalHandler.tsx b/tgui/packages/tgui/interfaces/CircuitSignalHandler.tsx index 1fc1f8397f9..66d04644391 100644 --- a/tgui/packages/tgui/interfaces/CircuitSignalHandler.tsx +++ b/tgui/packages/tgui/interfaces/CircuitSignalHandler.tsx @@ -221,7 +221,7 @@ const Entry = (props: EntryProps) => { {(options.length && ( diff --git a/tgui/packages/tgui/interfaces/CommandReport.tsx b/tgui/packages/tgui/interfaces/CommandReport.tsx index dfe8cf9ff3d..9185bebb5b4 100644 --- a/tgui/packages/tgui/interfaces/CommandReport.tsx +++ b/tgui/packages/tgui/interfaces/CommandReport.tsx @@ -117,7 +117,7 @@ const AnnouncementColor = (props) => {
    act('update_announcement_color', { @@ -138,7 +138,7 @@ const AnnouncementSound = (props) => {
    act('set_report_sound', { diff --git a/tgui/packages/tgui/interfaces/ControllerOverview.tsx b/tgui/packages/tgui/interfaces/ControllerOverview.tsx deleted file mode 100644 index 5b5c210b7bb..00000000000 --- a/tgui/packages/tgui/interfaces/ControllerOverview.tsx +++ /dev/null @@ -1,245 +0,0 @@ -import { BooleanLike } from 'common/react'; -import { createSearch } from 'common/string'; -import { useMemo, useState } from 'react'; - -import { useBackend } from '../backend'; -import { - Button, - Collapsible, - Dropdown, - Input, - LabeledList, - Section, - Stack, -} from '../components'; -import { Window } from '../layouts'; - -type SubsystemData = { - name: string; - ref: string; - init_order: number; - last_fire: number; - next_fire: number; - can_fire: BooleanLike; - doesnt_fire: BooleanLike; - cost_ms: number; - tick_usage: number; - tick_overrun: number; - initialized: BooleanLike; - initialization_failure_message: string | undefined; -}; - -type ControllerData = { - world_time: number; - fast_update: BooleanLike; - map_cpu: number; - subsystems: SubsystemData[]; -}; - -const SubsystemView = (props: { data: SubsystemData }) => { - const { act } = useBackend(); - const { data } = props; - const { - name, - ref, - init_order, - last_fire, - next_fire, - can_fire, - doesnt_fire, - cost_ms, - tick_usage, - tick_overrun, - initialized, - initialization_failure_message, - } = data; - - let icon = 'play'; - if (!initialized) { - icon = 'circle-exclamation'; - } else if (doesnt_fire) { - icon = 'check'; - } else if (!can_fire) { - icon = 'pause'; - } - - return ( - { - act('view_variables', { ref: ref }); - }} - /> - } - > - - {init_order} - {last_fire} - {next_fire} - {cost_ms}ms - - {(tick_usage * 0.01).toFixed(2)}% - - - {(tick_overrun * 0.01).toFixed(2)}% - - {initialization_failure_message ? ( - - {initialization_failure_message} - - ) : undefined} - - - ); -}; - -enum SubsystemSortBy { - INIT_ORDER = 'Init Order', - NAME = 'Name', - LAST_FIRE = 'Last Fire', - NEXT_FIRE = 'Next Fire', - TICK_USAGE = 'Tick Usage', - TICK_OVERRUN = 'Tick Overrun', - COST = 'Cost', -} - -const sortSubsystemBy = ( - subsystems: SubsystemData[], - sortBy: SubsystemSortBy, - asending: boolean = true, -) => { - let sorted = subsystems.sort((left, right) => { - switch (sortBy) { - case SubsystemSortBy.INIT_ORDER: - return left.init_order - right.init_order; - case SubsystemSortBy.NAME: - return left.name.localeCompare(right.name); - case SubsystemSortBy.LAST_FIRE: - return left.last_fire - right.last_fire; - case SubsystemSortBy.NEXT_FIRE: - return left.next_fire - right.next_fire; - case SubsystemSortBy.TICK_USAGE: - return left.tick_usage - right.tick_usage; - case SubsystemSortBy.TICK_OVERRUN: - return left.tick_overrun - right.tick_overrun; - case SubsystemSortBy.COST: - return left.cost_ms - right.cost_ms; - } - }); - if (!asending) { - sorted.reverse(); - } - return sorted; -}; - -export const ControllerOverview = () => { - const { act, data } = useBackend(); - const { world_time, map_cpu, subsystems, fast_update } = data; - - const [filterName, setFilterName] = useState(''); - const [sortBy, setSortBy] = useState(SubsystemSortBy.NAME); - const [sortAscending, setSortAscending] = useState(true); - - let filteredSubsystems = useMemo(() => { - if (!filterName) { - return subsystems; - } - - return subsystems.filter(() => - createSearch(filterName, (subsystem: SubsystemData) => subsystem.name), - ); - }, [filterName, subsystems]); - - let sortedSubsystems = useMemo(() => { - return sortSubsystemBy(filteredSubsystems, sortBy, sortAscending); - }, [sortBy, sortAscending, filteredSubsystems]); - - const overallUsage = subsystems.reduce( - (acc, subsystem) => acc + subsystem.tick_usage, - 0, - ); - const overallOverrun = subsystems.reduce( - (acc, subsystem) => acc + subsystem.tick_overrun, - 0, - ); - - return ( - - -
    - - World Time: {world_time} - Map CPU: {map_cpu.toFixed(2)}% - - Overall Usage: {(overallUsage * 0.01).toFixed(2)}% - - - Overall Overrun: {(overallOverrun * 0.01).toFixed(2)}% - - -
    -
    { - act('toggle_fast_update'); - }} - /> - } - > - setFilterName(value)} - /> - - - - - - -
    -
    - - {sortedSubsystems.map((subsystem) => ( - - ))} - -
    -
    -
    - ); -}; diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/OverviewSection.tsx b/tgui/packages/tgui/interfaces/ControllerOverview/OverviewSection.tsx new file mode 100644 index 00000000000..919c19631f6 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/OverviewSection.tsx @@ -0,0 +1,57 @@ +import { useBackend } from '../../backend'; +import { Button, LabeledList, Section, Stack } from '../../components'; +import { ControllerData } from './types'; + +export function OverviewSection(props) { + const { act, data } = useBackend(); + const { fast_update, map_cpu, subsystems = [], world_time } = data; + + let overallUsage = 0; + let overallOverrun = 0; + for (let i = 0; i < subsystems.length; i++) { + overallUsage += subsystems[i].tick_usage; + overallOverrun += subsystems[i].tick_overrun; + } + + return ( +
    { + act('toggle_fast_update'); + }} + > + Fast + + } + > + + + + + {world_time.toFixed(1)} + + + {map_cpu.toFixed(2)}% + + + + + + + {(overallUsage * 0.01).toFixed(2)}% + + + {(overallOverrun * 0.01).toFixed(2)}% + + + + +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/SubsystemDialog.tsx b/tgui/packages/tgui/interfaces/ControllerOverview/SubsystemDialog.tsx new file mode 100644 index 00000000000..21acd2dca1d --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/SubsystemDialog.tsx @@ -0,0 +1,69 @@ +import { + Box, + Button, + Divider, + LabeledList, + Modal, + Stack, +} from '../../components'; +import { SubsystemData } from './types'; + +type Props = { + subsystem: SubsystemData; + onClose: () => void; +}; + +export function SubsystemDialog(props: Props) { + const { subsystem, onClose } = props; + const { + cost_ms, + init_order, + initialization_failure_message, + last_fire, + name, + next_fire, + tick_overrun, + tick_usage, + } = subsystem; + + return ( + + + + {name} + + + + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/SubsystemRow.tsx b/tgui/packages/tgui/interfaces/ControllerOverview/SubsystemRow.tsx new file mode 100644 index 00000000000..0a0bef6a9e6 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/SubsystemRow.tsx @@ -0,0 +1,107 @@ +import { Dispatch } from 'react'; + +import { useBackend } from '../../backend'; +import { + Button, + Icon, + ProgressBar, + Stack, + Table, + Tooltip, +} from '../../components'; +import { SORTING_TYPES } from './contants'; +import { SortType, SubsystemData } from './types'; + +type Props = { + max: number; + setSelected: Dispatch; + showBars: boolean; + sortType: SortType; + subsystem: SubsystemData; +}; + +export function SubsystemRow(props: Props) { + const { act } = useBackend(); + const { max, setSelected, showBars, sortType, subsystem } = props; + const { can_fire, doesnt_fire, initialized, name, ref } = subsystem; + + const { propName } = SORTING_TYPES[sortType]; + const value = subsystem[propName]; + + let icon = 'play'; + let color = 'good'; + let tooltip = 'Operational'; + if (!initialized) { + icon = 'circle-exclamation'; + color = 'darkgreen'; + tooltip = 'Not initialized'; + } else if (doesnt_fire) { + icon = 'check'; + color = 'grey'; + tooltip = 'Does not fire'; + } else if (!can_fire) { + icon = 'pause'; + color = 'grey'; + tooltip = 'Paused'; + } + + let valueDisplay = ''; + let rangeDisplay = {}; + if (showBars) { + if (sortType === SortType.Cost) { + valueDisplay = value.toFixed(0) + 'ms'; + rangeDisplay = { + average: [75, 124.99], + bad: [125, Infinity], + }; + } else { + valueDisplay = (value * 0.01).toFixed(2) + '%'; + rangeDisplay = { + average: [10, 24.99], + bad: [25, Infinity], + }; + } + } else { + valueDisplay = value; + } + + return ( + + + + + + + setSelected(subsystem)}> + {showBars ? ( + + {name} {valueDisplay} + + ) : ( + + )} + + + + + + } + > + + {sorted.map((subsystem) => ( + + ))} +
    +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/contants.ts b/tgui/packages/tgui/interfaces/ControllerOverview/contants.ts new file mode 100644 index 00000000000..fdd28bfd36b --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/contants.ts @@ -0,0 +1,43 @@ +type SortType = { + label: string; + propName: string; + inDeciseconds: boolean; +}; + +export const SORTING_TYPES: readonly SortType[] = [ + { + label: 'Alphabetical', + propName: 'name', + inDeciseconds: false, + }, + { + label: 'Cost', + propName: 'cost_ms', + inDeciseconds: true, + }, + { + label: 'Init Order', + propName: 'init_order', + inDeciseconds: false, + }, + { + label: 'Last Fire', + propName: 'last_fire', + inDeciseconds: false, + }, + { + label: 'Next Fire', + propName: 'next_fire', + inDeciseconds: false, + }, + { + label: 'Tick Usage', + propName: 'tick_usage', + inDeciseconds: true, + }, + { + label: 'Tick Overrun', + propName: 'tick_overrun', + inDeciseconds: true, + }, +]; diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/filters.ts b/tgui/packages/tgui/interfaces/ControllerOverview/filters.ts new file mode 100644 index 00000000000..8d975ac9a71 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/filters.ts @@ -0,0 +1,45 @@ +import { SortType } from './types'; + +export type FilterState = { + ascending: boolean; + inactive: boolean; + query: string; + smallValues: boolean; + sortType: SortType; +}; + +export enum FilterAction { + Ascending = 'SET_SORT_ASCENDING', + Inactive = 'SET_FILTER_INACTIVE', + SmallValues = 'SET_FILTER_SMALL_VALUES', + SortType = 'SET_SORT_TYPE', + Query = 'SET_FILTER_QUERY', + Update = 'UPDATE_FILTER', +} + +type Action = + | { type: FilterAction.Ascending; payload: boolean } + | { type: FilterAction.Inactive; payload: boolean } + | { type: FilterAction.SmallValues; payload: boolean } + | { type: FilterAction.SortType; payload: SortType } + | { type: FilterAction.Query; payload: string } + | { type: FilterAction.Update; payload: Partial }; + +export function filterReducer(state: FilterState, action: Action): FilterState { + switch (action.type) { + case FilterAction.Inactive: + return { ...state, inactive: action.payload }; + case FilterAction.SmallValues: + return { ...state, smallValues: action.payload }; + case FilterAction.Ascending: + return { ...state, ascending: action.payload }; + case FilterAction.SortType: + return { ...state, sortType: action.payload }; + case FilterAction.Query: + return { ...state, query: action.payload }; + case FilterAction.Update: + return { ...state, ...action.payload }; + default: + return state; + } +} diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/index.tsx b/tgui/packages/tgui/interfaces/ControllerOverview/index.tsx new file mode 100644 index 00000000000..388d3d43678 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/index.tsx @@ -0,0 +1,152 @@ +import { useReducer, useState } from 'react'; + +import { Button, Dropdown, Input, Section, Stack } from '../../components'; +import { Window } from '../../layouts'; +import { SORTING_TYPES } from './contants'; +import { FilterAction, filterReducer, FilterState } from './filters'; +import { OverviewSection } from './OverviewSection'; +import { SubsystemDialog } from './SubsystemDialog'; +import { SubsystemViews } from './SubsystemViews'; +import { SortType, SubsystemData } from './types'; + +export function ControllerOverview(props) { + return ( + + + + + + ); +} + +export function ControllerContent(props) { + const [state, dispatch] = useReducer(filterReducer, { + ascending: true, + inactive: true, + query: '', + smallValues: false, + sortType: SortType.Name, + }); + + const [selected, setSelected] = useState(); + + const { label, inDeciseconds } = + SORTING_TYPES?.[state.sortType] || SORTING_TYPES[0]; + + function onSelectionHandler(value: string) { + const updates: Partial = { + sortType: SORTING_TYPES.findIndex((type) => type.label === value), + }; + + if (updates.sortType === undefined) return; + + const { inDeciseconds } = SORTING_TYPES[updates.sortType]; + + updates.ascending = !inDeciseconds; + updates.smallValues = inDeciseconds; + + dispatch({ type: FilterAction.Update, payload: updates }); + } + + return ( + + {selected && ( + setSelected(undefined)} + subsystem={selected} + /> + )} + + + + +
    + + + + + + dispatch({ type: FilterAction.Query, payload: value }) + } + placeholder="By name" + value={state.query} + width="85%" + /> + + + + + + + + + + + type.label)} + selected={label} + displayText={label} + onSelected={onSelectionHandler} + /> + + + + + + + + +
    +
    + + + +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/ControllerOverview/types.ts b/tgui/packages/tgui/interfaces/ControllerOverview/types.ts new file mode 100644 index 00000000000..604989b1f75 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview/types.ts @@ -0,0 +1,33 @@ +import { BooleanLike } from 'common/react'; + +export type SubsystemData = { + can_fire: BooleanLike; + cost_ms: number; + doesnt_fire: BooleanLike; + init_order: number; + initialization_failure_message: string | undefined; + initialized: BooleanLike; + last_fire: number; + name: string; + next_fire: number; + ref: string; + tick_overrun: number; + tick_usage: number; +}; + +export type ControllerData = { + world_time: number; + fast_update: BooleanLike; + map_cpu: number; + subsystems: SubsystemData[]; +}; + +export enum SortType { + Name, + Cost, + InitOrder, + LastFire, + NextFire, + TickUsage, + TickOverrun, +} diff --git a/tgui/packages/tgui/interfaces/CrewConsole.jsx b/tgui/packages/tgui/interfaces/CrewConsole.jsx deleted file mode 100644 index ef3f8c31a38..00000000000 --- a/tgui/packages/tgui/interfaces/CrewConsole.jsx +++ /dev/null @@ -1,195 +0,0 @@ -import { sortBy } from 'common/collections'; - -import { useBackend } from '../backend'; -import { Box, Button, Icon, Section, Table } from '../components'; -import { COLORS } from '../constants'; -import { Window } from '../layouts'; - -const HEALTH_COLOR_BY_LEVEL = [ - '#17d568', - '#c4cf2d', - '#e67e22', - '#ed5100', - '#e74c3c', - '#801308', -]; - -const STAT_LIVING = 0; -const STAT_DEAD = 4; - -const jobIsHead = (jobId) => jobId % 10 === 0; - -const jobToColor = (jobId) => { - if (jobId === 0) { - return COLORS.department.captain; - } - if (jobId >= 10 && jobId < 20) { - return COLORS.department.security; - } - if (jobId >= 20 && jobId < 30) { - return COLORS.department.medbay; - } - if (jobId >= 30 && jobId < 40) { - return COLORS.department.science; - } - if (jobId >= 40 && jobId < 50) { - return COLORS.department.engineering; - } - if (jobId >= 50 && jobId < 60) { - return COLORS.department.cargo; - } - if (jobId >= 60 && jobId < 200) { - return COLORS.department.service; - } - if (jobId >= 200 && jobId < 230) { - return COLORS.department.centcom; - } - return COLORS.department.other; -}; - -const statToIcon = (life_status) => { - switch (life_status) { - case STAT_LIVING: - return 'heart'; - case STAT_DEAD: - return 'skull'; - } - return 'heartbeat'; -}; - -const healthToAttribute = (oxy, tox, burn, brute, attributeList) => { - const healthSum = oxy + tox + burn + brute; - const level = Math.min(Math.max(Math.ceil(healthSum / 25), 0), 5); - return attributeList[level]; -}; - -const HealthStat = (props) => { - const { type, value } = props; - return ( - - {value} - - ); -}; - -export const CrewConsole = () => { - return ( - - -
    - -
    -
    -
    - ); -}; - -const CrewTable = (props) => { - const { act, data } = useBackend(); - const sensors = sortBy(data.sensors ?? [], (s) => s.ijob); - return ( - - - Name - - - Vitals - - - Position - - {!!data.link_allowed && ( - - Tracking - - )} - - {sensors.map((sensor) => ( - - ))} -
    - ); -}; - -const CrewTableEntry = (props) => { - const { act, data } = useBackend(); - const { link_allowed } = data; - const { sensor_data } = props; - const { - name, - assignment, - ijob, - life_status, - oxydam, - toxdam, - burndam, - brutedam, - area, - can_track, - } = sensor_data; - - return ( - - - {name} - {assignment !== undefined ? ` (${assignment})` : ''} - - - {oxydam !== undefined ? ( - - ) : life_status !== STAT_DEAD ? ( - - ) : ( - - )} - - - {oxydam !== undefined ? ( - - - {'/'} - - {'/'} - - {'/'} - - - ) : life_status !== STAT_DEAD ? ( - 'Alive' - ) : ( - 'Dead' - )} - - - {area !== undefined ? ( - area - ) : ( - - )} - - {!!link_allowed && ( - - + + + setSearchQuery((e.target as HTMLTextAreaElement).value) + } + /> + + } + > + + + Name + + + Vitals + + + Position + + {!!data.link_allowed && ( + + Tracking + + )} + + {sorted.map((sensor) => ( + + ))} +
    +
    + ); +}; + +type CrewTableEntryProps = { + sensor_data: CrewSensor; +}; + +const CrewTableEntry = (props: CrewTableEntryProps) => { + const { act, data } = useBackend(); + const { link_allowed } = data; + const { sensor_data } = props; + const { + name, + assignment, + ijob, + life_status, + oxydam, + toxdam, + burndam, + brutedam, + area, + can_track, + } = sensor_data; + + return ( + + + {name} + {assignment !== undefined ? ` (${assignment})` : ''} + + + {oxydam !== undefined ? ( + + ) : life_status !== STAT_DEAD ? ( + + ) : ( + + )} + + + {oxydam !== undefined ? ( + + + {'/'} + + {'/'} + + {'/'} + + + ) : life_status !== STAT_DEAD ? ( + 'Alive' + ) : ( + 'Dead' + )} + + + {area !== '~' && area !== undefined ? ( + area + ) : ( + + )} + + {!!link_allowed && ( + + + + )} + + ); +}; diff --git a/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx b/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx index 457c909b2ca..12dad26bc71 100644 --- a/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx +++ b/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx @@ -6,228 +6,315 @@ import { Button, Divider, Dropdown, - Flex, Icon, + LabeledList, Modal, + NoticeBox, Section, + Stack, Table, + Tooltip, } from '../components'; import { ButtonCheckbox } from '../components/Button'; import { Window } from '../layouts'; -type PlayerLike = { - [key: string]: { - host: number; - ready: BooleanLike; - }; +type Player = Record; + +type PlayerInfo = { + host: number; + ready: BooleanLike; }; type Modifier = { - name: string; desc: string; modpath: string; - selected: BooleanLike; - selectable: BooleanLike; - player_selected: BooleanLike; + name: string; player_selectable: BooleanLike; + player_selected: BooleanLike; + selectable: BooleanLike; + selected: BooleanLike; +}; + +type Map = { + desc: string; + max_players: number; + min_players: number; + name: string; + time: number; }; type Data = { - self: string; - host: BooleanLike; + active_mods: string; admin: BooleanLike; - playing: BooleanLike; + host: BooleanLike; + loadoutdesc: string; loadouts: string[]; + map: Map; maps: string[]; - map: { - name: string; - desc: string; - time: number; - min_players: number; - max_players: number; - }; mod_menu_open: BooleanLike; modifiers: Modifier[]; - active_mods: string; - loadoutdesc: string; - players: PlayerLike[]; - observers: PlayerLike[]; + observers: Player[]; + players: Player[]; + playing: BooleanLike; + self: string; }; -export const DeathmatchLobby = (props) => { +export function DeathmatchLobby(props) { const { act, data } = useBackend(); - const { modifiers = [] } = data; + const { admin, observers = [], self, players } = data; + + const allReady = Object.keys(players).every( + (player) => players[player].ready, + ); + return ( - - -
    - - - - Name - Loadout - Ready - - {Object.keys(data.players).map((player) => ( - - - {!!data.players[player].host && } - - - {(!( - (data.host && !data.players[player].host) || - data.admin - ) && {player}) || ( - - act('host', { - id: player, - func: value, - }) - } - /> - )} - - - - act('change_loadout', { - player: player, - loadout: value, - }) - } - /> - - - act('ready')} - /> - - - ))} - {Object.keys(data.observers).map((observer) => ( - - - {(!!data.observers[observer].host && ( - - )) || } - - - {(!( - (data.host && !data.observers[observer].host) || - data.admin - ) && {observer}) || ( - - act('host', { - id: observer, - func: value, - }) - } - /> - )} - - Observing - - ))} -
    -
    -
    - + + + + + + + + + + + +
    - - {(!!data.host && ( - - act('host', { - func: 'change_map', - map: value, - }) - } - /> - )) || {data.map.name}} - - - {data.map.desc} - - - Maximum Play Time: {`${data.map.time / 600}min`} -
    - Min players: {data.map.min_players} -
    - Max players: {data.map.max_players} -
    - Current players: {Object.keys(data.players).length} -
    - - {data.active_mods} - {(!!data.admin || !!data.host) && ( - <> - + + + {!!admin && ( + + )} + + + + + +
    -
    -
    - + + )} + + + Loadout Description + + + {loadoutdesc} + {!!playing && ( + <> + + + The game is currently in progress, or loading. + + + )} + + ); +} const ModSelector = (props) => { const { act, data } = useBackend(); @@ -235,21 +322,18 @@ const ModSelector = (props) => { if (!mod_menu_open || !(host || admin)) { return null; } + return ( - {modifiers.map((mod, index) => { return ( { modpath: mod.modpath, }) } - /> + > + {mod.name} + ); })} diff --git a/tgui/packages/tgui/interfaces/DeathmatchPanel.jsx b/tgui/packages/tgui/interfaces/DeathmatchPanel.jsx deleted file mode 100644 index 8ac2ff5f76d..00000000000 --- a/tgui/packages/tgui/interfaces/DeathmatchPanel.jsx +++ /dev/null @@ -1,95 +0,0 @@ -import { useBackend } from '../backend'; -import { - Button, - Dropdown, - Flex, - NoticeBox, - Section, - Stack, - Table, -} from '../components'; -import { Window } from '../layouts'; - -export const DeathmatchPanel = (props, context) => { - const { act, data } = useBackend(context); - const playing = data.playing || ''; - return ( - - - - If you play, you can still possibly be returned to your body (No - Guarantees)! - -
    - - - Host - Map - Players - - {data.lobbies.map((lobby) => ( - - - {(!data.admin && lobby.name) || ( - - act('admin', { - id: lobby.name, - func: value, - }) - } - /> - )} - - {lobby.map} - - {lobby.players}/{lobby.max_players} - - - {(!lobby.playing && ( - <> -
    -
    - +
    + + + + ); +} + +function LobbyPane(props) { + const { data } = useBackend(); + const { lobbies = [] } = data; + + return ( +
    + + + Host + Map + + + + + + + + + + + {lobbies.length === 0 && ( + + + + No lobbies found. Start one! + + + + )} + + {lobbies.map((lobby, index) => ( + + ))} +
    +
    + ); +} + +function LobbyDisplay(props) { + const { act, data } = useBackend(); + const { admin, playing, hosting } = data; + const { lobby } = props; + + const isActive = (!!hosting || !!playing) && playing !== lobby.name; + + return ( + + + {!admin ? ( + lobby.name + ) : ( + + act('admin', { + id: lobby.name, + func: value, + }) + } + /> + )} + + {lobby.map} + + {lobby.players}/{lobby.max_players} + + + {!lobby.playing ? ( + <> + + + )} + + + ); +} diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.jsx b/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.jsx index 9b91ef348fa..e243ef365b0 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.jsx +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.jsx @@ -120,7 +120,8 @@ export class ComponentMenu extends Component { currentLimit: DEFAULT_COMPONENT_MENU_LIMIT, }) } - displayText={`Category: ${selectedTab}`} + selected={selectedTab} + placeholder="Category" color="transparent" className="IntegratedCircuit__BlueBorder" /> diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.jsx b/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.jsx index 2ea8ce922aa..65d0814d8ce 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.jsx +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.jsx @@ -88,7 +88,7 @@ export const FUNDAMENTAL_DATA_TYPES = { color={'transparent'} options={data} onSelected={setValue} - displayText={value} + selected={value} menuWidth={large ? '200px' : undefined} /> ); diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.jsx b/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.jsx index 955e45da41b..45e7e90d737 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.jsx +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.jsx @@ -1,4 +1,5 @@ import { shallowDiffers } from 'common/react'; +import { multiline } from 'common/string'; import { Component } from 'react'; import { @@ -15,7 +16,6 @@ import { VARIABLE_LIST, VARIABLE_NOT_A_LIST, } from './constants'; -import { multiline } from 'common/string'; export class VariableMenu extends Component { constructor(props) { @@ -145,7 +145,7 @@ export class VariableMenu extends Component { { over mb={1.7} width="100%" - displayText={bookName} + selected={bookName} options={inventory.map((book) => book.title)} value={bookName} onSelected={(e) => setBookName(e)} diff --git a/tgui/packages/tgui/interfaces/ListInputModal.tsx b/tgui/packages/tgui/interfaces/ListInputWindow/ListInputModal.tsx similarity index 57% rename from tgui/packages/tgui/interfaces/ListInputModal.tsx rename to tgui/packages/tgui/interfaces/ListInputWindow/ListInputModal.tsx index 8695ac842f7..a56363f2310 100644 --- a/tgui/packages/tgui/interfaces/ListInputModal.tsx +++ b/tgui/packages/tgui/interfaces/ListInputWindow/ListInputModal.tsx @@ -7,35 +7,26 @@ import { KEY_ESCAPE, KEY_UP, KEY_Z, -} from '../../common/keycodes'; -import { useBackend } from '../backend'; -import { Autofocus, Button, Input, Section, Stack } from '../components'; -import { Window } from '../layouts'; -import { InputButtons } from './common/InputButtons'; -import { Loader } from './common/Loader'; +} from '../../../common/keycodes'; +import { useBackend } from '../../backend'; +import { Autofocus, Button, Input, Section, Stack } from '../../components'; +import { InputButtons } from '../common/InputButtons'; -type ListInputData = { - init_value: string; +type ListInputModalProps = { items: string[]; - large_buttons: boolean; + default_item: string; message: string; - timeout: number; - title: string; + on_selected: (entry: string) => void; + on_cancel: () => void; }; -export const ListInputModal = (props) => { - const { act, data } = useBackend(); - const { - items = [], - message = '', - init_value, - large_buttons, - timeout, - title, - } = data; - const [selected, setSelected] = useState(items.indexOf(init_value)); +export const ListInputModal = (props: ListInputModalProps) => { + const { items = [], default_item, message, on_selected, on_cancel } = props; + + const [selected, setSelected] = useState(items.indexOf(default_item)); const [searchBarVisible, setSearchBarVisible] = useState(items.length > 9); const [searchQuery, setSearchQuery] = useState(''); + // User presses up or down on keyboard // Simulates clicking an item const onArrowKey = (key: number) => { @@ -99,82 +90,77 @@ export const ListInputModal = (props) => { const filteredItems = items.filter((item) => item?.toLowerCase().includes(searchQuery.toLowerCase()), ); - // Dynamically changes the window height based on the message. - const windowHeight = - 325 + Math.ceil(message.length / 3) + (large_buttons ? 5 : 0); // Grabs the cursor when no search bar is visible. if (!searchBarVisible) { setTimeout(() => document!.getElementById(selected.toString())?.focus(), 1); } return ( - - {timeout && } - { - const keyCode = window.event ? event.which : event.keyCode; - if (keyCode === KEY_DOWN || keyCode === KEY_UP) { - event.preventDefault(); - onArrowKey(keyCode); +
    { + const keyCode = window.event ? event.which : event.keyCode; + if (keyCode === KEY_DOWN || keyCode === KEY_UP) { + event.preventDefault(); + onArrowKey(keyCode); + } + if (keyCode === KEY_ENTER) { + event.preventDefault(); + on_selected(filteredItems[selected]); + } + if (!searchBarVisible && keyCode >= KEY_A && keyCode <= KEY_Z) { + event.preventDefault(); + onLetterSearch(keyCode); + } + if (keyCode === KEY_ESCAPE) { + event.preventDefault(); + on_cancel(); + } + }} + buttons={ +
    ); }; @@ -183,7 +169,7 @@ export const ListInputModal = (props) => { * If a search query is provided, filters the items. */ const ListDisplay = (props) => { - const { act } = useBackend(); + const { act } = useBackend(); const { filteredItems, onClick, onFocusSearch, searchBarVisible, selected } = props; @@ -227,7 +213,7 @@ const ListDisplay = (props) => { * Closing the bar defaults input to an empty string. */ const SearchBar = (props) => { - const { act } = useBackend(); + const { act } = useBackend(); const { filteredItems, onSearch, searchQuery, selected } = props; return ( diff --git a/tgui/packages/tgui/interfaces/ListInputWindow/index.tsx b/tgui/packages/tgui/interfaces/ListInputWindow/index.tsx new file mode 100644 index 00000000000..29355ff5d21 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ListInputWindow/index.tsx @@ -0,0 +1,44 @@ +import { useBackend } from '../../backend'; +import { Window } from '../../layouts'; +import { Loader } from '../common/Loader'; +import { ListInputModal } from './ListInputModal'; + +type ListInputData = { + init_value: string; + items: string[]; + large_buttons: boolean; + message: string; + timeout: number; + title: string; +}; + +export const ListInputWindow = () => { + const { act, data } = useBackend(); + const { + items = [], + message = '', + init_value, + large_buttons, + timeout, + title, + } = data; + + // Dynamically changes the window height based on the message. + const windowHeight = + 325 + Math.ceil(message.length / 3) + (large_buttons ? 5 : 0); + + return ( + + {timeout && } + + act('submit', { entry })} + on_cancel={() => act('cancel')} + /> + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx b/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx index 889d50de884..11e52b2ac55 100644 --- a/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx +++ b/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx @@ -10,15 +10,23 @@ export function IconDisplay(props: Props) { item: { icon, icon_state }, } = props; - const fallback = ; + const fallback = ; if (!icon) { return fallback; } if (icon_state) { - return ; + return ( + + ); } - return ; + return ; } diff --git a/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx b/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx index 22b0c8532dd..613db1ead53 100644 --- a/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx +++ b/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx @@ -1,4 +1,4 @@ -import { capitalizeAll } from 'common/string'; +import { capitalizeAll, capitalizeFirst } from 'common/string'; import { useBackend } from '../../backend'; import { Tooltip } from '../../components'; @@ -25,28 +25,35 @@ export function LootBox(props: Props) { item = props.item; } + const name = !item.name + ? '???' + : capitalizeFirst(item.name.split(' ')[0]).slice(0, 5); + return ( -
    - act('grab', { - ctrl: event.ctrlKey, - ref: item.ref, - shift: event.shiftKey, - }) - } - onContextMenu={(event) => { - event.preventDefault(); - act('grab', { - middle: true, - ref: item.ref, - shift: true, - }); - }} - > - - {amount > 1 &&
    {amount}
    } +
    +
    + act('grab', { + ctrl: event.ctrlKey, + ref: item.ref, + shift: event.shiftKey, + }) + } + onContextMenu={(event) => { + event.preventDefault(); + act('grab', { + middle: true, + ref: item.ref, + shift: true, + }); + }} + > + + {amount > 1 &&
    {amount}
    } +
    + {name}
    ); diff --git a/tgui/packages/tgui/interfaces/LootPanel/index.tsx b/tgui/packages/tgui/interfaces/LootPanel/index.tsx index bd64113f302..bc6330b1806 100644 --- a/tgui/packages/tgui/interfaces/LootPanel/index.tsx +++ b/tgui/packages/tgui/interfaces/LootPanel/index.tsx @@ -24,7 +24,7 @@ export function LootPanel(props) { const total = contents.length ? contents.length - 1 : 0; return ( - + { if (event.key === KEY.Escape) { diff --git a/tgui/packages/tgui/interfaces/MODsuit.tsx b/tgui/packages/tgui/interfaces/MODsuit.tsx index 9d7fab88bd9..f78bd4dd1d8 100644 --- a/tgui/packages/tgui/interfaces/MODsuit.tsx +++ b/tgui/packages/tgui/interfaces/MODsuit.tsx @@ -226,7 +226,7 @@ const ConfigureListEntry = (props) => { const { act } = useBackend(); return ( act('configure', { diff --git a/tgui/packages/tgui/interfaces/MineBot.tsx b/tgui/packages/tgui/interfaces/MineBot.tsx index 4a3087cf8d6..9118562cdd0 100644 --- a/tgui/packages/tgui/interfaces/MineBot.tsx +++ b/tgui/packages/tgui/interfaces/MineBot.tsx @@ -97,7 +97,7 @@ export const MineBot = (props) => { { return possible_color.color_name; })} diff --git a/tgui/packages/tgui/interfaces/NavBeacon.tsx b/tgui/packages/tgui/interfaces/NavBeacon.tsx index 5194fe42c1c..6cc5036c87f 100644 --- a/tgui/packages/tgui/interfaces/NavBeacon.tsx +++ b/tgui/packages/tgui/interfaces/NavBeacon.tsx @@ -20,11 +20,11 @@ export type Data = { }; export type NavBeaconControl = { - location: String; + location: string; patrol_enabled: BooleanLike; - patrol_next: String; + patrol_next: string; delivery_enabled: BooleanLike; - delivery_direction: String; + delivery_direction: string; cover_locked: BooleanLike; }; @@ -107,7 +107,7 @@ export const NavBeaconControlSection = (props: DisabledProps) => { act('set_delivery_direction', { direction: value, diff --git a/tgui/packages/tgui/interfaces/NtosCard.tsx b/tgui/packages/tgui/interfaces/NtosCard.tsx index 7c3991a487c..5997aa0e91c 100644 --- a/tgui/packages/tgui/interfaces/NtosCard.tsx +++ b/tgui/packages/tgui/interfaces/NtosCard.tsx @@ -240,7 +240,7 @@ const TemplateDropdown = (props) => { { return templates[path]; })} @@ -249,6 +249,7 @@ const TemplateDropdown = (props) => { name: sel, }) } + selected="None" /> diff --git a/tgui/packages/tgui/interfaces/NtosRoboControl.jsx b/tgui/packages/tgui/interfaces/NtosRoboControl.jsx index 20c70220d36..9b55c90a456 100644 --- a/tgui/packages/tgui/interfaces/NtosRoboControl.jsx +++ b/tgui/packages/tgui/interfaces/NtosRoboControl.jsx @@ -2,7 +2,6 @@ import { useBackend, useSharedState } from '../backend'; import { Box, Button, - Dropdown, LabeledList, ProgressBar, Section, @@ -71,19 +70,22 @@ export const NtosRoboControl = (props) => { + Drone Pings + {dronepingtypes.map((ping_type) => ( + + ))} {drones?.map((drone) => ( diff --git a/tgui/packages/tgui/interfaces/NtosScipaper.jsx b/tgui/packages/tgui/interfaces/NtosScipaper.jsx index 3866ccab24c..2af2cd12f43 100644 --- a/tgui/packages/tgui/interfaces/NtosScipaper.jsx +++ b/tgui/packages/tgui/interfaces/NtosScipaper.jsx @@ -93,7 +93,7 @@ const PaperPublishing = (props) => { act('select_file', { selected_uid: fileList[ordfile_name], @@ -117,7 +117,7 @@ const PaperPublishing = (props) => { act('select_experiment', { selected_expath: expList[experiment_name], @@ -141,7 +141,7 @@ const PaperPublishing = (props) => { String(number))} - displayText={tier ? String(tier) : '-'} + selected={String(tier)} onSelected={(new_tier) => act('select_tier', { selected_tier: Number(new_tier), @@ -165,7 +165,7 @@ const PaperPublishing = (props) => { act('select_partner', { selected_partner: allowedPartners[new_partner], diff --git a/tgui/packages/tgui/interfaces/NtosVirtualPet.tsx b/tgui/packages/tgui/interfaces/NtosVirtualPet.tsx index 7b61f2b566e..1894aa703d6 100644 --- a/tgui/packages/tgui/interfaces/NtosVirtualPet.tsx +++ b/tgui/packages/tgui/interfaces/NtosVirtualPet.tsx @@ -268,7 +268,7 @@ const PetTricks = (props) => { UpdateSequence(index, selected)} /> @@ -354,7 +354,7 @@ const Customization = (props) => {
    { return selected_hat.hat_name; })} @@ -369,7 +369,7 @@ const Customization = (props) => {
    { return possible_color.color_name; })} diff --git a/tgui/packages/tgui/interfaces/PersonalCrafting.tsx b/tgui/packages/tgui/interfaces/PersonalCrafting.tsx index 96ec4b818b3..d45890d271a 100644 --- a/tgui/packages/tgui/interfaces/PersonalCrafting.tsx +++ b/tgui/packages/tgui/interfaces/PersonalCrafting.tsx @@ -701,13 +701,33 @@ const RecipeContentCompact = ({ item, craftable, busy, mode }) => { ? 'utensils' : 'hammer' } - iconSpin={busy ? 1 : 0} + iconSpin={!!busy} onClick={() => act('make', { recipe: item.ref, }) } /> + {!!item.mass_craftable && ( +
    diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/RandomizationButton.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/RandomizationButton.tsx index 4152e2d77c1..0620f22da3a 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/RandomizationButton.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/RandomizationButton.tsx @@ -1,6 +1,6 @@ import { exhaustiveCheck } from 'common/exhaustive'; -import { Dropdown, Icon } from '../../components'; +import { Dropdown } from '../../components'; import { RandomSetting } from './data'; const options = [ @@ -48,12 +48,13 @@ export const RandomizationButton = (props: { color={color} {...dropdownProps} clipSelectedText={false} - displayText={} + icon="dice-d20" options={options} noChevron onSelected={setValue} menuWidth="120px" width={1.85} + selected="None" /> ); }; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx index 6da6aec820d..26a05dfbad6 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx @@ -1,5 +1,5 @@ -import { sort, sortBy } from 'common/collections'; -import { BooleanLike, classes } from 'common/react'; +import { sortBy } from 'common/collections'; +import { BooleanLike } from 'common/react'; import { ComponentType, createElement, @@ -124,16 +124,15 @@ export const CheckboxInputInverse = ( ); }; -export const createDropdownInput = ( +export function createDropdownInput( // Map of value to display texts choices: Record, dropdownProps?: Record, -): FeatureValue => { +): FeatureValue { return (props: FeatureValueProps) => { return ( ( /> ); }; -}; +} export type FeatureChoicedServerData = { choices: string[]; @@ -158,136 +157,6 @@ export type FeatureChoicedServerData = { export type FeatureChoiced = Feature; -const capitalizeFirstLetter = (text: string) => - text.toString().charAt(0).toUpperCase() + text.toString().slice(1); - -export const StandardizedDropdown = (props: { - choices: string[]; - disabled?: boolean; - displayNames: Record; - onSetValue: (newValue: string) => void; - value: string; - buttons?: boolean; -}) => { - const { choices, disabled, buttons, displayNames, onSetValue, value } = props; - - return ( - { - return { - displayText: displayNames[choice], - value: choice, - }; - })} - /> - ); -}; - -export const FeatureDropdownInput = ( - props: FeatureValueProps & { - disabled?: boolean; - buttons?: boolean; - }, -) => { - const serverData = props.serverData; - if (!serverData) { - return null; - } - - const displayNames = - serverData.display_names || - Object.fromEntries( - serverData.choices.map((choice) => [ - choice, - capitalizeFirstLetter(choice), - ]), - ); - - return ( - - ); -}; - -export type FeatureWithIcons = Feature< - { value: T }, - T, - FeatureChoicedServerData ->; - -export const FeatureIconnedDropdownInput = ( - props: FeatureValueProps< - { - value: string; - }, - string, - FeatureChoicedServerData - >, -) => { - const serverData = props.serverData; - if (!serverData) { - return null; - } - - const icons = serverData.icons; - - const textNames = - serverData.display_names || - Object.fromEntries( - serverData.choices.map((choice) => [ - choice, - capitalizeFirstLetter(choice), - ]), - ); - - const displayNames = Object.fromEntries( - Object.entries(textNames).map(([choice, textName]) => { - let element: ReactNode = textName; - - if (icons && icons[choice]) { - const icon = icons[choice]; - element = ( - - - - - - {element} - - ); - } - - return [choice, element]; - }), - ); - - return ( - - ); -}; - export type FeatureNumericData = { minimum: number; maximum: number; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_core_display.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_core_display.tsx index 6b3e10bb10c..0e73c28526a 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_core_display.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_core_display.tsx @@ -1,4 +1,5 @@ -import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base'; +import {} from '../base'; +import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../dropdowns'; export const preferred_ai_core_display: FeatureWithIcons = { name: 'AI core display', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_emote_display.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_emote_display.tsx index c8a59a5d9a4..3e958297b88 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_emote_display.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_emote_display.tsx @@ -1,4 +1,4 @@ -import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base'; +import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../dropdowns'; export const preferred_ai_emote_display: FeatureWithIcons = { name: 'AI emote display', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_hologram_display.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_hologram_display.tsx index 423fcea8ed2..46d572fcda6 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_hologram_display.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/ai_hologram_display.tsx @@ -1,4 +1,4 @@ -import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base'; +import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../dropdowns'; export const preferred_ai_hologram_display: FeatureWithIcons = { name: 'AI hologram display', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/body_type.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/body_type.tsx index de9d6523e2c..3746e62ceee 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/body_type.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/body_type.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const body_type: FeatureChoiced = { name: 'Body type', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/food_allergy.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/food_allergy.tsx index f5b0ea37ca8..bdcd91ac7af 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/food_allergy.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/food_allergy.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const food_allergy: FeatureChoiced = { name: 'Food Allergy', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/glasses.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/glasses.tsx index 60cb3131f1b..df73451c35a 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/glasses.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/glasses.tsx @@ -1,4 +1,4 @@ -import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base'; +import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../dropdowns'; export const glasses: FeatureWithIcons = { name: 'Glasses', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/hemiplegic.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/hemiplegic.tsx index 0494558ba77..35837c80099 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/hemiplegic.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/hemiplegic.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const hemiplegic: FeatureChoiced = { name: 'Hemiplegic', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/junkie.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/junkie.tsx index 8ac11ed968d..586b69d86c2 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/junkie.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/junkie.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const junkie: FeatureChoiced = { name: 'Addiction', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/language.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/language.tsx index 6b1a1be1220..39c48ae40d6 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/language.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/language.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const language: FeatureChoiced = { name: 'Language', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx index fdc9a2be5da..196dea45c5d 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx @@ -1,9 +1,5 @@ -import { - Feature, - FeatureChoiced, - FeatureDropdownInput, - FeatureShortTextInput, -} from '../base'; +import { Feature, FeatureChoiced, FeatureShortTextInput } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const pda_theme: FeatureChoiced = { name: 'PDA Theme', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/phobia.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/phobia.tsx index dd14349277f..f2f35f65e16 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/phobia.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/phobia.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const phobia: FeatureChoiced = { name: 'Phobia', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pride_pin.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pride_pin.tsx index b0fae6092a1..70c6f8a8efe 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pride_pin.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pride_pin.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const pride_pin: FeatureChoiced = { name: 'Pride Pin', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prisoner_crime.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prisoner_crime.tsx index 2ca17aa4e36..b551b68ee2e 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prisoner_crime.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prisoner_crime.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const prisoner_crime: FeatureChoiced = { name: 'Prisoner crime', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_limb.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_limb.tsx index adbaefe90c8..87a8ea23de1 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_limb.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_limb.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const prosthetic: FeatureChoiced = { name: 'Prosthetic', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_organ.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_organ.tsx index da0e37a4173..5b484d5960e 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_organ.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/prosthetic_organ.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const prosthetic_organ: FeatureChoiced = { name: 'Prosthetic Organ', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/security_department.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/security_department.tsx index e9f380bd675..a1311e347c8 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/security_department.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/security_department.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const prefered_security_department: FeatureChoiced = { name: 'Security department', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skin_tone.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skin_tone.tsx index 2e5c18f2324..95029374bd2 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skin_tone.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skin_tone.tsx @@ -1,12 +1,8 @@ import { sortBy } from 'common/collections'; +import { useMemo } from 'react'; +import { Box, Dropdown, Stack } from 'tgui/components'; -import { Box, Stack } from '../../../../../components'; -import { - Feature, - FeatureChoicedServerData, - FeatureValueProps, - StandardizedDropdown, -} from '../base'; +import { Feature, FeatureChoicedServerData, FeatureValueProps } from '../base'; type HexValue = { lightness: number; @@ -24,43 +20,53 @@ const sortHexValues = (array: [string, HexValue][]) => export const skin_tone: Feature = { name: 'Skin tone', component: (props: FeatureValueProps) => { - const { handleSetValue, serverData, value } = props; + const { handleSetValue, serverData } = props; if (!serverData) { return null; } + const value = { value: props.value }; + + const displayNames = useMemo(() => { + const sorted = sortHexValues(Object.entries(serverData.to_hex)); + + return sorted.map(([key, colorInfo]) => { + const displayName = serverData.display_names[key]; + + return { + value: key, + displayText: ( + + + + + + {displayName} + + ), + }; + }); + }, [serverData.display_names]); + return ( - key, - )} - displayNames={Object.fromEntries( - Object.entries(serverData.display_names).map(([key, displayName]) => { - const hexColor = serverData.to_hex[key]; - - return [ - key, - - - - - - {displayName} - , - ]; - }), - )} - onSetValue={handleSetValue} - value={value} + option.value === value.value) + ?.displayText + } + onSelected={(value) => handleSetValue(value)} + options={displayNames} + selected={value.value} + width="100%" /> ); }, diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/brain_type.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/brain_type.tsx index da0fd78de3a..5364d6d767d 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/brain_type.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/brain_type.tsx @@ -1,5 +1,6 @@ // THIS IS A SKYRAT UI FILE -import { FeatureChoiced, FeatureDropdownInput } from '../../base'; +import { FeatureChoiced } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const brain_type: FeatureChoiced = { name: 'Silicon and Synthetic Brain Type', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_laugh.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_laugh.tsx index ae03698b2b3..2c118ac111b 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_laugh.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_laugh.tsx @@ -1,5 +1,6 @@ // THIS IS A SKYRAT UI FILE -import { FeatureChoiced, FeatureDropdownInput } from '../../base'; +import { FeatureChoiced } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const character_laugh: FeatureChoiced = { name: 'Character Laugh', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_scream.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_scream.tsx index 9f6405feead..d6ec7c5bcf0 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_scream.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/character_scream.tsx @@ -1,5 +1,6 @@ // THIS IS A SKYRAT UI FILE -import { FeatureChoiced, FeatureDropdownInput } from '../../base'; +import { FeatureChoiced } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const character_scream: FeatureChoiced = { name: 'Character Scream', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/genitals.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/genitals.tsx index 9f420b7ebd9..60818536339 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/genitals.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/genitals.tsx @@ -4,7 +4,6 @@ import { Feature, FeatureChoiced, FeatureChoicedServerData, - FeatureDropdownInput, FeatureNumberInput, FeatureNumeric, FeatureToggle, @@ -12,6 +11,7 @@ import { FeatureTriColorInput, FeatureValueProps, } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const feature_penis: Feature = { name: 'Penis Choice', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/loadout_override_preference.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/loadout_override_preference.tsx index c0e9cda397e..87de99fb615 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/loadout_override_preference.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/loadout_override_preference.tsx @@ -1,5 +1,6 @@ // THIS IS A SKYRAT UI FILE -import { Feature, FeatureDropdownInput } from '../../base'; +import { Feature } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const loadout_override_preference: Feature = { name: 'Loadout Item Preference', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/pet_owner.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/pet_owner.tsx index 45e2c678965..88579aa989f 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/pet_owner.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/pet_owner.tsx @@ -1,10 +1,6 @@ // THIS IS A SKYRAT UI FILE -import { - Feature, - FeatureChoiced, - FeatureDropdownInput, - FeatureShortTextInput, -} from '../../base'; +import { Feature, FeatureChoiced, FeatureShortTextInput } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const pet_owner: FeatureChoiced = { name: 'Pet Owner', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/species_features.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/species_features.tsx index c77e86659c2..120e2fdd5c8 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/species_features.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/skyrat/species_features.tsx @@ -5,7 +5,6 @@ import { FeatureChoiced, FeatureChoicedServerData, FeatureColorInput, - FeatureDropdownInput, FeatureNumberInput, FeatureShortTextInput, FeatureTextInput, @@ -14,6 +13,7 @@ import { FeatureTriColorInput, FeatureValueProps, } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const feature_leg_type: FeatureChoiced = { name: 'Leg type', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/trans_prosthetic.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/trans_prosthetic.tsx index 368a2a16a1b..fc8601e3cc7 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/trans_prosthetic.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/trans_prosthetic.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const trans_prosthetic: FeatureChoiced = { name: 'Augment', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/tts_voice.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/tts_voice.tsx index 94a208158c5..1f588f07f15 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/tts_voice.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/tts_voice.tsx @@ -2,11 +2,11 @@ import { Button, Stack } from '../../../../../components'; import { FeatureChoiced, FeatureChoicedServerData, - FeatureDropdownInput, FeatureNumeric, FeatureSliderInput, FeatureValueProps, } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; const FeatureTTSDropdownInput = ( props: FeatureValueProps, diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/uplink_loc.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/uplink_loc.tsx index 06c125c33fc..2b1ffe26a32 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/uplink_loc.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/uplink_loc.tsx @@ -1,4 +1,5 @@ -import { FeatureChoiced, FeatureDropdownInput } from '../base'; +import { FeatureChoiced } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const uplink_loc: FeatureChoiced = { name: 'Uplink Spawn Location', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dropdowns.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dropdowns.tsx new file mode 100644 index 00000000000..32e1161e636 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dropdowns.tsx @@ -0,0 +1,113 @@ +import { classes } from 'common/react'; +import { capitalizeFirst } from 'common/string'; +import { ReactNode } from 'react'; + +import { Box, Dropdown, Stack } from '../../../../components'; +import { Feature, FeatureChoicedServerData, FeatureValueProps } from './base'; + +type DropdownInputProps = FeatureValueProps< + string, + string, + FeatureChoicedServerData +> & + Partial<{ + disabled: boolean; + buttons: boolean; + }>; + +type IconnedDropdownInputProps = FeatureValueProps< + string, + string, + FeatureChoicedServerData +>; + +export type FeatureWithIcons = Feature; + +export function FeatureDropdownInput(props: DropdownInputProps) { + const { serverData, disabled, buttons, handleSetValue, value } = props; + + if (!serverData) { + return null; + } + + const { choices, display_names } = serverData; + + const dropdownOptions = choices.map((choice) => { + let displayText: ReactNode = display_names + ? display_names[choice] + : capitalizeFirst(choice); + + return { + displayText, + value: choice, + }; + }); + + let display_text = value; + if (display_names) { + display_text = display_names[value]; + } + + return ( + + ); +} + +export function FeatureIconnedDropdownInput(props: IconnedDropdownInputProps) { + const { serverData, handleSetValue, value } = props; + + if (!serverData) { + return null; + } + + const { choices, display_names, icons } = serverData; + + const dropdownOptions = choices.map((choice) => { + let displayText: ReactNode = display_names + ? display_names[choice] + : capitalizeFirst(choice); + + if (icons?.[choice]) { + displayText = ( + + + + + {displayText} + + ); + } + + return { + displayText, + value: choice, + }; + }); + + let display_text = value; + if (display_names) { + display_text = display_names[value]; + } + + return ( + + ); +} diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx index 03244e9f6ee..d99cd329f55 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/admin.tsx @@ -4,9 +4,9 @@ import { CheckboxInput, Feature, FeatureColorInput, - FeatureDropdownInput, FeatureToggle, } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const asaycolor: Feature = { name: 'Admin chat color', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx index ab973e3659e..5ec16867197 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx @@ -10,10 +10,10 @@ import { CheckboxInput, FeatureChoiced, FeatureChoicedServerData, - FeatureDropdownInput, FeatureToggle, FeatureValueProps, } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const ghost_accs: FeatureChoiced = { name: 'Ghost accessories', @@ -81,9 +81,10 @@ const GhostFormInput = ( return ( = { name: 'MOD active module key', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/parallax.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/parallax.tsx index a7b143a6d3d..914af27c382 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/parallax.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/parallax.tsx @@ -1,4 +1,5 @@ -import { Feature, FeatureDropdownInput } from '../base'; +import { Feature } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const parallax: Feature = { name: 'Parallax (fancy space)', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/preferred_map.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/preferred_map.tsx index 1a1755ce714..5b0860ef91e 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/preferred_map.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/preferred_map.tsx @@ -1,6 +1,7 @@ import { multiline } from 'common/string'; -import { Feature, FeatureDropdownInput } from '../base'; +import { Feature } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const preferred_map: Feature = { name: 'Preferred map', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/screentips.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/screentips.tsx index 5c65c4f100a..ff2cf95a048 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/screentips.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/screentips.tsx @@ -5,9 +5,9 @@ import { Feature, FeatureChoiced, FeatureColorInput, - FeatureDropdownInput, FeatureToggle, } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const screentip_color: Feature = { name: 'Screentips: Screentips color', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/erp_preferences.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/erp_preferences.tsx index 5df13462cc7..fefa333fd7b 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/erp_preferences.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/erp_preferences.tsx @@ -1,10 +1,6 @@ // THIS IS A SKYRAT UI FILE -import { - CheckboxInput, - FeatureChoiced, - FeatureDropdownInput, - FeatureToggle, -} from '../../base'; +import { CheckboxInput, FeatureChoiced, FeatureToggle } from '../../base'; +import { FeatureDropdownInput } from '../../dropdowns'; export const master_erp_pref: FeatureToggle = { name: 'Show/Hide Erotic Roleplay Preferences', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sounds.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sounds.tsx index 0bce5e0982e..34e968f35c4 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sounds.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/sounds.tsx @@ -4,10 +4,10 @@ import { CheckboxInput, Feature, FeatureChoiced, - FeatureDropdownInput, FeatureSliderInput, FeatureToggle, } from '../base'; +import { FeatureDropdownInput } from '../dropdowns'; export const sound_ambience: FeatureToggle = { name: 'Enable ambience', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx index 218b5b3c580..d3fdc0b94de 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ui_style.tsx @@ -46,7 +46,6 @@ const UIStyleInput = ( = { name: 'Eye color', diff --git a/tgui/packages/tgui/interfaces/ProcCallMenu.tsx b/tgui/packages/tgui/interfaces/ProcCallMenu.tsx index 716ae19a147..6db723bcfb4 100644 --- a/tgui/packages/tgui/interfaces/ProcCallMenu.tsx +++ b/tgui/packages/tgui/interfaces/ProcCallMenu.tsx @@ -45,7 +45,7 @@ export const ProcCallMenu = (props) => { @@ -139,7 +139,7 @@ const PortEntry = (props) => { { width="100%" options={sorted_assistance} selected={recipient} - displayText={recipient || 'Pick a Recipient'} + placeholder="Pick a Recipient" onSelected={(value) => setRecipient(value)} /> )} @@ -94,7 +94,7 @@ export const MessageWriteTab = (props) => { width="100%" options={sorted_supply} selected={recipient} - displayText={recipient || 'Pick a Recipient'} + placeholder="Pick a Recipient" onSelected={(value) => setRecipient(value)} /> )} @@ -103,7 +103,7 @@ export const MessageWriteTab = (props) => { width="100%" options={sorted_information} selected={recipient} - displayText={recipient || 'Pick a Recipient'} + placeholder="Pick a Recipient" onSelected={(value) => setRecipient(value)} /> )} diff --git a/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx b/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx index e6e7b02ce67..8496d62552f 100644 --- a/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx +++ b/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx @@ -34,7 +34,7 @@ const FutureStationTraitsPage = (props) => { const { act, data } = useBackend(); const { future_station_traits } = data; - const [selectedTrait, setSelectedTrait] = useState(); + const [selectedTrait, setSelectedTrait] = useState(''); const traitsByName = Object.fromEntries( data.valid_station_traits.map((trait) => { @@ -50,9 +50,9 @@ const FutureStationTraitsPage = (props) => { diff --git a/tgui/packages/tgui/interfaces/TramController.tsx b/tgui/packages/tgui/interfaces/TramController.tsx index 0fccd23a911..f787c8726b5 100644 --- a/tgui/packages/tgui/interfaces/TramController.tsx +++ b/tgui/packages/tgui/interfaces/TramController.tsx @@ -193,7 +193,7 @@ export const TramController = (props) => { width="98.5%" options={destinations.map((id) => id.name)} selected={tripDestination} - displayText={tripDestination || 'Pick a Destination'} + placeholder="Pick a Destination" onSelected={(value) => setTripDestination(value)} />