* Fixes assistants going to medium priority when other job is selected (#65645)
* Fixes assistants going to medium priority when other job is selected
Co-authored-by: Tastyfish <crazychris32@gmail.com>
* Changes the default ghost lighting, makes it a preference (#65352)
* Changes the default ghost lighting, makes it a preference
I think the way ghost lighting looks right now is really crummy.
It's dark enough you can see where the shadows should be, but it's just
bright enough for everything to look like dog poo
A lot of what makes the game look nice is the depth of the lighting
and if we just hide that for observers we're shooting ourselves in the
foot.
I'm also making it a game preference, so if someone wants to have bad
opinions they can easily.
* Changes the default ghost lighting, makes it a preference
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
* Restores the Persistent Scars preference (#65358)
* Restores the Persistant Scars preference
I also had to remove some raw READ_FILE()s because that was now useless. I was thus able to remove the persistent_scars variable from the prefs, as it is now a standalone preference.
* I forgor...
* Restores the Persistent Scars preference
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
* Fit Viewport cleanup (#65225)
* Fit Viewport cleanup
Changes how Fit Viewport works slightly.
From what I understand, the verb was created with the goal of
eliminating the pixel hunting required to get rid of letterboxing.
This works fine for stretch to fit, but ever since the command bar got
nuked it's ended up creating a lot of blackspace for targeted zoom
modes.
I've changed how it decides on its optimal width slightly, if the client
has a non stretch to fit zoom mode, we use it, the world icon size and
the clients view size to figure out the exact width we want.
The bars on the left and right have been bugging me forever. Want them
gone.
In light of this, I'm also making changing your zoom amount attempt to
fit the viewport, if you have the pref enabled.
Oh and I'm trying something with auto fit viewport stuff.
It currently waits a second between view change and fitting. The comment
implies this is to avoid winget strangeness from Login calls. When I
blamed it, I found a commit from antruk talking about client dropping,
and this being a potential fix.
Unfortunately none wrote down what dropping means, and anturk's
forgotten.
I'm making the assumption that it's related to attempting the related
winsets before an inital login is over.
I might be wrong about this, if I am we'll know what went wrong I
suppose.
* Whoops, this needs to be invoke async
* Ensures client safety, autodocs code, adds proper cleanup
* Fit Viewport cleanup
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
* Makes deadchat control inputs bypass automute. (#65195)
* Makes deadchat control inputs bypass automute.
It's slightly annoying when you get muted because you spent a minute trying to get the supermatter to move down.
* Makes deadchat control inputs bypass automute.
Co-authored-by: TemporalOroboros <TemporalOroboros@gmail.com>
* Make the repeated messages spam filter give a clearer warning (#65029)
Co-authored-by: Jeremiah <42397676+jlsnow301@ users.noreply.github.com>
* Make the repeated messages spam filter give a clearer warning
Co-authored-by: Kyle Spier-Swenson <kyleshome@gmail.com>
Co-authored-by: Jeremiah <42397676+jlsnow301@ users.noreply.github.com>
* Contextual screentips -- Screentips now show you what items/objects can do (#64502)
Adds the foundational system for contextual screentips, which will show you what you can do with objects/items, including through context, such as what you are holding.
Provides several helper elements for most use cases, and applies it to a handful of common objects in order to show the full breadth of the system.
Changes screentips preference from on/off to on/off/only with context. Players who originally had it on off will have it migrated to only with context, though can re-disable it.
* Contextual screentips -- Screentips now show you what items/objects can do
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
* Put a comment explaining the client parent_type line (#64629)
I also took the opportunity to sketch out the description of the client
object itself
* I cast identify at 9th level
Co-authored-by: oranges <email@oranges.net.nz>
* Ensures that COMSIG_PARENT_QDELETING is sent before client Destroy. (#64536)
I want to let logic rely on this, so I'ma just ensure it can
* Ensures that COMSIG_PARENT_QDELETING is sent before client Destroy.
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
* makes most statpanel tabs update a tenth or so as often (>= 4 seconds instead of 4 deciseconds) because theyre wastful of cpu (#63991)
makes most updating stat panel tabs update once every 4 seconds instead of 4 deciseconds, but switching tabs instantly updates statpanel data for you. also makes examining a turf make flat icons for a maximum of 10 contents instead of 30 because its ridiculous to call getFuckingFlatIcon() wrappers that many times. also makes SSfluids not have SS_TICKER and updates its wait accordingly because theres no reason for it to be a ticker subsystem
the mc tab updates every 2 seconds unless someone has the pref enabled to refresh it quickly because SOME UNILLUMINATED LEMONS absolutely must watch overtime spikes in real time
statpanels can take between 1-3% of masters total processing time at very high pop, which is silly considering theres no need for someone to know any of the data updated accurate to less than half of a second. The only reason it needed to update so fast was because it looked awful when switching tabs, which will only be updated on the next fire. now switching tabs updates data instantly so theres no need to update the rest of the data quickly.
also makes each stat tab update into its own proc so we can tell how much each tab update costs
* makes most statpanel tabs update a tenth or so as often (>= 4 seconds instead of 4 deciseconds) because theyre wastful of cpu
* E
* https://github.com/Skyrat-SS13/Skyrat-tg/pull/11003
Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
* Adds a movement looping system, replaces inbuild procs and spacedrift with it (#62567)
* Adds a subsystem to handle automated directional movement, replaces all instances of walk_towards with it. Makes meteors and immovable rods not drift in space, and makes immovable rods more destructive. Note, I've opted not to use byond's method of moving towards something, which is effectively Move(src, get_step(src, get_dir(src, target))) as it's cringe and doesn't make a smooth line. I've replaced it with a autoupdating rise over run setup, read the code for more details
* woop forgot the subsystem
* Documentation, contributing.md entry, and some cleanup
* Makes the moveloop datum more oop friendly, sets us up for a lot of conversions
* Converts the curseblob and walk_away() to the subsystem
* Changes the default for override from FALSE to TRUE
* converts walk() over, still need to add a replacement proc for it, but we didn't actually have anything that used the raw proc
* converts the rest of walk_to() over, nearing the end now
* cleans up some errors
* Fully documents everything, fills in some missing movement types, uses the power of oop to make things cleaner, and typepaths longer
* Finishes the contributing.md stuff
* Done
* Fefaults -> Defaults, can you tell I wrote this at 1AM?
* resolves bubblegum issues
* Roh's suggestions
Co-authored-by: Rohesie <rohesie@ gmail.com>
* Cleanup
* Hey lemon, did you know that Destroy() lives on datums? ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
* Converts over the discrepencies created in my absense
* HAHA FUCK YOU I PAY MY DUES
* Whoops lost some stuff in the merge
* Converts the system from seconds to deciseconds to make dealing with the api more sane
* Some stuff I missed
* Makes movement an inheritable subsystem type, splits the moveloop file into two, one for the subsystem, and one for the datums
* Makes a subsystem that handles directing movers out to other subsystems. It's a bit bad right now, but it's a
good first step. I think I'll move the move loop datum to a lazy var on mobs instead of an assoc list, don't
like lists.
Also makes the movement procs global, I'll move em to the /movement subsystem at some point or something like
that
* Converts the existing uses of the procs over to the new format
* Adds support for subsystem precedence, so a type of A can override type B.
General cleanup, still kinda in debug mode but it's getting better
* I'll admit I'm not too familiar with this, but I think it will work
* Adds starting logic so movement types "pausing" makes any sense
Redoes how waiting is handled to make it based on world.time directly. I don't remember why. I think it's better
this way.
Adds a drifting movement type, moves space drift over to it.
Needs severe work before it's ready, too much info stored and modified on the moving object, see comment
Starts work on making drifting smooth
* Moves almost all space drifting vars over to signals on the movement datum
Properly implements glide size stuff for both the subsystem and the loops. Space drift will be smoother now.
It's not perfect, but it'll work just fine for now
Adds a way to override a client'd mob's glide size mid move, uses it to make entering a spacedrift look right
Adds a way to delay a client move outside of just move_delay, meant to be used for long periods, and setup such
that it doesn't make inputs persist
Adds flags to movement loops, alongside MOVELOOP_OVERRIDE_CLIENT_CONTROL, which blocks client movements while
the loop is firing, and for it's visual delay after
This means you can't exit a space drift until you hit the actual wall. This feels a lot better
Some general logic stuff, move() will return true/false if it succeeded or failed
Adds a stop_loop() proc that's called when a move loop is no longer active
Suck my nuts
* Moves precedence to the loop instead of the subsystem
* Moves drifting into a component, this lets me explictly block input after the move loop ends, so people can't
move the moment they functionally move onto a new tile
This is a bit underdeveloped currently, but that's a problem for another day
Cleans up some uses of move procs, fixes runtimes in metoer and curseblob code
Adds signals for stopping/starting a move loop, sending one for destroy is redundant.
Moves existing event signals from the movable being acted on to the loop itself, makes more sense this way
Makes the move handler return the created loop up the chain so we can register to it
Fixes a logic error in loop contesting code that lead to loops never actually being removed from subsystems
because they didn't know they should be.
Properly changes lifetime from a time to stop, to functionally an amount of moves to complete before stopping
Adds some new signals for pre/post loop process. This is to better tie into components.
I decided I didn't like the idea of tying all functionality to the loops themselves
The loop decides functionally how to move, components or just tied in signals can decide when/when not to move
and can modify properties of the loop
Making a new loop for things like atmos drift, something I'm interested in tackling in the future, seemed silly
* Moves movement procs directly to the subsystem for better namespacing or whatever
* Moves movement packets onto /atom/movable, no longer need the debugging
I've decided to not just put their contents fully onto atom movable, since it makes debugging on live much
harder, can't sdql for them anymore.
Fixes a runtime in meteor code, properly this time
Fixes a logic error in stop_looping
Makes move manager NO_INIT, because well, it doesn't init
* Commits human sin, makes Recover() work properly for movement subsystems
* Fixes immovable rod orbits not always working, they were returning too early in moved and fucking up the var we use to track move count, and thus not sending a signal properly
* Reworks the curseblob to use signals more, and to not use override
* Missed this in the movement ss commit
* Removes override, makes having a higher or equal precedence take its place
* Updates documentation
* Cleans up some unused defines
* Nukes the unused flags option
* Whoops forgot to qdel check
* Removes an unused var I had for client move prevention before I started using a component
* Let's do this properly
* Modernizes meteor code to better match how explosions actually work currently
* Some more cleanup
* Cleans up effect code a little bit
Nukes the effect system's sleep loop, we use movement loops instead
As a part of that, instead of 1 timer per effect spawned, we react to loop failure and make it 1 timer per
effect system
This should reduce the amoumt of slowdown we see after mass lighting break
It's not everything, we're still making a timer per spark effect, but it cuts things down significantly
* Updates explosions to not sleep
* Adds support for modifying a loops delay post process, makes extinguisher code suck less then it does currently, nukes some more sleeps and timer loops
* Converts water tank resin over to move loops rather then sleeps, minor behavior change mind, the cooldown starts on fire rather then on land, but I think that makes more sense anyway
* compile and runtime fix
* Fixes some runtimes, cleans up some code, ensures feature parity when it comes to logging
* Prevents resin foam from space drifting
* Adds support for flags back into the system, I need it for reasons
* Updates move_towards to fix some bugs and resolve some inconsistent behavior, implements a flag that makes a loop's first move start instantly
* Fixes extinguishers not actually transfering any reagents
* Converts sprays to the new system. This does actually minorly change behavior, in that I've changed the order of spray actions from step -> sleep -> wash to step -> wash -> sleep, but I'm not terribly torn up about it because frankly I think it feels better
* Converts grav catapults over to the new system
* Converts trays over to moveloops
* Converts robot streaking to move loops, the other two coming soon
* Compile you won't. Also fixes a behavior issue with oil streaks
* Does directional step_to properly, cleans up the other two streaking types
* Converts step_trigger over, not that it's actually used anywhere. Changes how stoping a move works, you need to explicitly qdel, other the step is just considered to be ignored. This will make life easier later
* Adds a jps movement loop. It's a bit bloaty, id is stupid, but it'll work just fine
* Makes the system support passing in a datum that's just used as extra context for the move. The hope is this makes signalizing things less of an absolute headache
* Begins the conversion of ai movement datums to movement loops
* These two are reasonably simple, only weird thing I'm doing is A: Not allowing target hotswapping, which I hope none is doing, and B: passing the controller into the move loop as extra context so things work properly
* JPS is a bit more complex, partially because the old implementation was a bit weird. 2 major things. 1: I'm dropping what I think was a redundant behavior minimum distance check from the premove bit of logic, since I'm pretty sure it didn't do anything. 2, instead of just stoping the step in an error state like being pulled, we count it against our max move total
* Audit
* Moves most forced movement to the framework, adds some components to make things nicer
* Implements a flag that makes the loop always operate, regardless of precedence and without impacting any other loops
* Moves movement subsystems into the right folder
* Hey potato what if you had two procs that did the same thing and one called the other? Wow it's useless
* Merges slipping and force movement
* Converys conveyors over to the system. It's a bit fragile, but I think it's totally worth it to save the sleep loop
* Precedence -> Priority, cleans up some logic errors, makes priority highest to lowest instead of lowest to highest, straight cleans some code up
* Makes poly and bubbles ignore spacedrift, now that precedence actually functions properly. I'm likely missing cases of this, will deal with it later
* Depression, thy name is linter
* Fixes linter, and hopefully fixes the runtimes in ci too
* Wew
* Sets sprays and extinguishers back to legacy, since people do actually seem to have noticed
* Spelling errors my beloved
Co-authored-by: Kylerace <kylerlumpkin1@ gmail.com>
* More detail, moves return descriptions
* Converts transit tubes to the system?
* Adds the glide size modifier. Not honestly sure that this should be default, considering how crummy it makes things look for normal walking, but it's useful as hell here
* Adds a force move in dir template, actual support for fast initial steps (wtf old me) and a helper proc for setting delay
* Cleans up displosal code a bit, I thought about adding it to the system but it would functionally be just 'disposal loops'. Maybe I'll make a template subtype? not sure how I want to handle stuff like this
* Cleans up mob movement a bit
* Let's use the controller's visual delay
* Makes the resin thrower nicer, cries
* Cleans up some comments, replaces an implicit world.icon_size with an explicit one, fixes up a typecheck
* typecache instead of double istype. Can't do much about the !atom/movable, list would be too big I feel
* hhh
* bro wtf
* Documents the why of SS_TICKER
* Puts SSmovement on SS_TICKER. Lets us support tick steps
* Cleans up the charge action. Makes it use moveloops
* Fixes CI? kinda worried that this just got dropped
* Converts disposal pipes to move loops. They stutter a bit more then usual as of now, hoping that's a me thing, if it's not I'ma look at uping the priority of the base subsystem
* Moves the move subsystems off background, puts some on ssticker
* Prevents some things that shouldn't move in space from moving in space
* Documents the general form and usage of the system
* Virgin one vs chad once
Co-authored-by: Kylerace <kylerlumpkin1@ gmail.com>
* Removes unneeded check
* Moves appropriate movement subsystems into SS_BACKGROUND. Removes redundant SS_KEEP_TIMINGs
I do want the behavior of SS_TICKER, which at this point is tick based waits, and ignoring overtime when
calculating next fire.
Since honestly, these subsystems should ignore overtime in regards to next fire, the cost of moving A may be
nothing compared to the cost of moving B.
* Makes the MODULUS macro use floor. I knew our coders would never let me down, glad this exists, thanks ninja
Fixes teleporting caused by shitty round() behavior, adds a "you hit your target" case to homing loops
* Converts blood splatters to move loops, that'll do it
Co-authored-by: Rohesie <rohesie@ gmail.com>
Co-authored-by: Kylerace <kylerlumpkin1@ gmail.com>
* Adds a movement looping system, replaces inbuild procs and spacedrift with it
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: Rohesie <rohesie@ gmail.com>
Co-authored-by: Kylerace <kylerlumpkin1@ gmail.com>
* Fixes the mess between ROLE_REV and ROLE_REV_HEAD (#64068)
* Fixes the mess between ROLE_REV and ROLE_REV_HEAD
* Update code/modules/client/preferences/migrations/tgui_prefs_migration.dm
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
* Update revolution.dm
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
* Fixes the mess between ROLE_REV and ROLE_REV_HEAD
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
* Amortize the cost of creating preference assets by caching them per git revision on production, reducing best case init times by ~20 seconds (#63503)
Preference asset creation, which while consistently created in early assets, can be requested at any time before then and often is, currently takes about 15 to 25 seconds to produce. Because of extremely hard to reproduce BYOND icon bugs, most of this is done on the same tick.
Lowering the cost of initialization itself is very tricky. Some of it we can theoretically optimize, such as creating humans for antagonists, others we can't, such as the raw cost of icon blending.
Furthermore, adding new icons later down the line would just increase this initialization time even more.
Instead of optimizing the asset creation, which is an uphill battle, this instead chooses to amortize the cost by caching preference assets created per git revision. This means that preference assets will be created, with their long delay, only once whenever the code changes.
This is done on a config, defaulting to on so that production needs no changes, as the whole point of these being made at runtime at all is that it keeps assets/art styles consistent, and PRs making subtle bugs that break preference generation in some way is not uncommon. On development, your git revision will stay the same until you commit, no matter what code changes you make.
* Amortize the cost of creating preference assets by caching them per git revision on production, reducing best case init times by ~20 seconds
* Fixing another conflict :)
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
Co-authored-by: GoldenAlpharex <jerego1234@hotmail.com>
* Move MouseEntered to a queue, such that only the most recently hovered atom will be processed (#63567)
bout The Pull Request
MouseEntered currently fires multiple (multiple) times per frame, presumably over every atom that was hovered in some timeframe (though it appears to be much worse than that).
This makes MouseEntered only add to a queue, while a per-tick subsystem ensures only the most recent MouseEntered gets the screentip work done on it, through a generic on_mouse_enter proc call.
Contextual screen tips are coming and are going to make the screen tip code more computationally expensive, so slimming it down is going to be a must.
Would like to hear from @ LemonInTheDark if this makes any obvious difference in time dilation, since it of course won't be as easy as just checking MouseEntered overtime anymore.
* Move MouseEntered to a queue, such that only the most recently hovered atom will be processed
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
* creates SSspeech_controller so the MC can control say() execution
* Update mob_say.dm
Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
Co-authored-by: Gandalf <jzo123@hotmail.com>
* [Ready] MODsuits
* we dont need to add these people as codeowners, goodness gracious
* have to remove this because upstream
* part 1 of these fixes
* EEEE
* Update peacekeeper_clothing.dm
* E
* E
* Auto stash before merge of "upstream-merge-59109" and "origin/upstream-merge-59109"
* E
* Update expeditionary_trooper.dm
* more removal
* nice
* modsuti modstui modusuti
* fixes
* E
* ITS MODsuit not HARDSUIT
* more hardsuit references
* MODSUIT NOT HARSUITEDSA
* Maps
* More ,map
* oop
* e
* oo aa
* 0
* ting tang
* Update modsuit_tailsprites.dm
* hi fikou
* bs tech update
Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com>
Co-authored-by: jjpark-kb <55967837+jjpark-kb@users.noreply.github.com>
Co-authored-by: Gandalf <jzo123@hotmail.com>
Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com>
* Fix skin tone sorting and refactor color procs (#63554)
* Remove superfluous hash from hex2rgb call
Add stack_trace to hex2rgb to catch future nonsense
* Fix skin tone sorting and refactor color procs
Co-authored-by: AndrewL97 <andrewjlove97@gmail.com>
* Field of View and Blindness improvements [bounty + upstream push]
* Update death.dm
* almost done
* Update fov_handler.dm
* Face mouse when in combat mode, fix
* Fixes the category for the fov admin verb. #63401
* Fixes objects with bad planes and FoV bugs #63412
* pain
* there we go
* face pref
Co-authored-by: Azarak <azarak10@gmail.com>
* Moves the suicided var to where its supposed to be (#63470)
Co-authored-by: Fikou <23585223+Fikou@ users.noreply.github.com>
* Moves the suicided var to where its supposed to be
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Fikou <23585223+Fikou@ users.noreply.github.com>
* fugitives now poll for a fugitive role, instead of being based on traitors (#63339)
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
* fugitives now poll for a fugitive role, instead of being based on traitors
Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
* TGUI input box framework (#63190)
About The Pull Request
Creates the framework for two new TGUI input boxes that can be toggled via game prefs.
This does not convert any actual inputs to TGUI
This does not convert any tgui_list_inputs into being toggleable
Example pictures
Input on a hand labeler. This has a MAX_LENGTH set, so it can be invalidated. Cancel always returns null. Enter button submits, if valid.
text input
(OUTDATED) Multiline input on newscaster. Newer version fills the window with a section, like the others
multiline
Sheets from a stack
number input
Why It's Good For The Game
1
So I did...
Much sleeker input boxes
Result should be a in place swap for most occurrences of input
Renders casting as text/num/null obsolete but still doable
Input validation from both sides handled
Prefs toggle if you don't like the look
Changelog
cl
add: TGUI input boxes are on the way! You can find new preferences in the menu. They will be on by default.
/cl
* TGUI input box framework
Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
* Revert "[MIRROR] Ethereals no longer get the "he" pronoun accidentally [MDB IGNORE] (#9880)"
This reverts commit f42200feef.
* Properly reverts it, the Skyrat way
* Ethereals no longer get the "he" pronoun accidentally (#63221)
Character preferences now disregards the gender value if the species you're playing as is sexless
fixes#61491 (Ethereals being "He" instead of "They")
* Ethereals no longer get the "he" pronoun accidentally
Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
* makes the gradient color options not show if no gradient is selected (#63169)
* makes the gradient color options not show if no gradient is selected
Co-authored-by: Seris02 <49109742+Seris02@users.noreply.github.com>
* de-hardcodes moth antennae preference icons (#62888)
It just makes the preferences actually appear for downstreams who have unique moth preferences.
* de-hardcodes moth antennae preference icons
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
* Replaces Batform with Vampire houses (#62516)
Permissions for species change
image
About The Pull Request
Goodbye batform
Hello, new preference called vampire status. Outcast vampires act just like normal, Inoculated vampires join their department under a unified "vampire house name" everyone shares.
image
image
image
Why It's Good For The Game
I've heard people complain about batform for years now, if vampires aren't gone by next halloween we can at least enjoy making them far less griefy (ruining a lot of the fun of halloween as just a dumb grief holiday) and more roleplay oriented. I don't even know why vampires got a griefy spell when they already have their main mechanic encourage randomly attacking people and stealing their blood to stay alive
Changelog
cl
del: Batform is gone!
add: ...Replaced by vampire houses as a preference. Join your department as a vampire ménage!
/cl
* Replaces Batform with Vampire houses
Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
* Hair gradient preference no longer shows for species that don't have hair (#62950)
* Hair gradient preference no longer shows for species that don't have hair
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
* Allows players to send more visible adminhelps when no admins are on, which'll definitely alert admins
* db portion sorted out
* now it really is
* should work about fine
* one last touch
* well, one more
* also botched comment
Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
Co-authored-by: Useroth <37159550+Useroth@users.noreply.github.com>