Files
+3 fa2ab65f07 Missed mirrors (#28919)
Handful of missed mirrors (#3739)

* fix duplicate traits

* Adds a Contraband trait, and implements contraband as a mechanic to security bounties. (#84003)

This PR does a few things but centrally it's all centered around
mechanically enforcing what items are and are-not considered contraband
in-game.

Contraband items are visually indistinguishable from non-contraband. If
an item is Contraband, it can only be detected in two ways:
* After being scanned by an N-Spect scanner, which is a standard item
security item, assuming it still has a charge to do so.
* Via a scanner gate, which can now be upgraded with an N-spect scanner
to allow for it to scan a person and all their contents for contraband.

Contraband items are intended to be determined both logically and
through other relevant examine text. However, here's the short list of
items that are considered contraband, reserving the right to expand the
list.

<details>
  <summary>In hindsight it's kind of a long list.</summary>

* Items that have "contraband" or "illegal" in the name or description.
* Items that allow for the player to obtain other illegal items, that
are NOT particularly stealthy.
* This means that a syndicate uplink is NOT considered contraband, as
they're typically hidden on your person as something else.
* Stealth items under the syndicate uplink, the revolutionary flash, and
some mapped in dangerous items that can come from both syndicate and
company-aligned resources are not considered dangerous.
* Items that are purchased from cargo after emagging or switching to
extended cargo range.
* Items purchased FROM syndicate uplinks, the wizard knowledge scroll,
or other antagonist shops.
* Cursed artifacts/tools magically produced by cultists or heretics.
* Items purchased from the blackmarket.
* Items purchased from the contraband section of vending machines.
* Some drugs and overtly dangerous or criminal byproducts.

</details>

Well, primarily, this is an aid for in-game enforcement of space law.
Based on the length of the above list, we have a LONG, LONG list of
items in-game that are technically considered, in one way or another,
illegal to have on the station, and yet without either metaknowledge of
what those items are, or how they're used, security officers lack some
of the certainty of how to deal with these kinds of encounters.

Additionally to the knowledge aspect of this trait, security officers
may now receive a new civilian bounty to collect items that are
considered contraband, also giving them an incentive to look for and
confiscate contraband that's been found across the station while
upholding space law.

Security has a bounty for 3 different rechargers, and considering access
limitations, most security players aren't going to make this exchange,
so I've lowered the required amount down to 1.

Adjusted the N-spect scanner's description to match it's new
functionality.

The Civilian bounty TGUI now has an additional 1 point of padding to
make it feel less cramped.

https://github.com/tgstation/tgstation/assets/41715314/c3cd4752-b03a-4e0b-959e-1252fcc2369d

**Updated as of 6/19/2024:**
Additionally, some storage items will block the presence of contraband
when going through a contraband aligned scanning gate. These items
include the infiltrator modsuit core, storage implant, void cloak, the
aptly named smuggler's satchel, and the chameleon kit's backpack.

**Updated as of 6/23/2024:**
N-spect scanner now has contextual screentips.

**Updated as of 6/29/2024:**
Scanner gates are now available in all lathes that have a feature
specific to how scanner gates function. So, includes cargo (contraband),
security (weapons), and medbay (diseases).

Originally, this started out as a way to be able to provide more
in-character and in-flavor bounties for security officers, because they
suck! Most security bounties as they exist right now do the worst
possible things from all respective bounties:
* They detract away from a job's actual responsibilities as opposed to
working with them.
* They're best completed while sitting next to your lathe and running
items back to the bounty pad.
* They exist with such esoteric rarity of high quantity of items that
it's miserable to fulfil.

As a result, I started work on this as a framework to allow security
officers to be further incentivized to collect contraband across the
station, either as a result of the gamemode or just through routine
patrols across the station.

Implementing it as a learning tool for security as well just happened to
work out as an additional bonus, and having a function in-game allowing
newer or less experienced players to know if an item is considered
dangerous or conspicuous also works as a particularly good way to
provide information where a player may not know what they're up against.

If nothing else, this might be interesting to try, and if not, I'll just
snip out the QOL changes from it and we'll see how it goes.

Going forward, I am a bit hesitant about the contraband scanner gate
mode, and as such, will try working with the admin team to determine if
that's a good feature to keep around for game health, while hoping to
give it a chance in the fullness of time.

🆑
add: Items spawned via traitor uplinks or are known illegal contraband
on the station can now be scanned and identified as such by the N-spect
scanners in security. These only applies to overt traitor or antagonist
items, and "stealth" items will not be seen as such.
add: Scanner gates can now be upgraded by using an N-spect scanner on it
to unlock "contraband scanning" mode.
add: Security officers can now be offered a bounty to turn in pieces of
contraband.
add: Some stealthy storage items like storage implants, smuggler's
satchels, void cloaks, the infiltrator modsuit, and the chameleon
backpack will block the presence of contraband on your person when
placed inside.
qol: N-spect scanner contextual screentips.
balance: Recharger security bounties ask for a quantity of 1, down from
3.
qol: security, cargo, and medbay have access to scanner gate boards.
/🆑

---------



* Adds six new strange object powers! (#84775)

DESIGN CONCEPT: Strange Devices are at their best when they're odd tools
which can help a department out, with some strange drawbacks that make
them interesting and unique. Foam for the Janitor, Flashbang for
Security, Teleporter for tiders, Corgimaker for the chef. They're also
ambiguous enough that they can really be used by anyone for silly
hijinks.

Drink Dispenser: Creates a glass, then fills it up with a random drink.

Bioscrambler: After a noticeable warning, bioscrambles people nearby.
33% chance to be used up on use.

Recharger: Shocks you, but recharges one random item to max battery.

Hugger: Hugs everyone in range as if you had the friendly trait.

DImensional: Converts the surroundings to a random material-theme. Each
use increases cooldown by two seconds.

Disguiser: Drops your clothing to the ground and replaces it with a
delete-on-drop costume and a randomly assigned cardboard ID.

Removed an unused and unusable shock flag.

Removed an unused dumb ghost item.

Added a proc that returns a hex color with the # attached.

> DESIGN CONCEPT: Strange Devices are at their best when they're odd
tools which can help a department out, with some strange drawbacks that
make them interesting and unique. Foam for the Janitor, Flashbang for
Security, Teleporter for tiders, Corgimaker for the chef. They're also
ambiguous enough that they can really be used by anyone for silly
hijinks.

Request by ArcaneMusic! He wanted new abilities to go along with the new
sprites, and approved these.

> Removed an unused dumb ghost item.

please stop using costume subtypes for OP items. whats the damn point of
the subtype if youre just going to screw with it

> Added a proc that returns a hex color with the # attached.

idk why it didnt have this tbh

🆑
add: Adds six new strange object powers! Drink dispenser, bioscrambler,
recharger, hugger, dimensional, disguiser.
code: Removed some unused code and items, and added a proc that returns
a random #colorstring.
/🆑

* [NO GBP] the random spawner loot weight config is not an integer (#84814)

Sets `integer` to false.
Also a tidbit about the `skew_loot_weight` proc, though loot lists with
uneven weights all tend to add a value to all entries so it isn't an
issue.

The config isn't an integer.

N/A

* The techweb no longer erroneously refers to MODsuits as exosuits (#84800)

At some point, some of the techweb node descriptions were changed, so
that it referred to certain modsuits as exosuits. This just changes it
back.

The term "exosuit" is generally used for mechs, not modsuits. The
techweb descriptions should refer to modsuits as modsuits.
🆑
spellcheck: The techweb no longer erroneously refers to MODsuits as
exosuits.
/🆑

* Adds new hairstyle - Short Bangs 2 (#84804)

Adds a new hairstyle called Short Bangs 2.
The hairstyle is basically an edit of the existing double buns, except
the hair buns themselves are removed.

https://github.com/tgstation/tgstation/assets/66234359/38fe3b09-c42b-43e6-9e30-949428aab506

More customization, variety and character flavor is great. Double buns
itself is a good hairstyle but some may not like the hair buns out of
personal preference or that it can look weird on non-human species like
felinids.

🆑 Hardly3D
add: Added new hairstyle: Short Bangs 2
/🆑

* Offset render relays for non-offsetting planes to match highest matching render plane (#84184)

**Alternate title: "Fix blind people getting so blind they become deaf
when going down a flight of stairs"**

So 'bout half a week to a week ago I overheard a friend complaining
about blind people not seeing runechat on lower multi-z levels. Asked a
bit, apparently they'd reported this about half a year ago, and it's
still an issue.
So in my never-ending hubris I decided to just go and fix it!
Now, admittedly? I really _really_ do not get the rendering system we
use.
The simple options were right out: we can't allow the fullscreens plane
to be offset, as this causes issues with looking up/down, or disallow
runechat from being offset, which causes issues with runechat from other
levels.

After poking our very cool and smart rendering guy several times over
the course of the last week, this is what we got to:

We simply make the rendering relays for non-offsetting plane masters
point to the highest rendering plane that matches the target.
We do this by offsetting the rendering relays in place, by adjusting
their plane and layer values to match the new offset, with a new
`offset_relays_in_place(new_offset)` proc called in
`/datum/plane_master_group/proc/transform_lower_turfs(...)`.
Importantly, we compare the current layer values to what they should've
been, so we don't accidentally override relays with custom-set layers.

This fixes our issue (as tested on wawastation):
<details>
  <summary>Images</summary>

![image](https://github.com/tgstation/tgstation/assets/42909981/c6a10e04-dd08-4642-bc4d-d99ae5004a40)

![image](https://github.com/tgstation/tgstation/assets/42909981/740dc894-7495-4c35-b729-ffcc539ca928)

![image](https://github.com/tgstation/tgstation/assets/42909981/986433a7-e66e-408a-8e77-1f1eb89cb67c)

</details>

Fixes #80376.
🆑
fix: You can see runechat above fullscreen overlays on lower multi-z
levels again. Rejoice, blind players. Please report any weird rendering
layering issues.
/🆑

* illegal tech flag got changed

* Automatic changelog for PR #84003 [ci skip]

* Automatic changelog for PR #84775 [ci skip]

* Automatic changelog for PR #84800 [ci skip]

* Automatic changelog for PR #84804 [ci skip]

* Automatic changelog for PR #84184 [ci skip]

* Makes the smoking pipe sprite not give you a phantom stache. (#84898)

The smoking pipe currently gives you a phantom stache. Observe, note the
black background and know this character has no facial hair.

![image](https://github.com/tgstation/tgstation/assets/70115628/2939afa9-e4e4-4ee2-b38b-fc517e207d01)
I basically adjusted the pixels so it'd look better from different
directions.
This is the new look - approximately.

![image](https://github.com/tgstation/tgstation/assets/70115628/55e23d8e-2367-468a-94c2-9c5741f34762)
Smoking pipe is cool for RP but the sprite's fucked.
🆑
image: the smoking pipe's directional looks have been altered to make it
less ugly
/🆑

(cherry picked from commit c499c51bb3)

* Automatic changelog for PR #84898 [ci skip]

(cherry picked from commit 1e80a72dee)

* Revert "Automatic changelog for PR #84898 [ci skip]"

This reverts commit 1ddc7d43de30bb7ef029d1ddd39f86ded94e110c.

* Revert "Makes the smoking pipe sprite not give you a phantom stache. (#84898)"

This reverts commit b66b9d634e5f28e40e800586d4642468049767e6.

---------

Co-authored-by: FlufflesTheDog <piecopresident@gmail.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: carlarctg <53100513+carlarctg@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
Co-authored-by: GPeckman <21979502+GPeckman@users.noreply.github.com>
Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: orange man <61334995+comfyorange@users.noreply.github.com>
Co-authored-by: NewyearnewmeUwu <70115628+NewyearnewmeUwu@users.noreply.github.com>
Co-authored-by: SomeRandomOwl <2568378+SomeRandomOwl@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
2024-07-20 14:23:18 +05:30

233 lines
9.4 KiB
Plaintext

/// Datum that represents one "group" of plane masters
/// So all the main window planes would be in one, all the spyglass planes in another
/// Etc
/datum/plane_master_group
/// Our key in the group list on /datum/hud
/// Should be unique for any group of plane masters in the world
var/key
/// Our parent hud
var/datum/hud/our_hud
/// List in the form "[plane]" = object, the plane masters we own
var/list/atom/movable/screen/plane_master/plane_masters = list()
/// The visual offset we are currently using
var/active_offset = 0
/// What, if any, submap we render onto
var/map = ""
/// Controls the screen_loc that owned plane masters will use when generating relays. Due to a Byond bug, relays using the CENTER positional loc
/// Will be improperly offset
var/relay_loc = "CENTER"
/datum/plane_master_group/New(key, map = "")
. = ..()
src.key = key
src.map = map
build_plane_masters(0, SSmapping.max_plane_offset)
/datum/plane_master_group/Destroy()
orphan_hud()
QDEL_LIST_ASSOC_VAL(plane_masters)
return ..()
/// Display a plane master group to some viewer, so show all our planes to it
/datum/plane_master_group/proc/attach_to(datum/hud/viewing_hud)
if(viewing_hud.master_groups[key])
stack_trace("Hey brother, our key [key] is already in use by a plane master group on the passed in hud, belonging to [viewing_hud.mymob]. Ya fucked up, why are there dupes")
return
#if MIN_COMPILER_VERSION > 516
#warn Fully change default relay_loc to "1,1", rather than changing it based on client version
#endif
if(viewing_hud.mymob?.client?.byond_version > 515)
relay_loc = "1,1"
rebuild_plane_masters()
our_hud = viewing_hud
our_hud.master_groups[key] = src
show_hud()
build_planes_offset(our_hud, active_offset)
/// Hide the plane master from its current hud, fully clear it out
/datum/plane_master_group/proc/orphan_hud()
if(our_hud)
our_hud.master_groups -= key
hide_hud()
our_hud = null
/// Well, refresh our group, mostly useful for plane specific updates
/datum/plane_master_group/proc/refresh_hud()
hide_hud()
show_hud()
/// Fully regenerate our group, resetting our planes to their compile time values
/datum/plane_master_group/proc/rebuild_hud()
hide_hud()
rebuild_plane_masters()
show_hud()
build_planes_offset(our_hud, active_offset)
/// Regenerate our plane masters, this is useful if we don't have a mob but still want to rebuild. Such in the case of changing the screen_loc of relays
/datum/plane_master_group/proc/rebuild_plane_masters()
QDEL_LIST_ASSOC_VAL(plane_masters)
build_plane_masters(0, SSmapping.max_plane_offset)
/datum/plane_master_group/proc/hide_hud()
for(var/thing in plane_masters)
var/atom/movable/screen/plane_master/plane = plane_masters[thing]
plane.hide_from(our_hud.mymob)
/datum/plane_master_group/proc/show_hud()
for(var/thing in plane_masters)
var/atom/movable/screen/plane_master/plane = plane_masters[thing]
show_plane(plane)
/// This is mostly a proc so it can be overriden by popups, since they have unique behavior they want to do
/datum/plane_master_group/proc/show_plane(atom/movable/screen/plane_master/plane)
plane.show_to(our_hud.mymob)
/// Nice wrapper for the "[]"ing
/datum/plane_master_group/proc/get_plane(plane)
return plane_masters["[plane]"]
/// Returns a list of all the plane master types we want to create
/datum/plane_master_group/proc/get_plane_types()
return subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/rendering_plate
/// Actually generate our plane masters, in some offset range (where offset is the z layers to render to, because each "layer" in a multiz stack gets its own plane master cube)
/datum/plane_master_group/proc/build_plane_masters(starting_offset, ending_offset)
for(var/atom/movable/screen/plane_master/mytype as anything in get_plane_types())
for(var/plane_offset in starting_offset to ending_offset)
if(plane_offset != 0 && (initial(mytype.offsetting_flags) & BLOCKS_PLANE_OFFSETTING))
continue
var/atom/movable/screen/plane_master/instance = new mytype(null, null, src, plane_offset)
plane_masters["[instance.plane]"] = instance
prep_plane_instance(instance)
/// Similarly, exists so subtypes can do unique behavior to planes on creation
/datum/plane_master_group/proc/prep_plane_instance(atom/movable/screen/plane_master/instance)
return
// It would be nice to setup parallaxing for stairs and things when doing this
// So they look nicer. if you can't it's all good, if you think you can sanely look at monster's work
// It's hard, and potentially expensive. be careful
/datum/plane_master_group/proc/build_planes_offset(datum/hud/source, new_offset, use_scale = TRUE)
// Check if this feature is disabled for the client, in which case don't use scale.
var/mob/our_mob = our_hud?.mymob
if(!our_mob?.client?.prefs?.read_preference(/datum/preference/toggle/multiz_parallax))
use_scale = FALSE
// No offset? piss off
if(!SSmapping.max_plane_offset)
return
active_offset = new_offset
// Each time we go "down" a visual z level, we'll reduce the scale by this amount
// Chosen because mothblocks liked it, didn't cause motion sickness while also giving a sense of height
var/scale_by = 0.965
if(!use_scale)
// This is a workaround for two things
// First of all, if a mob can see objects but not turfs, they will not be shown the holder objects we use for
// What I'd like to do is revert to images if this case throws, but image vis_contents is broken
// https://www.byond.com/forum/post/2821969
// If that's ever fixed, please just use that. thanks :)
scale_by = 1
var/list/offsets = list()
var/multiz_boundary = our_mob?.client?.prefs?.read_preference(/datum/preference/numeric/multiz_performance)
// We accept negatives so going down "zooms" away the drop above as it goes
for(var/offset in -SSmapping.max_plane_offset to SSmapping.max_plane_offset)
// Multiz boundaries disable transforms
if(multiz_boundary != MULTIZ_PERFORMANCE_DISABLE && (multiz_boundary < abs(offset)))
offsets += null
continue
// No transformations if we're landing ON you
if(offset == 0)
offsets += null
continue
var/scale = scale_by ** (offset)
var/matrix/multiz_shrink = matrix()
multiz_shrink.Scale(scale)
offsets += multiz_shrink
// So we can talk in 1 -> max_offset * 2 + 1, rather then -max_offset -> max_offset
var/offset_offset = SSmapping.max_plane_offset + 1
for(var/plane_key in plane_masters)
var/atom/movable/screen/plane_master/plane = plane_masters[plane_key]
if(plane.offsetting_flags & BLOCKS_PLANE_OFFSETTING)
if(plane.offsetting_flags & OFFSET_RELAYS_MATCH_HIGHEST)
// Don't offset the plane, do offset where the relays point
// Required for making things like the blind fullscreen not render over runechat
plane.offset_relays_in_place(new_offset)
continue
var/visual_offset = plane.offset - new_offset
// Basically uh, if we're showing something down X amount of levels, or up any amount of levels
if(multiz_boundary != MULTIZ_PERFORMANCE_DISABLE && (visual_offset > multiz_boundary || visual_offset < 0))
plane.outside_bounds(our_mob)
else if(plane.is_outside_bounds)
plane.inside_bounds(our_mob)
if(!plane.multiz_scaled)
continue
if(plane.force_hidden || plane.is_outside_bounds || visual_offset < 0)
// We don't animate here because it should be invisble, but we do mark because it'll look nice
plane.transform = offsets[visual_offset + offset_offset]
continue
animate(plane, transform = offsets[visual_offset + offset_offset], 0.05 SECONDS, easing = LINEAR_EASING)
/// Holds plane masters for popups, like camera windows
/// Note: We do not scale this plane, even though we could
/// This is because it's annoying to get turfs to position inside it correctly
/// If you wanna try someday feel free, but I can't manage it
/datum/plane_master_group/popup
/// This is janky as hell but since something changed with CENTER positioning after build 1614 we have to switch to the bandaid LEFT,TOP positioning
/// using LEFT,TOP *at* or *before* 1614 will result in another broken offset for cameras
#define MAX_CLIENT_BUILD_WITH_WORKING_SECONDARY_MAPS 1614
/datum/plane_master_group/popup/attach_to(datum/hud/viewing_hud)
// If we're about to display this group to a mob who's client is more recent than the last known version with working CENTER, then we need to remake the relays
// with the correct screen_loc using the relay override
if(viewing_hud.mymob?.client?.byond_build > MAX_CLIENT_BUILD_WITH_WORKING_SECONDARY_MAPS)
relay_loc = "LEFT,TOP"
rebuild_plane_masters()
return ..()
#undef MAX_CLIENT_BUILD_WITH_WORKING_SECONDARY_MAPS
/datum/plane_master_group/popup/build_planes_offset(datum/hud/source, new_offset, use_scale = TRUE)
return ..(source, new_offset, FALSE)
/// Holds the main plane master
/datum/plane_master_group/main
/datum/plane_master_group/main/build_planes_offset(datum/hud/source, new_offset, use_scale = TRUE)
if(use_scale)
return ..(source, new_offset, source.should_use_scale())
return ..()
/// Hudless group. Exists for testing
/datum/plane_master_group/hudless
var/mob/our_mob
/datum/plane_master_group/hudless/Destroy()
. = ..()
our_mob = null
/datum/plane_master_group/hudless/hide_hud()
for(var/thing in plane_masters)
var/atom/movable/screen/plane_master/plane = plane_masters[thing]
plane.hide_from(our_mob)
/// This is mostly a proc so it can be overriden by popups, since they have unique behavior they want to do
/datum/plane_master_group/hudless/show_plane(atom/movable/screen/plane_master/plane)
plane.show_to(our_mob)