Compare commits

...

503 Commits

Author SHA1 Message Date
Ed
b63f054245 Revert "roles and departments"
This reverts commit eeecbbfd57.
2024-07-18 13:59:07 +03:00
Ed
eeecbbfd57 roles and departments 2024-07-18 13:58:17 +03:00
Ed
2eaa917afd Create cp14-ignoredPrototypes.yml 2024-07-18 13:52:19 +03:00
Ed
eba7d2de0d Merge pull request #331 from crystallpunk-14/ed-17-07-2024-upstream
Ed 17 07 2024 upstream
2024-07-17 23:46:05 +03:00
Ed
fb7ca28b9a update locales 2024-07-17 23:35:22 +03:00
Ed
02275a0237 Merge remote-tracking branch 'upstream/master' into ed-17-07-2024-upstream 2024-07-17 23:25:31 +03:00
slarticodefast
6f5077803b Fix formatting warnings (#30122) 2024-07-17 10:25:19 -08:00
PJBot
be9acaea35 Automatic changelog update 2024-07-17 13:51:32 +00:00
Winkarst
ba2c5fcded Make the super door remote to be able to control Syndicate doors (#30033)
* Make the super door remote to be able to control Syndicate doors

* Fix
2024-07-17 09:50:24 -04:00
Flareguy
b20fd4fbd0 Vox displacement updates (#29824)
* more vox displacement maps

* A

* remove vox insuls sprites

* sci magboots

* Update vox.yml

* Update meta.json

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2024-07-17 10:43:11 +03:00
PJBot
0e02c50548 Automatic changelog update 2024-07-17 06:27:16 +00:00
lzk
6443c53a8c Little saw debuff (#29995) 2024-07-17 09:26:10 +03:00
PJBot
1ac7739564 Automatic changelog update 2024-07-17 06:20:20 +00:00
lzk
1fd8369a9c Add examine for caustic and cold damage (#29989)
* Examinable cold damage

* lightblue

* update grammar

* caustic
2024-07-17 09:19:13 +03:00
Ed
d8ab4982ad Character menu issuer localization (#29840)
* Update CharacterUIController.cs

* TODO Burn this shit

* huh?

* huh!

---------

Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
2024-07-17 08:47:50 +03:00
PJBot
11320f4d2c Automatic changelog update 2024-07-17 04:36:25 +00:00
Nemanja
13bec7a0e9 Sign Resprite (#29806)
* Redone signage

* Signs

* ok this thing now

* alright ig?

* big data

* cryo sign

* new sign
2024-07-17 14:35:18 +10:00
PJBot
8d99961a00 Automatic changelog update 2024-07-16 23:27:09 +00:00
K-Dynamic
8db252e7dc Nerf & standardised slip times (#27879)
* standardised slip times

* puddle and gib soap

* banana peels

* cleaned yaml by shifting to component

* error slip

* error slip intersect

* intersect ratio return

* error and omega soap changes

* SlipocalypseClusterSoap 2 tc cost
2024-07-17 09:26:02 +10:00
PJBot
21d48ca5c4 Automatic changelog update 2024-07-16 22:51:25 +00:00
Jezithyr
93e4bfcfb3 Remove Geras from Slimes to address combat balance (#29731)
Removed Geras

Removed Geras
2024-07-16 15:50:17 -07:00
Plykiya
db3f304f4b Replace EntityPrototype.NoSpawn with EntityPrototype.HideSpawnMenu (#30082)
NoSpawn

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-17 00:29:31 +10:00
Nemanja
2e3d2db97e Revert "Change wristwatch meta description" (#30070)
Revert "Change wristwatch meta description (#30036)"

This reverts commit 919b3ac9e6.
2024-07-17 00:27:37 +10:00
Cojoke
927cf7799f Remove uses of AllObjectives (#30077)
Remove the uses of AllObjectives
2024-07-16 10:17:18 +03:00
Simon
911a94dba9 Add missing command description to replay_toggleui (#30071) 2024-07-16 11:04:31 +10:00
Ed
8cbd26ae2f Farming WIP (#269)
* setup planting doafter

* spawn plants after use seed

* some work

* move comps to separate folder

* public check daylight

* daylight plant energy regeneration

* some fixes

* bruh, im thinking

* added ingame soil

* added hoe

* attaching plants

* hoe system

* block plant dublicating

* some planting refactor

* shovel as pant + soil remover

* plant growing visualizer

* soil resprite

* split farming system to second partial class

* update throught event refactor

* tring sync update plant with update visuals

* finish visual sync

* plants growing

* more partial splitting, naming work, clean up

* Update FARMINGTEST.yml

* Update FARMINGTEST.yml

* fix typo

* prototype value validating

* Оно бухает воду!

* solution visualizer in soil

* forgot some fix

* part of Tornado review fix

* destroy RemovePlantComponent

* more fixes

* simple harvesting

* refactor plant component values changing

* harvest redo

* gather on destroyByTool

* sickle resprite

* plant fading

* fading per minute!

* wheat sprites

* YML restruct

* fixes

* auto root plants

* add comments

* move sprites

* split structures from object textures

* wheat farming!

* Update CP14FarmingSystem.Interactions.cs

* seedbed (#297)

seedbed :^)

* a

* Update soil.yml

---------

Co-authored-by: Jaraten <116667537+Jaraten@users.noreply.github.com>
2024-07-15 23:58:03 +03:00
Ed
2de26baebd Ambient loops (#323)
* ambient loop systems

* audio content

* Update ContentAudioSystem.CP14AmbientLoop.cs

* Update attributions.yml

* limit frequency

* Update CP14AmbientLoopPrototype.cs

* Create IsDaylight.cs

* fix problem
2024-07-15 23:18:14 +03:00
Ed
c69fff0bb9 Merge pull request #328 from crystallpunk-14/ed-15-07-2024-upstream
Ed 15 07 2024 upstream
2024-07-15 22:21:51 +03:00
PJBot
09a05955d7 Automatic changelog update 2024-07-15 19:19:40 +00:00
Winkarst
33a303236c Make addgamerule command process only valid game rules (#29912)
* addgamerule command processes only valid rules

* Update

* English moment
2024-07-15 21:18:33 +02:00
Simon
b35539db4a Fix some markup related obsolete warnings in research and anomaly related systems (#30072)
Fix some Markup related obsolete warnings in Research and Anomaly related systems
2024-07-15 22:14:37 +03:00
Ed
dbc8c1b4d7 disable test 2024-07-15 22:10:53 +03:00
Pieter-Jan Briers
c0593fb328 Fix invalid UI hover/click sounds breaking client (#30067)
fixes #29561
2024-07-15 16:55:05 +02:00
Pieter-Jan Briers
eb3b2ae01a Update host key for changelog RSS (#30068) 2024-07-15 16:32:12 +02:00
Ed
028c1ee478 Merge remote-tracking branch 'upstream/master' into ed-15-07-2024-upstream 2024-07-15 12:58:23 +03:00
Pieter-Jan Briers
b7d3964c56 Fix AccessLevelControl breaking (#30045)
#29987 did an oopsie

This broke the ID computer, station records, and maybe some others too.
2024-07-15 00:07:48 +02:00
PJBot
17c23f11c5 Automatic changelog update 2024-07-14 15:13:31 +00:00
lzk
3b85b1e43e make scarves eatable again (#29959) 2024-07-15 01:12:25 +10:00
deltanedas
35cd013e88 make ninja shoes magboots (#28586)
Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-07-15 01:11:40 +10:00
PJBot
f6d827f5d9 Automatic changelog update 2024-07-14 14:10:48 +00:00
CookieMasterT
b6115b672a Add petting cyborgs (#30037)
added petting borgs, adjusted interactions
2024-07-15 00:09:41 +10:00
themias
a0052c5b09 Prevent virtual item storage and popups (#30020)
* Prevent virtual item storage and popups

* fix typo

* add comment
2024-07-15 00:08:39 +10:00
Ed
1c74ffb8e4 Ambient music rules refactor (#29921)
* refactor

* dutypo
2024-07-14 23:58:48 +10:00
osjarw
7d9653fff7 Fix HTN/NPC better plan selection (#30017)
* recording commit

* Remove debugging/recording content
2024-07-14 20:28:46 +10:00
PJBot
f90538cca7 Automatic changelog update 2024-07-14 10:28:02 +00:00
Winkarst
07535e8ecf Clumsy proof grappling gun (#29904)
Make grappling gun clumsy proof
2024-07-14 20:26:56 +10:00
SlamBamActionman
4f479b6c85 Fix RGB toys color when worn/in-hand (#30023)
rgbeeeeeeee
2024-07-14 20:26:34 +10:00
lzk
919b3ac9e6 Change wristwatch meta description (#30036) 2024-07-14 20:25:57 +10:00
lzk
011250f35e Fix AGhostCommand naming (#29945) 2024-07-14 20:25:18 +10:00
Winkarst
960cc806cc Update AccessLevelControl.xaml.cs to use ISawmill (#29987)
* Update AccessLevelControl.xaml.cs to use ISawmill

* Update

* Silly me

* Update
2024-07-14 20:24:26 +10:00
ShadowCommander
bdf7293cfb Clean itemmapper (#29983)
* File scoped namespace

* Format file

* Fix param name in doc comment

* Reflow doc comment

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-07-14 13:27:39 +10:00
osjarw
922be64290 NPC exits MeleeOperator on invalid EntityUid (#30005)
EntityUid 0 problem fix
2024-07-14 13:26:38 +10:00
Winkarst
5d1702d280 Update MainMenu.cs to use ISawmill (#29988)
* Update MainMenu.cs to use ISawmill

* Update

* Error
2024-07-14 13:05:39 +10:00
PJBot
68982953f3 Automatic changelog update 2024-07-14 03:00:52 +00:00
Luiz Costa
87467a358b Fix lizards losing snouts when equipping a head bandana (#29979)
* say goodbye to no-snout lizards

* remove snout from plague doctor hat HideLayerClothing component
2024-07-14 12:59:45 +10:00
github-actions[bot]
a06309b964 Update Credits (#30026)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-07-13 20:26:39 -04:00
Pieter-Jan Briers
85fba9809a Update changelog RSS configuration (#30024)
New server
2024-07-14 01:18:12 +02:00
Winkarst
f687124312 Update IdExaminableSystem.cs to use TryFromMarkup (#29957)
* Change FromMarkup to TryFromMarkup method in IdExaminableSystem.cs

* Update
2024-07-14 01:17:15 +02:00
Plykiya
b7aa97e203 Replace obsolete EntityCoordiates.InRange() with TransformSystem.InRange() (#29993)
* Replace EntityCoordiates.InRange() with TransformSystem.InRange()

* nullspace

* I figured it out

* man I have no clue how client side sutff works

* please have mercy

* remove RadiationPulseOverlay changes

* nullspace

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 23:25:51 +02:00
Plykiya
a03b88979e Replace obsolete xform.ToMap() with xformSystem.ToMapCoordinates() (#30010)
* Get rid of a bunch of obsolete usages

* position

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 23:05:22 +02:00
Pieter-Jan Briers
c1915c9d73 Remove outdated steps from Test Packaging workflow (#30018)
gen build info was removed in 5e800e0ece but I didn't realize this workflow also tested it. Gone now.
2024-07-13 22:36:20 +02:00
Pieter-Jan Briers
5e800e0ece New CDN publish workflow (#30009)
* LET'S SEE IF THIS WORKS

* I forgot the chmod +x

* I forgot the shebang
2024-07-13 19:34:17 +02:00
Winkarst
bf4ef62ab3 Update RadiationPulseOverlay.cs to have 0 warnings (#30004) 2024-07-13 18:45:34 +02:00
Ed
dcb3443b35 Vgroid diamonds hotfix (#29999)
vgroid diamonds
2024-07-13 15:45:35 +03:00
PJBot
22a9290c5b Automatic changelog update 2024-07-13 12:17:05 +00:00
Ed
1b0c434a9f Shiny Diamonds (#25750)
* shiny

* add

* reresprite

* rereresprite

* Add files via upload

* Update ore.yml
2024-07-13 15:15:57 +03:00
Plykiya
87c82ff114 Update SpawnAfterInteractSystem.cs to not use Component.Owner (#29968)
* Update SpawnAfterInteractSystem.cs

* what the fuck is that condition

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 21:50:21 +10:00
Plykiya
6c1d1057d5 Replace DetachParentToNull() with DetachEntity() (#29992)
DETACH PARENT TO ENTITY

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 20:59:33 +10:00
CaasGit
ac768fe9f1 fix(SharedGunSystem): Return and debug log on CreateEffect. (#29656)
Sometimes CreateEffect is called on a Invalid Entity. This now causes
that to check, thus returning out and printing some hopefully helpful
logs to try to track down the real source of this issue.
2024-07-13 16:12:57 +10:00
deltanedas
87f7ea8aa9 make cargo balance ui updating its own component (#28295)
* add BankClientComponent and event

* query BankClient instead of hardcoded CargoOrderConsole for updating

* add BankClient to all ordering consoles

* :trollface:

* add Balance field to BankClient

* forgor

Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>

* m

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
2024-07-13 16:11:14 +10:00
PJBot
044d84142c Automatic changelog update 2024-07-13 06:10:25 +00:00
slarticodefast
eb4ce85354 Remove imagesharp and StatusEffectAddedEvent from FlashOverlay (#28930)
remove imagesharp and StatusEffectAddedEvent from FlashOverlay
2024-07-13 16:10:04 +10:00
Nemanja
49096cf14f Watches (#29550)
* watches

* rename

* add it into loot pools
2024-07-13 16:09:19 +10:00
Errant
361ec59412 Dummy vox deserves a proper vox name (#29789)
SKREEEEEeeeeeeee
2024-07-13 16:05:57 +10:00
metalgearsloth
f969fd2bfb Update submodule to 228.0.0 (#29947)
* Update submodule to 228.0.0

* Fix every single test

* Also this one
2024-07-13 16:05:32 +10:00
Plykiya
cb98b659ad Update SalvageSystem.Magnet to not use Component.Owner (#29961)
* Update SalvageSystem.Magnet.cs

* Update SalvageSystem.Magnet.cs the right way

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 14:20:17 +10:00
deltanedas
7b590122b6 fire extinguisher using item toggle (#29906)
* move SprayAttemptEvent to shared

* add SolutionTransferredEvent

* replace FireExtinguisher with SpraySafety

* update fire extinguisher yml

* invert visuals

* always handle event in solution transfer, it makes popups

* instantly fill it

* untroll

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-07-13 14:17:10 +10:00
PJBot
87fa6075b6 Automatic changelog update 2024-07-13 04:15:36 +00:00
Tayrtahn
3388c0dcaa Fix antag objectives always overshooting MaxDifficulty (and kill tries20) (#29830)
* The death of try20

* Add integration test for traitor gamerule

* Fix max difficulty being overshot

* Check at least one objective is assigned

* EntProtoId
2024-07-13 14:14:30 +10:00
Plykiya
de2ab29f34 Update SmokingSystem.SmokingPipe.cs to not use Component.Owner (#29967)
Update SmokingSystem.SmokingPipe.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 14:06:54 +10:00
Winkarst
e11f1e6cf6 Update ActionAlertTooltip.cs to use TryFromMarkup (#29975) 2024-07-13 14:05:51 +10:00
Plykiya
3acc100ae5 Update ShuttleDockControl.xaml.cs to not use Component.Owner (#29966)
Update ShuttleDockControl.xaml.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-13 14:05:31 +10:00
ShadowCommander
b94b52396e Add doc comments to target action components (#29982) 2024-07-13 14:04:53 +10:00
PJBot
1b360ac914 Automatic changelog update 2024-07-13 04:04:22 +00:00
lzk
55a50d0426 Use reinforced glass damage modifier for secure windoors (#29941)
* Use Rglass damage modifier for reinforced windoors

* i actually can remove this line since inherited
2024-07-13 14:03:16 +10:00
ShadowCommander
162348e02d Change whitelist to pass when null (#29981) 2024-07-13 13:43:07 +10:00
Plykiya
8ed9ea1586 Update TriggerSystem.TimedCollide.cs to not use Component.Owner (#29970)
Update TriggerSystem.TimedCollide.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 20:12:46 -07:00
Plykiya
5fa0844f3c Update UtensilSystem.cs to not use Component.Owner (#29971)
Update UtensilSystem.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 20:00:34 -07:00
PJBot
a1000587cf Automatic changelog update 2024-07-12 15:01:46 +00:00
Jonathan Argo
2e694f109d Centered hard hat sprites (#29953) 2024-07-12 18:00:40 +03:00
Ed
97aa8ff701 Merge pull request #327 from crystallpunk-14/ed-12-07-2024-upstream
Ed 12 07 2024 upstream
2024-07-12 16:23:06 +03:00
Plykiya
c94c72785d Updates GasTankSystem and InternalsSystem to not use Component.Owner (#29934)
* blah, setup

* Updates GasTankSystem and InternalsSystem to not use Component.Owner

* squish the diff

* Fixa the rest

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 21:44:45 +10:00
PJBot
e3697c6fda Automatic changelog update 2024-07-12 11:40:04 +00:00
themias
a314a967c2 Fix timer deconstruction (#29917)
Fix deconstruction for timers
2024-07-12 21:38:58 +10:00
osjarw
3ee7d7bc35 Implement Health Consideration for NPCs (#29922)
Implement TargetHealthCon
2024-07-12 21:37:47 +10:00
lzk
7ce3a1f27f Fix supplybot movement state (#29944)
Fix supplybot movement sprite
2024-07-12 21:36:40 +10:00
PJBot
caf8776d07 Automatic changelog update 2024-07-12 10:33:53 +00:00
slarticodefast
560df6ed97 Throwing system hotfix (#29935)
throwing system hotfix
2024-07-12 20:32:47 +10:00
Ed
4f24b30b22 Update base.yml 2024-07-12 13:10:02 +03:00
Ed
2ef4402068 Update base.yml 2024-07-12 12:57:02 +03:00
Ed
0931c9e7d1 Merge remote-tracking branch 'upstream/master' into ed-12-07-2024-upstream
# Conflicts:
#	Resources/Prototypes/Maps/cluster.yml
#	Resources/Prototypes/Maps/europa.yml
2024-07-12 12:53:42 +03:00
PJBot
b5e49c9c07 Automatic changelog update 2024-07-12 09:25:44 +00:00
chavonadelal
f53d0143ae Localization of dungeon direction (#29911) 2024-07-12 19:24:37 +10:00
Plykiya
a8cae6f3e6 Fixes dropping item in container (#29900)
* Items droped in containers will end up in containers

* Adds integration test for dropping entity while inside container

* comment

* comment

* trim the diff

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 19:24:08 +10:00
Plykiya
160364e100 Update BiomeSystem.cs to not use Component.Owner (#29939)
Update BiomeSystem.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 19:22:24 +10:00
Plykiya
b6672f087f Update MapScreen.xaml.cs to not use Component.Owner (#29938)
Update MapScreen.xaml.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 19:21:54 +10:00
Plykiya
65ccd6e033 Update RCDSystem.cs to not use Component.Owner (#29940)
Update RCDSystem.cs

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 19:20:41 +10:00
PJBot
00ec83af0f Automatic changelog update 2024-07-12 09:20:31 +00:00
slarticodefast
f125dda677 Make stun batons be thrown like a throwing weapon (#29883)
* make stun batons be thrown like a throwing weapon

* stun prods too

* pies too
2024-07-12 19:19:24 +10:00
themias
3a9b1eaa16 Allow notice boards to be built on walls (#29851) 2024-07-12 12:18:32 +03:00
PJBot
cd90b414df Automatic changelog update 2024-07-12 09:17:29 +00:00
Jonathan Argo
00a2c6a234 Made musket wieldable. (#29910)
* Made musket wieldable.

* Updated musket rsi meta.json copyright.

* Copyright adjustment again.
2024-07-12 12:16:21 +03:00
Ed
e87994ae40 Localization clean up + temp eng switch (#325)
* Update ContentLocalizationManager.cs

* Update battle_royale_temp.yml

* Update basic-effect-reagent.ftl
2024-07-12 08:34:08 +03:00
Plykiya
4945e6a61c Update FloorTileSystem to not use Component.Owner() (#29930)
* Update FloorTileSystem to use EntityUid

* missed a variable

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-12 00:44:19 +02:00
lzk
e3bb2771d6 Update cluster evac (#29885)
* Update cluster evac

* forgot tiny fans

* the change
2024-07-11 15:03:51 -06:00
PJBot
8fd35e8e44 Automatic changelog update 2024-07-11 14:04:28 +00:00
Winkarst-cpu
bb67364900 Better admin note popups text visibility (#29909)
* Better admin note popup text visibility

* Bring buttons closer to the border
2024-07-12 00:03:21 +10:00
chavonadelal
9a17154d83 Аnnouncement sender localization (#29907) 2024-07-12 00:02:53 +10:00
metalgearsloth
03f0257ae9 Revert "Picking a ghostrole as an admin will now deadmin you. (#29790)" (#29901)
This reverts commit 1a50760e67.
2024-07-11 17:04:10 +10:00
Tayrtahn
e6f55fafb4 Fix AtmosDeviceSystem debug assert Heisenbug (#29752)
Fix AtmosDeviceSystem debug assertion Heisenbug
2024-07-11 16:14:34 +10:00
deltanedas
02636386b5 item toggling giga rework + full ninja refactor (#28039)
* item toggle refactoring and some new systems

* add ToggleClothing component/system

* unhardcode magboots gravity logic

* make magboots and speedboots use ItemToggle and stuff

* remove now useless clothing components

* update client/server magboots systems

* add note to use ItemToggledEvent in ToggleActionEvent doc

* refactor PowerCellDraw to use ItemToggle for ui open/close control

* add TryUseCharges, refactor charges system

* update magboot trigger code

* make borg use ItemToggle, network SelectedModule instead of now removed Activated

* add AccessToggle for borg

* the giga ninja refactor

* update ninja yml

* update ItemToggle usage for some stuff

* fix activatableui requires power

* random fixing

* yaml fixing

* nuke ItemToggleDisarmMalus

* make defib use ItemToggle

* make things that use power not turn on if missing use charge

* pro

* fix sound prediction

* bruh

* proximity detector use ItemToggle

* oop

* big idiot syndrome

* fix ninja spawn rule and make it generic

* fix ninja spawn rule yml

* move loading profiles into AntagLoadProfileRule

* more ninja refactor

* ninja yml fixes

* the dreaded copy paste ops

* remove useless NinjaRuleComponent and ue AntagSelection for greeting

* fix invisibility

* move IsCompleted to SharedObjectivesSystem

* ability fixes

* oop fix powercell instantly draining itself

* sentient speedboots gaming

* make reflect use ItemToggle

* fix other test

* loadprofilerule moved into its own pr

* remove conflict with dragon refactor

* remove all GenericAntag code from ninja

* )

* probably

* remove old enabled

* great language bravo vince

* GREAT LANGUAGE

* who made this language

* because it stinks

* reparent blood-red magboots to magboots probbbly works

* most of the review stuff

* hasGrav doesnt mean what i thought it did

* make health analyzer use itemtoggle, not fail test

* fix mag/speed boots being wacky

* UNTROLL

* add ItemToggle to the random health analyzers

* a

* remove unused obsolete borg func

* untrolling

* :trollface:

* fix test

* fix

* g

* untroll

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-07-11 15:55:56 +10:00
PJBot
e45f55e36d Automatic changelog update 2024-07-11 05:54:21 +00:00
MFMessage
1a50760e67 Picking a ghostrole as an admin will now deadmin you. (#29790)
* @forcibly deadmins you

* Added checks for AdminDeadminOnJoin
2024-07-11 15:53:14 +10:00
PJBot
1ea7e3e71f Automatic changelog update 2024-07-11 05:34:27 +00:00
Cojoke
eae04129cf Glass Airlocks In Spray Painter (#29869) 2024-07-11 15:33:20 +10:00
PJBot
3ebfe468ca Automatic changelog update 2024-07-11 05:15:55 +00:00
Cojoke
19a06b6cc0 Fix the ability to shoot out of crates (#28961)
* Fix the ability to shoot out of crates

* Makes it check what inventory the player is in

* use IsEntityOrParentInContainer

* Fix Issues Github had

* gaahhh... Prevents lasers from being shot out of crates

* gaahhh... Prevents lasers from being shot out of crates

* Fix laser?

* hmmm... this is better looking I think?

* Uncook indentation

* Rerun tests?
2024-07-11 15:14:49 +10:00
Chief-Engineer
6371a04621 Fix baby jail (#29896)
* Revert "Revert Baby Jail (#29891)"

This reverts commit 24a2866747.

* the fix
2024-07-11 15:14:01 +10:00
PJBot
e01af4d602 Automatic changelog update 2024-07-11 04:49:06 +00:00
ShadowCommander
4d4f67132c Allow attack while pulling (#29703)
* Make VirtualItem not block attacking

* Remove unneeded usings
2024-07-11 14:48:00 +10:00
Vasilis
24a2866747 Revert Baby Jail (#29891)
* Revert "SS14-28662 Add Baby Jail: a Jail for Babies (inverse panic bunker) (#28763)"

This reverts commit 3ceb92a0c4.

* Revert configs

* Oops
2024-07-11 10:33:47 +10:00
PJBot
8340686078 Automatic changelog update 2024-07-11 00:25:44 +00:00
Winkarst-cpu
adcbe8d0be Character menu asks if you want to save your character on exit (#29875)
* Character menu asks if you want to save your character on exit

* Fix

* Another fix, little mistake by me

* Update Content.Client/Lobby/UI/CharacterSetupGuiSavePanel.xaml.cs

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-07-11 10:24:37 +10:00
Tayrtahn
2df65f10f5 Replace ProtoId<EntityPrototype> uses with EntProtoId (#29892) 2024-07-11 02:01:30 +02:00
Ubaser
b014d4d0e0 Update Core (#29880)
add
2024-07-10 11:42:45 -06:00
Tunguso4ka
939f0f4b27 Fixed jobwhitelist locale (#29878)
Fixed whitelist locale
2024-07-10 15:27:44 +02:00
PJBot
6f6bc38a55 Automatic changelog update 2024-07-10 10:33:36 +00:00
Winkarst-cpu
ee59ae91ec Custom solution transfer volume popup and item status panel fix (#29852)
* Fix for custom solution transfer volume

* Dirty call to prevent issues

* Another fix, git issue

---------

Co-authored-by: Winkarst-cpu <Winkarst@users.noreply.github.com>
2024-07-10 12:32:30 +02:00
PJBot
8aecd663f8 Automatic changelog update 2024-07-10 05:52:53 +00:00
saga3152
a5ec01792b Crafting pizza boxes. (#29680)
* We can now craft pizza boxes

* Fixing errors
2024-07-10 15:52:33 +10:00
beck-thompson
91740ef5be Fix typing indicators! (#29492)
* First commit

* Removed pause stuff

* Make the event better

* Forgot to add the comment

* Proto id stuff

* cool comments

* serializer

* Added the time stuff
2024-07-10 15:51:47 +10:00
Ghagliiarghii
56fb8c832e books bag tabletop (#29863)
* books bag tabletop

* Update Resources/Prototypes/Entities/Objects/Specific/Librarian/books_bag.yml

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-07-10 15:51:01 +10:00
PJBot
a1f2df0b2c Automatic changelog update 2024-07-10 05:29:42 +00:00
dffdff2423
e8b3042a38 Add an option to the admin fax menu to lock papers such that they can't be edited by cybersun pens (#28972)
* Add option to adminfax for locking papers.

* Replace dummy control with margin
2024-07-10 15:28:36 +10:00
PJBot
8d48096c57 Automatic changelog update 2024-07-10 05:27:40 +00:00
Ivan
a0165773a4 Add scarf to warm clothing bounty (#29779)
* Add scarf to warm clothing bounty

* Added ClothingScarfBase prototype and assigned to all of the scarves
2024-07-10 15:26:33 +10:00
Moomoobeef
3f2793c179 fixed missing characters in OwO accent (#29047)
replaced two characters with ones that actually show up ingame
2024-07-10 15:25:24 +10:00
Ed
eef6f92012 Steal Objective Condition now support stacks (#29843)
* Update StealConditionSystem.cs

* Update StealConditionSystem.cs
2024-07-10 15:24:25 +10:00
PJBot
d3642c7383 Automatic changelog update 2024-07-09 23:50:02 +00:00
Winkarst-cpu
c57009b646 Fix borg's popup spam (#29861)
Fix borg popup spam

Co-authored-by: Winkarst-cpu <Winkarst@users.noreply.github.com>
2024-07-10 01:48:56 +02:00
PJBot
7a66da31c7 Automatic changelog update 2024-07-09 23:29:16 +00:00
Boaz1111
d3495fc51c made the guitars be able to be worn on suitstorage (#29048)
* made the guitars be able to be worn on suitstorage

* minor fix
2024-07-10 09:28:10 +10:00
lzk
93197b6cce Fix colornetwork desc and help (#29856)
* Fix colornetwork description

* suggested changes

* forgor

* done

* ok now it IS done
2024-07-10 09:24:38 +10:00
PJBot
edf8c6cb4a Automatic changelog update 2024-07-09 23:13:46 +00:00
Plykiya
2349fb485e Stop eating food if you drop it (#29854)
* Stop eating food if you drop it

* woops, unused param

* comments

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-10 09:12:40 +10:00
lzk
742290c606 Update map changes labeler (#29858)
Update labeler.yml
2024-07-09 23:35:31 +02:00
lzk
bb82b4cd6f Change Cluster evac (#29828) 2024-07-09 15:14:25 -06:00
Ed
1ac9ec85c5 Some mobs pvs-based systems (#321)
* outPVS despawn component

* Update CP14HelperPvsSystem.cs

* experimental constrained spawners
2024-07-09 23:05:19 +03:00
Jaraten
82f1ed1493 upd cliffs (#320)
* upd cliffs

* localize

* Update marker_base.yml

* Update entities.ftl

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2024-07-09 21:31:36 +03:00
Errant
49128ba9d3 Aghosts can now /ghost (#29360)
I will not be subjected to criminal abuse
2024-07-09 18:55:47 +02:00
chavonadelal
b511d8e180 Nozzle Direction Localization (#29849) 2024-07-09 18:11:07 +02:00
chavonadelal
c9be1ef96b Localization of the threat level in an emergency lamp (#29847) 2024-07-09 16:57:36 +02:00
lzk
245c99cc78 Fix lobby time typo (#29841) 2024-07-09 23:51:03 +10:00
PJBot
8c598799b4 Automatic changelog update 2024-07-09 13:47:27 +00:00
Cojoke
62d8665484 Let Pacifists Use Certain Guns(Foam Weapons) (#29835)
Let Pacifists Use Certain Guns(foam)
2024-07-09 23:46:21 +10:00
PJBot
7bf77beb9e Automatic changelog update 2024-07-09 13:40:53 +00:00
slarticodefast
7e087a6eb8 fix passive vent sprite in construction menu (#29820) 2024-07-09 23:39:47 +10:00
chavonadelal
04cb2657bf Action menu localization (#29839) 2024-07-09 23:37:00 +10:00
chavonadelal
f3342c5155 localization and change of appearance of the phrase about the remaining time (#29844) 2024-07-09 23:36:33 +10:00
lzk
061ec432ff Add popup for health analyzer target (#29803)
* Add popup for health analyzer target

* addition

* fix showing popup to all
2024-07-09 04:42:35 -04:00
lzk
74d9ac7241 Add popup for healing target (#29804)
* Add popup for healing target

* hop

* huh

* fix one

* fix showing popup to all
2024-07-09 04:41:47 -04:00
Ed
ba03872c57 Expedition goals (#318)
* forgot this one

* disable dinosaurus

* expedition collect objective condition

* Update CP14ExpeditionSystem.cs

* add expedition objectives

* auto-issue of objectives to all expedition participants

* delete cp14playtest gamemode

* Update CP14ExpeditionObjectivesRule.cs
2024-07-09 08:31:24 +03:00
PJBot
9bf3c33cca Automatic changelog update 2024-07-09 04:24:14 +00:00
Cojoke
08b12f34b3 Fix Shotgun Spam Loading (#29827) 2024-07-09 14:23:08 +10:00
PJBot
8bd8787819 Automatic changelog update 2024-07-09 04:15:58 +00:00
Whisper
8dde49db95 all toggle light actions have a 1 second use delay (#29833) 2024-07-09 14:14:51 +10:00
Chief-Engineer
c7f752dc96 Restore a panic bunker cvar in wizardsDen.toml (#29832)
Update wizardsDen.toml
2024-07-09 14:14:18 +10:00
PJBot
f12b395f2a Automatic changelog update 2024-07-09 00:29:39 +00:00
Errant
149b6a89ca Vox guidebook entry (#29713)
* vox guidebook entry

* skreee

* Removed incorrect diet reference
2024-07-09 10:28:33 +10:00
metalgearsloth
40f735acb1 Don't treat vgroid as station grid (#29811)
Forgot I added this toggle.
2024-07-08 12:05:01 -06:00
Ed
f42546e0c6 Some round beginning preparation (#317)
* gamepresets filter

* addgamerule cp14 filter

* shuttle dropping

* long time FTL

* FTL map tweaks

* Update ShuttleSystem.FasterThanLight.cs

* handle player ship spawning (not tested yet)

* typo

* test elemental shit (ship)

* player spawn handling (real this time)

* FTL map gravity

* clean up 1

* clean up 2

* instant FTL

* Update CP14ExpeditionSystem.cs
2024-07-08 17:39:04 +03:00
ravage
451d04d759 Add beards (#312)
* :neckbeard:

borodi

* :neckbeard: v2

a
2024-07-08 14:21:56 +03:00
PJBot
d6c4ebdd37 Automatic changelog update 2024-07-08 09:04:59 +00:00
slarticodefast
92e2980534 Improve throwing precision (#29726)
* improve throwing precision

* remove debugging logs

* minor fixes

* f

* Update Content.Shared/Throwing/LandAtCursorComponent.cs

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-07-08 19:03:53 +10:00
JIPDawg
c8a87ceaab Fixed the guide book entry for Diona's blood type (#29805)
Fixed the entry for Diona's blood type

Co-authored-by: JIP <jipdawg93@gmail.com>
2024-07-08 18:30:41 +10:00
PJBot
f6d093ef5c Automatic changelog update 2024-07-08 03:34:24 +00:00
Tayrtahn
8c3e72c8c8 Silence ringtones on admin PDAs (#29801)
* Silence ringtones on invisible PDAs

* Revert "Silence ringtones on invisible PDAs"

This reverts commit afc1041f31eebe82e83630a856a8856b877a9826.

* Literally just this

* Add an admin announcement for news article publishing
2024-07-08 13:33:17 +10:00
KittenColony
5ae2590667 removed Goblin lastname (#314) 2024-07-07 21:00:02 +03:00
PJBot
eab93cb09e Automatic changelog update 2024-07-07 14:29:18 +00:00
Plykiya
04249e8682 Removes max damage threshold on healing for hyperzine (#29712)
* Removes max damage threshold for hyperzine

* the description...

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-08 00:28:13 +10:00
Nemanja
ed7f00692e The real AME nerf (#29587)
* The real AME nerf

* oh the real change

* Update AmeNodeGroup.cs
2024-07-08 00:27:52 +10:00
Nemanja
21d0f85cc2 metal foam grenades (#29428)
* metal foam grenades

* wow okay

* meh

* bruh

* test

* push
2024-07-08 00:26:58 +10:00
PJBot
ff93070d25 Automatic changelog update 2024-07-07 14:23:44 +00:00
Brandon Hu
70b56136aa fix(hardsuits): Give the carp suit and hardsuit a suit storage slot (#29322)
* fix(hardsuits): Give the carp hardsuit suit storage

* Both carpsuits have suit slots
2024-07-08 00:23:03 +10:00
NotSoDamn
437f6f451a Slicing food with Swords (#29005)
* added utensil component

* BaseSword added
2024-07-08 00:22:38 +10:00
Verm
13b84870ec Bartending+: Shaking and Stirring (#29243)
* Shaking and Stirring

* Remove shake message

* Switch if order a bit

* Add doafter supprot for reactionmixer

* Fix nullability

* Timespan zero

* Forgot to remove loc string

* Reorganize usings

* Remove unneeded usings, fix b52 needing to be shaken
2024-07-08 00:21:53 +10:00
PJBot
71b7dddb59 Automatic changelog update 2024-07-07 14:20:16 +00:00
Nemanja
0e9ed36b85 Intercom buffs and fixes (#29580)
* Intercom buffs and fixes

* remove unused bui state

* mild sec intercom buff

* reinforce sec intercoms
2024-07-08 00:19:10 +10:00
PJBot
063c5de985 Automatic changelog update 2024-07-07 13:07:30 +00:00
Simon
f50488d7e3 Raise ratking migration minimum players to 30 from 15 (#29737) 2024-07-07 23:06:24 +10:00
lzk
c9c721be16 Add supplybot moving states (#29795)
* Add supplybot moving states

* forgor
2024-07-07 23:05:09 +10:00
Ed
8e1547e616 Update attributions.yml 2024-07-07 14:06:48 +03:00
Ed
20d6ccffdb Scythe (#311)
* Scythe

* Update entities.ftl
2024-07-07 12:55:03 +03:00
PJBot
336f264c77 Automatic changelog update 2024-07-07 06:21:59 +00:00
Tayrtahn
23887d5bd9 Improve buckling's interactions with standing state (#29741) 2024-07-07 16:20:53 +10:00
PJBot
d9be666e8a Automatic changelog update 2024-07-07 03:53:24 +00:00
beck-thompson
18df27d8e7 Spilling reagents on mutliple entities at once fix (#29763)
* Fixed!

* That could have been bad this is why I'm glad I check the diff xD
2024-07-07 13:52:18 +10:00
github-actions[bot]
0098d71717 Update Credits (#29784)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-07-07 13:50:12 +10:00
themias
60ef7848fb Fix wielding while pulling (#29781) 2024-07-07 13:49:55 +10:00
PJBot
fa6d6806d1 Automatic changelog update 2024-07-06 17:34:30 +00:00
JIPDawg
5cd7cf182a Added cryosleep UnitSpawner and UnitSpawnerLate to the map Origin (#29761)
Added cryosleep UnitSpawner and UnitSpawnerLate

Co-authored-by: JIP <jipdawg93@gmail.com>
2024-07-06 11:33:20 -06:00
Ed
b6d6e2de8c haha! 2024-07-06 12:19:32 +03:00
Ed
b4b63ed898 revert sublicense, its not working 2024-07-06 12:08:50 +03:00
Ed
d9ed4a63df sublicense 2024-07-06 11:56:18 +03:00
Ed
f8b6bc7243 Update battle_royale.yml 2024-07-06 11:27:38 +03:00
Ed
205aae364c Battle royale playtest map (#309)
* setup balance

* more preparation

* Update arenas.yml

* Update battle_royale.yml

* pop

* Update arenas.yml
2024-07-06 11:22:36 +03:00
Errant
b418338af7 Phoronman 1984 (#29747)
No more.
2024-07-06 14:17:32 +10:00
MFMessage
34f36665a6 Fixes a minor typo for the base gingerbread body part (#29717)
"Fixes a minor typo in the gingerbread bodypart prototype"
2024-07-06 14:04:59 +10:00
Killerqu00
7ae3e353ea You no longer get deleted when cuffed and buckled (#29718)
fix
2024-07-06 14:01:51 +10:00
themias
7b99d1f851 Don't allow toggling internals while asleep (#29753) 2024-07-06 13:55:58 +10:00
PJBot
12edad89e8 Automatic changelog update 2024-07-06 03:53:02 +00:00
metalgearsloth
4c5c6a84dc Shuttle map button tweaks (#29757)
- Avoids adding pending objects we can never show so the list should fill much faster.
2024-07-06 13:51:55 +10:00
end
84ff5e334b nuke biochem (#29751)
Nuke biomchem again
2024-07-06 00:52:27 +03:00
AndreyCamper
24c47c805d Fire Axe resprite 45 degrees v3 (#28866)
Rotating Fire Axe 45 deg
2024-07-06 00:37:29 +03:00
DrSmugleaf
11034a0986 Fix showing the inventory button on entities without any inventory slots (#29728) 2024-07-06 00:25:23 +10:00
lzk
b0ae7d5725 Add summary comments for ElectrifiedComponent fields (#29733)
add summaries for ElectrifiedComponent
2024-07-05 09:01:39 -04:00
Ed
cc9e5f68da Update entities.ftl (#307) 2024-07-05 14:00:56 +03:00
PJBot
ead0c375f6 Automatic changelog update 2024-07-05 08:00:24 +00:00
Jezithyr
8adcb37964 Re-enabling nukie species(except vox), added antag species blacklisting
* Revert "Make all Nukies humans (#29693)"

This reverts commit 3e3e050aaf.

* Implemented species blacklist

* Re-enabled all species as Nukies except for Vox because loadouts don't support breathing alternative gases yet.
2024-07-05 00:59:16 -07:00
Ed
01f97a8aaa +3 berets (#306) 2024-07-05 08:56:38 +03:00
Ed
d9fc93e0c5 +2 lobby track (#304) 2024-07-04 23:35:53 +03:00
Ed
3182447fbf Grass update v2 (#303)
* high bush

* update worldgen
2024-07-04 23:25:22 +03:00
nikthechampiongr
8e05e1cfed Move checking code for BlacklistedRange to the right place in sqlite (#29389) 2024-07-04 21:02:53 +02:00
jmcb
bc7c121713 Fix typo in pineapple pizza description (#29714) 2024-07-04 14:30:33 -04:00
Ed
9280ca8830 Merge pull request #301 from crystallpunk-14/ed-05-07-2024-upstream
Upstream sync
2024-07-04 19:46:27 +03:00
Jaraten
b7e2d66557 wood&paper walls (#299) 2024-07-04 19:46:10 +03:00
Jaraten
a9cb687899 resprite decals (#302) 2024-07-04 19:45:24 +03:00
Ed
b1a2aaf1f5 remove vox 2024-07-04 18:25:23 +03:00
Ed
bd011bf418 Merge remote-tracking branch 'upstream/master' into ed-05-07-2024-upstream
# Conflicts:
#	Content.IntegrationTests/Tests/Round/JobTest.cs
#	Resources/Prototypes/Traits/speech.yml
2024-07-04 18:14:21 +03:00
Ed
38cd8ad6a1 Fix Vox clothing in character creation menu (#29709)
Update vox.yml
2024-07-04 22:55:00 +10:00
Brandon Hu
96ff998d18 fix(packed): Fix a couple of issues (#29422)
* fix(packed): Fix a couple of issues

* Name the signal button for bar
2024-07-04 03:02:02 -06:00
Brandon Hu
fb9c03186c fix(marathon): Fixing more issues (#29411) 2024-07-04 03:01:31 -06:00
PJBot
2cf42bf7a4 Automatic changelog update 2024-07-04 08:03:49 +00:00
Pieter-Jan Briers
8d015f5c9f Fix animation looping bugs. (#29457)
Summary of the problem is in the corresponding engine commit: a4ea5a4620

This commit requires engine master right now.

I think #29144 is probably the most severe one, but I touched Jittering and RotatingLight too since they seemed sus too.

Fixes #29144

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2024-07-04 18:02:43 +10:00
PJBot
bc7907728c Automatic changelog update 2024-07-04 07:18:53 +00:00
JIPDawg
1471bd5b53 Added Health Analyzer to basic treatment module. (#29696)
Removed dropped, added Health Analyzer to Basic Treatment Module

Co-authored-by: JIP <jipdawg93@gmail.com>
2024-07-04 17:17:47 +10:00
PJBot
acf186490c Automatic changelog update 2024-07-04 07:12:08 +00:00
metalgearsloth
2988ac3839 Make vox roundstart (#29704)
* Make vox roundstart

I believe all the issues are fixed.

* Click detection bandaid
2024-07-04 17:11:01 +10:00
PJBot
97d39e0c28 Automatic changelog update 2024-07-04 02:30:32 +00:00
Nemanja
3e3e050aaf Make all nukies humans (#29693) 2024-07-04 12:29:26 +10:00
Errant
223ade9b3f Starting gear for vox crewmembers (#29685)
* tank harness

* weh

* Suit Storage Whitelist

* Revert "Suit Storage Whitelist"

This reverts commit b1f503573c2936642a2d7627c4852153ec71ce79.

* suit storage filter

* vox spawn gear

* weh
2024-07-04 12:01:03 +10:00
PJBot
0d80021433 Automatic changelog update 2024-07-04 01:52:52 +00:00
Plykiya
62fcb6bd96 Makes portable flashers destructable (#29564)
Makes portable flashers destructible

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-04 11:51:46 +10:00
PJBot
406cf7adcd Automatic changelog update 2024-07-04 01:30:13 +00:00
Plykiya
48ae8ce0a8 Fixes objects changing physics behavior after being pulled (#29694)
* Fixes pull rotation logic

* cleaner condition

* even less code

* I CHANGED MY MIND

* first one

* second one

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-04 11:29:07 +10:00
PJBot
143151f284 Automatic changelog update 2024-07-04 01:26:31 +00:00
Rinary
9120f5fada Dynamic Radial Menus (#29678)
* fix

* Clean Some Code

* Some Commentaries

* Update Content.Client/UserInterface/Controls/RadialContainer.cs

* Update Content.Client/UserInterface/Controls/RadialContainer.cs

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-07-04 11:25:25 +10:00
Nemanja
e612ccda92 add apc power draw to stat value command (#29701)
add apc stat value
2024-07-04 11:13:49 +10:00
Interrobang01
5198c87597 improved wrench description (#29700)
Lefty latchy, righty removey
2024-07-03 20:43:42 -04:00
PJBot
5c1aa578ef Automatic changelog update 2024-07-03 17:00:36 +00:00
ArkiveDev
54c659f4aa Allow construction of rotated railings (#29687)
* Remove southRotation from railing structures

* Curly Braces
2024-07-03 12:59:29 -04:00
Alex Pavlenko
ac87f7a977 feat: allow developers to customize vscode settings, closes #29285 (#29294) 2024-07-03 11:37:40 -04:00
PJBot
833320a34a Automatic changelog update 2024-07-03 15:15:47 +00:00
Ed
a981f99b06 New anomaly behaviour: Invisibility (#29120)
* invisible anomaly

* good luck
2024-07-03 11:14:39 -04:00
Ed
7477b7c869 Cloud shadows (#298)
* not worked

* fix

* Update CP14CloudShadowsComponent.cs

* more params in component
2024-07-03 17:33:38 +03:00
metalgearsloth
a2f99cc69e VGRoid support (#27659)
* Dungeon spawn support for grid spawns

* Recursive dungeons working

* Mask approach working

* zack

* More work

* Fix recursive dungeons

* Heap of work

* weh

* the cud

* rar

* Job

* weh

* weh

* weh

* Master merges

* orch

* weh

* vgroid most of the work

* Tweaks

* Tweaks

* weh

* do do do do do do

* Basic layout

* Ore spawning working

* Big breaking changes

* Mob gen working

* weh

* Finalising

* emo

* More finalising

* reverty

* Reduce distance
2024-07-03 22:23:11 +10:00
Token
d54d27cda4 stuttering on bloodloss and electricity damage (#294) 2024-07-03 14:17:34 +03:00
Ed
e9aab2b722 World borders (#296)
* world edge mechanic

* visual fog
2024-07-03 14:06:32 +03:00
Leon Friedrich
1faa1b5df6 Allow zoom command to modify an eye's PVS range (#29245)
Allow zoom command to modify an eye's PVS range

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-07-03 16:44:55 +10:00
PJBot
a2a3233f5e Automatic changelog update 2024-07-03 05:28:41 +00:00
eoineoineoin
a05d05088e Make artifact analyzer obey laws of physics (#28117) 2024-07-03 01:27:33 -04:00
DrSmugleaf
347bed8be5 Make camera recoil system only refresh offset when its values change (#29673) 2024-07-03 15:16:18 +10:00
DrSmugleaf
c6d718d126 Fix camera recoil system overriding all other eye offsets (#29146) 2024-07-02 19:51:16 -07:00
PJBot
ae4cff4982 Automatic changelog update 2024-07-03 00:32:44 +00:00
nikthechampiongr
7defc4b87d Nerf the elite hardsuit (#29429) 2024-07-03 10:31:38 +10:00
PJBot
7b3140fbb3 Automatic changelog update 2024-07-03 00:03:05 +00:00
Plykiya
c56f495cf1 Thieving glove pickups actually stealthy (#29665)
Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-03 10:01:59 +10:00
Tayrtahn
cfc0247e5c Code Cleanup: Integration Tests (#29584)
* Cleanup PuddleTest

* Cleanup GravityGridTest

* Cleanup PowerTest

* Cleanup SaveLoadMapTest

* Cleanup Body tests

* Cleanup ContainerOcclusionTest

* Cleanup AirlockTest

* Cleanup DamageableTest

* Cleanup EntityTest

* Cleanup FluidSpillTest

* Cleanup FollowerSystemTest

* Cleanup HandCuffTest

* Cleanup InteractionSystemTests

* Cleanup InRangeUnobstructed

* Cleanup SimplePredictReconcileTest

* Cleanup PostMapInitTest

* Cleanup SalvageTest

* Cleanup SaveLoadSaveTest

* Cleanup ShuttleTest

* Cleanup MaterialArbitrageTest

* Cleanup PrototypeSaveTest

* Fix ShuttleTest

* Bunch of small ones

* Move JobTests to Station directory

* More small fixes

* Cleanup InteractionTest.Helpers
Had to change a method signature, so some callers were modified too.

* Missed one
2024-07-03 10:01:37 +10:00
lzk
58d46ddd46 Fix GhostCommand naming (#29671) 2024-07-03 10:01:17 +10:00
Ed
074ec3e17d Goblin species (#295)
* Create CP14HandDisplacementMapComponent.cs

* idk if it works, we need goblin first

* some clean up

* add goblin species sprites

* basic goblic species prototype

* hairs, ears

* typo

* hand displacement maps

* shoes displacement

* shirt displacement

* head displacement. Add support different size maps

* +dummy

* eyes displacement

* pants displacement

* gloves displacements

* cloak and mask displacement (final)

* belt displacement!

* add nose customization

* +2 ears customization
2024-07-03 01:09:57 +03:00
Token
b0ceeb19c3 fix CP14IronGrilleGate sound to chainy metall sound collection (#293) 2024-07-02 23:21:43 +03:00
Mervill
4ec15c84fa Clean up gas miners (#29657)
Separate the environment check from CapSpawnAmount into GetValidEnvironment to make the code a little cleaner, and also makes these two checks independent.

CapSpawnAmount and GetValidEnvironment now both have zero side-effects

Broken renamed Idle to reflect its use. Broken in my mind implies that there's some method for fixing.

---------

Co-authored-by: Partmedia <kevinz5000@gmail.com>
2024-07-02 12:18:56 -08:00
PJBot
542e1db913 Automatic changelog update 2024-07-02 15:29:55 +00:00
Ko4ergaPunk
59ce9e6dc7 pipetka) (#29667) 2024-07-02 18:28:49 +03:00
Brandon Hu
95f76efd80 fix(greenshift): remove meteors from greenshift (#29271) 2024-07-02 09:51:25 -04:00
PJBot
d89ea4dac7 Automatic changelog update 2024-07-02 13:34:55 +00:00
lzk
c0a1e6ea15 space law book (#29392)
* Space Law Book

* crate
2024-07-02 09:33:48 -04:00
lzk
2a6b7dbaf9 Add ability to add additional friendly and hostile factions in prototypes (#29636)
* Make friendly and hostile factions in NpcFactionMemberComponent datafiels

* :trollface:

* :trollface:
2024-07-02 09:32:21 -04:00
PJBot
5c8962823e Automatic changelog update 2024-07-02 13:05:23 +00:00
slarticodefast
daae8253c6 Fix MouseRotator on rotated grids (#29663)
* fix harm mode rotation

* cleanup

* -pi to pi
2024-07-02 23:04:15 +10:00
Chief-Engineer
763a25e934 add more info to entity json in logs (#18672)
* add more info to entity json in logs

* replace TryGetSessionById

* remove unused dependency

* get admin status from the entity

* group values by component

* alphabetize

* I've discovered that my original plans may be bad for performance
2024-07-02 11:09:24 +02:00
PJBot
cab2ea757d Automatic changelog update 2024-07-02 03:31:59 +00:00
Tayrtahn
b565258f12 Fixed buckled players thrashing while speaking in beds (#29653)
* Fix characters thrashing when talking while lying down

* Remove weird design choice
2024-07-01 23:30:53 -04:00
PJBot
2f1bc7ab93 Automatic changelog update 2024-07-01 22:24:42 +00:00
Tayrtahn
340332cf5b Fix nukeops ending early if an operative dies at base (#29642)
Fix nukeops ending early if an operative died at base
2024-07-01 18:23:36 -04:00
PJBot
854762092d Automatic changelog update 2024-07-01 21:15:44 +00:00
Cojoke
fe7dbb42b3 Allow Flares to light cigarettes (#29476)
* Allow Flares to light cigarettes

* !IsHot check

* nicer looking(and I think the right way to do that...)

* heh, whoops

* Adds IgnitionEvent, IgnitionSource now functions as IsHot when Ignited

* Fixes + remove redundancy

* Hows this?

* press enter

Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>

* Flare is not forever hot anymore

* Formatting fixes

* Make IgnitionEvent readonly

---------

Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
2024-07-01 14:14:38 -07:00
c4llv07e
73ea9197c5 Do not ignite zero coordinates because of items inside containers. (#292)
Items inside containers have zero coordinates so we shouldn't use them
in the fire spread system.

Fixes #277
2024-07-01 20:17:40 +03:00
jmcb
ed2789a0e4 Remove outdated NotNullWhen annotation (#29641)
A previous version of this function returned a bool. Since this no longer does that, remove the annotation.
2024-07-01 09:10:49 -08:00
PJBot
732489ee4a Automatic changelog update 2024-07-01 16:28:55 +00:00
jmcb
ca87fb8bc5 Fix showing tips on the login screen from the localized tip dataset (#29640)
Regression introduced in #28285
2024-07-01 12:27:49 -04:00
PJBot
e0697763f8 Automatic changelog update 2024-07-01 15:40:11 +00:00
Plykiya
7032499e2a Fixes gravity wells (#29617)
* Fixes gravity wells

* thank you slarticodefast

* Minor nitpicks addressed

* NITPICKS UNDONE

* REDO THE NITPICK, WE LOVE MATRIX MULTIPLCATION

* Revert "REDO THE NITPICK, WE LOVE MATRIX MULTIPLCATION"

This reverts commit c782eee1a1c7bda90c7ca686928019cc5f25c8cf.

* NITPICK REDO

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-01 11:39:05 -04:00
Ed
9eb86caa82 CC-BY-SA-3.0 for some assets (#290)
* Update meta.json

* Update attribution.yml

* Update attribution.yml

* Update attribution.yml

* Update meta.json

* Update attribution.yml

* Update attribution.yml

* Update meta.json

* Update meta.json
2024-07-01 12:32:59 +03:00
PJBot
cb87787ffb Automatic changelog update 2024-07-01 06:12:36 +00:00
metalgearsloth
b6cf2ce524 Add FTL arrival visuals (#29402)
* Add FTL arrival visuals

* weh

* Update Content.Shared/Shuttles/Components/FTLComponent.cs

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>

---------

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
2024-07-01 16:11:30 +10:00
metalgearsloth
5543689c14 Update submodule to 227.0.0 (#29634) 2024-07-01 16:09:41 +10:00
PJBot
a5ccf97a64 Automatic changelog update 2024-07-01 05:34:15 +00:00
Cojoke
7555952738 Add Slowdown to Dragging Items that Slow when Held (#29364)
* Add slowdown to dragging Items that slow when held

* Heh, fancy

* Heh, fancy

* rename SetMovementSpeedModifiers to GetHeldMovementSpeedModifiers because it was not setting anything
2024-07-01 15:33:08 +10:00
PJBot
195a1c1810 Automatic changelog update 2024-07-01 03:07:34 +00:00
Nemanja
84282ca016 Remove blurry vision examine mispredict (#29633)
remove blurry vision examine mispredict
2024-07-01 13:06:28 +10:00
TurboTracker
4039488654 comment out Exterminator reference in Ion Laws (#29628)
1984'ed via pull/26978 but was likely missed.
2024-06-30 23:01:53 -04:00
PJBot
a3db80af04 Automatic changelog update 2024-06-30 17:57:37 +00:00
Hmeister-real
7140d01336 CE hardsuit is fireproof again (#29516)
* helm fireproofing

* suit fireproofing

* Update hardsuit-helmets.yml

* Update hardsuits.yml
2024-06-30 10:56:31 -07:00
PJBot
a029925818 Automatic changelog update 2024-06-30 16:22:04 +00:00
Nemanja
162913ccd0 Selectable Bar Signs (#29068)
* make bar sign selectable

* ajcm strongest soldier

* AJCM comes down hard for round 2

* good shit

* ok ballin

* bless'ed be the webedit
2024-07-01 02:20:57 +10:00
Plykiya
f6bb10503f Removes obsolete AnchorEntity() functions (#28613)
Obsolete anchor entity functions

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-07-01 00:32:48 +10:00
PJBot
af1acf6e60 Automatic changelog update 2024-06-30 13:52:39 +00:00
deltanedas
379013a5da show sleeper agents in round end summary (#29468)
fix sleeper agents not showing in summary

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-06-30 09:51:33 -04:00
~DreamlyJack~
881f3e4255 New Color Dress (#29473)
* add dress

* add dress

* add dress

* add dress

* add dress

* add dress

* add dress

* add dress

* add dress yml

* add dress in dresser
2024-06-30 09:49:35 -04:00
PJBot
715e027183 Automatic changelog update 2024-06-30 13:48:27 +00:00
Partmedia
f4c7339870 Auto-scale sensor monitoring graph (#29559) 2024-06-30 09:48:20 -04:00
metalgearsloth
ab268b6e77 Make accentless cost 2 points (#29603)
Not an easy way to do this so if someone wants the default to be better be my guest.
2024-06-30 09:47:22 -04:00
Plykiya
7e2157fbed Borgs can no longer be freely locked/unlocked when emagged (#29605)
Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-30 09:46:45 -04:00
PJBot
de50a985b4 Automatic changelog update 2024-06-30 13:43:46 +00:00
Plykiya
fb1740f208 Give skeletons flash immunity (#29604)
Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-30 23:42:40 +10:00
PJBot
b426d87d82 Automatic changelog update 2024-06-30 12:29:06 +00:00
Plykiya
c8bb4e961c Change the price of traitor reinforcements to 14, nukie reinforcements to 35 (#29557)
Prices traitor reinforcements to 14, nukie reinforcements to 35

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-30 22:28:00 +10:00
PJBot
6c7f6a425e Automatic changelog update 2024-06-30 12:27:47 +00:00
Chief-Engineer
0c9a0707ce Disable ame unsafe admin alert (#29582)
disable ame unsafe admin alert
2024-06-30 22:26:41 +10:00
Plykiya
1eb3a3e6d1 Fixes lathe usage of EntityPrototypeView (#29608)
Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-30 21:45:43 +10:00
Ed
8e084267fa Merge pull request #289 from crystallpunk-14/ed-30-06-2024-upstream
Ed 30 06 2024 upstream sync
2024-06-30 12:40:08 +03:00
Ed
7abf678bbe fix inverse effect 2024-06-30 12:02:40 +03:00
Ed
7e6be7feac fix lava + affectTemp reagent effect 2024-06-30 11:49:51 +03:00
Ed
dbdb81381b Merge remote-tracking branch 'upstream/master' into ed-30-06-2024-upstream
# Conflicts:
#	Resources/Prototypes/Maps/box.yml
#	Resources/Prototypes/Maps/meta.yml
#	Resources/Prototypes/Maps/oasis.yml
#	Resources/Prototypes/Maps/origin.yml
#	Resources/Prototypes/lobbyscreens.yml
2024-06-30 11:18:30 +03:00
Plykiya
6f8369ed6b Fixes colored gloves appearing incorrectly in chameleon menu (#29607)
Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-30 03:28:17 -04:00
PJBot
92491c90e0 Automatic changelog update 2024-06-30 04:35:13 +00:00
ShadowCommander
afe9f3ae85 Fix ItemMapper whitelist mispredict when inserting or removing items (#29461)
* Fix ItemMapper whitelist mispredict when inserting or removing items

Makes the ItemMapper MapLayerData available on client so that the client
can predict whether an inserted/removed item changes the visibility of
a sprite layer.

* review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2024-06-30 14:34:06 +10:00
PJBot
3aa6270de6 Automatic changelog update 2024-06-30 04:29:56 +00:00
metalgearsloth
8985a48a34 Fix unlimited MaxTraitPoints for traits (#29600)
-1 is a silly API because now you have to handle it everywhere manually instead of using nullability.
2024-06-30 14:28:49 +10:00
PJBot
0974149c82 Automatic changelog update 2024-06-30 03:47:38 +00:00
MureixloI
fef679846c Fix some job's drobes point light (#29590)
* Fix some job's drobes point light

* Fix some job's drobes point light
2024-06-30 13:46:31 +10:00
SlamBamActionman
b9fa941ca6 Turn ReagentEffects into generic EntityEffects (#28168)
* Oh the possibilities

* Merge fixes

* Forgot to remote LavaSystem oops

* Changed EntityEffectArgs to EntityEffectBaseArgs and EntityEffectReagentArgs

* Throw exception for unimplemented effectargs

* Remove Json and overrideable datafields

* Fix test issues

* Actually fix the compiling issue

* Fix comments and remove EntityEffectArgs (no longer used, replaced with EntityEffectBaseArgs)
2024-06-30 13:43:43 +10:00
DrSmugleaf
250109f0b4 Fix armor speed examine giving you every single decimal place (#29597) 2024-06-29 21:39:31 -04:00
github-actions[bot]
af78c75d66 Update Credits (#29594)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-06-29 20:31:18 -04:00
Chief-Engineer
e6e7a29b68 Fix Farm Grass Hopper config for real this time (#29583)
Update wizardsDenGateway.toml
2024-06-29 22:18:06 +02:00
Guillaume E
83e048ee45 Improve gas miner's output bounds checks (#29569)
Miners now can produce a fraction of their SpawnAmount corresponding
to the "remaining space" available in their environment according to
their MaxExternalPressure and MaxExternalAmount.
2024-06-29 11:44:32 -07:00
Nemanja
eda8028dd6 fix explosion resistance showing 0 values (#29572)
* fix explosion resistance showing 0 values

* markup
2024-06-29 13:21:47 -04:00
osjarw
6af418663e Limit air lost by wrenching/breaking pipes (#29574)
Gas lost via wrench/breaking capped
2024-06-29 09:06:25 -07:00
PJBot
e8ee3bc1ad Automatic changelog update 2024-06-29 15:24:09 +00:00
Pieter-Jan Briers
2a7bdd9b08 Revert "plutonium core steal objective" (#29578)
Revert "plutonium core steal objective (#26786)"

This reverts commit f6ce07289a.
2024-06-30 01:23:03 +10:00
PJBot
325d64b5ed Automatic changelog update 2024-06-29 05:41:03 +00:00
metalgearsloth
6937857446 Ensure trait groups get validated (#28730)
* Ensure trait groups get validated

The only validation being done was on the UI. I also made the "Default" group match the PascalCase naming schema so might be a slight breaking change but the original PR only got merged a few days ago.

* overwatch
2024-06-29 15:39:57 +10:00
IProduceWidgets
3e7c0a086b Oasis Atmos department rework (#29549)
* Atmos department rework

* move paperwork back to library

* Would you believe I forgot a valve?

* camer and fore extinguisher wallmounts in new room.
2024-06-28 23:35:14 -06:00
PJBot
190a051ee9 Automatic changelog update 2024-06-29 05:03:54 +00:00
slarticodefast
cd2968d849 Add sprite for vent under-pressure lock-out (#29527) 2024-06-28 22:02:48 -07:00
slarticodefast
ebd6104c63 Fix air vent and scrubber not requiring power (#29544) 2024-06-28 21:41:49 -07:00
PJBot
9ee66892a0 Automatic changelog update 2024-06-29 04:12:38 +00:00
deltanedas
f6ce07289a plutonium core steal objective (#26786)
* add textures

* add SealingCabinet system

* add StoreUnlocker/ObjectiveUnlock system

* add plutonium core and nuke core container

* make nuke deconstructable

* add steal core objective

* add core extraction toolbox to new category

* typo ops wrench fuel

* use queries and resolve, have it resolve instead of using Comp

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-06-29 14:11:31 +10:00
PJBot
1c66e1d27d Automatic changelog update 2024-06-29 04:11:07 +00:00
Artjom
881c2323fd Favorites tab for the construction menu (#26347)
* Added fovarite button

* Some fixes in xaml

* added some events for favorite recipes

* set methods for presenter

* fixes for  presenter

* added translates

* reset seach when you select any category

* added some margins

* some fixes from compared

* fixed PR notes about arrays

* deleted controls & margins

* did simpleer with arrays

* review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2024-06-29 14:10:00 +10:00
PJBot
64af03042a Automatic changelog update 2024-06-29 03:35:02 +00:00
metalgearsloth
9032231300 Predict typing indicator (#29551)
It greatly annoys me in the rare instance I do play.
2024-06-29 13:33:56 +10:00
PJBot
4cc37a74dc Automatic changelog update 2024-06-29 03:29:53 +00:00
Token
f7e92980ab Mechs now destructable (#29338)
Add Destructible component to BaseMech
So all mechs are destructable now
2024-06-29 13:28:46 +10:00
DrSmugleaf
e3896e45fc Move GameTicker.RoundDuration to Shared (#29425) 2024-06-28 22:42:58 -04:00
Pieter-Jan Briers
797aebb161 Fix bugs resulting in quantum APC visual states (#29475)
There were TWO bugs here

FIRST, APCs *did* update their visual state on initialization, but at that point the relevant power state hasn't been initialized yet, so it always returns a bogus result. There aren't guaranteed to be subsequent power updates that actually trigger the APC to update so this can get it stuck.

Fixed by just deferring the on-init update to be after the first update tick, which is itself ordered to be after power update.

SECOND: Once I fixed that, I ran into the issue that APCs created at *server startup* also fail to update, because the throttling system (to prevent frequent APC updates) thinks the LastChargeStateTime was at server startup.

Fixed by making that variable nullable so it defaults to null.

Also removed the useless datafields on the "last update" fields. These are all just used to cache and throttle updates, something that should not be persisted to a map file.
2024-06-28 22:07:00 -04:00
Moomoobeef
cb6aeb4f96 Fixed the pipe in the TEG sprite (#29543)
fixed sprites
2024-06-28 22:03:45 -04:00
Brandon Hu
21a93eb6e8 tweak(oasis): Swap floppa and paperwork spawns (#29495)
tweak(oasis): Swap floppa and paperworkspawns
2024-06-28 19:24:46 -06:00
PJBot
aa1900d8dd Automatic changelog update 2024-06-28 23:29:33 +00:00
T-Stalker
692a6067e9 Remove rads from bananium (#29545)
webedit ops
2024-06-28 19:28:27 -04:00
PJBot
1e027de3e1 Automatic changelog update 2024-06-28 21:22:43 +00:00
Plykiya
dac09679a5 Fixes Chameleon menu icons appearing incorrectly (#29539)
EntityPrototypeView my beloved

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-28 17:21:36 -04:00
Guillaume E
c38859b77a Make miners respect AtmosDeviceUpdateEvent.dt (#29522)
Miners' prototype have been changed to reflect this (I read
somewhere that we have about 1 atmos tick/0.5s, my tests show more
like 1/0.53 but that looks close enough).

This also means that miner's spawnAmount is now expressed in mol/s.

See: #18781
2024-06-28 10:49:39 -08:00
Errant
9e4b8077f3 suit storage whitelist code (#29332)
suit storage whitelist
2024-06-28 11:11:43 -04:00
Pieter-Jan Briers
6409004244 WATTAGE IS NOT A UNIT OF STORED ENERGY (#29538) 2024-06-28 17:00:45 +02:00
PJBot
315aac9aab Automatic changelog update 2024-06-28 12:34:09 +00:00
slarticodefast
418fc79698 Give passive vents the correct sprite (#29536)
give passive vents the correct sprite
2024-06-28 08:33:03 -04:00
Ed
1dbe308527 Entity ru localization sync (#285)
* first use

* LOCALIZAAATION

* and again

* Update fire.yml

* Update entities.ftl

* Update main.py

* Update main.py

* delete wrong locales

* battle staff locale

* Update main.py

* more remove

* Update wielded-inhand-right.png
2024-06-28 12:25:20 +03:00
PJBot
e99e65929e Automatic changelog update 2024-06-28 03:35:30 +00:00
Plykiya
1f6e140eb6 Hide doafters if you're in a container (#29487)
* Hide doafters if you're in a container

* Out of the loop

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-28 13:34:24 +10:00
PJBot
1d17e4051f Automatic changelog update 2024-06-28 03:34:04 +00:00
Repo
4a728fa3c6 Fix Admin Object tab sorting and search - Part 2 (#28681)
* admin Object tab sorting and searchable

* Fix for showing disconnected players on player admin tab

* Fix namespace and search bar location.

* Change linq to loop.

* No more Linq to sort

* Fix item click vv menu

* Added refresh button and refresh on opening tab.

* Clear spaces.

* Move tab magic numbers to enums

* Get rid of old unused xaml

* Fix code style issues and button event type.

* Merge in baby jail

* More style cleanup and move cast around.

* Make the localization a little more easy to read, same loc var names.

* Missed Loc for label

* Fix class field order

* Over zelous delete.

* Small updates.

* Min syntax issues fix
2024-06-28 13:32:57 +10:00
PJBot
496860e254 Automatic changelog update 2024-06-28 00:24:23 +00:00
JIPDawg
bb50087dd0 Fixed the sound of pulling back a foam crossbow from a flash sound to a bow pull sound. (#29508)
Fixed foam Crossbow making a flash sound to just a bow pull sound

Co-authored-by: JIP <jipdawg93@gmail.com>
2024-06-27 20:23:17 -04:00
PJBot
7fa081e884 Automatic changelog update 2024-06-28 00:09:15 +00:00
Nemanja
c7fcbe8c16 map renderer fixes (#29523)
* map renderer fixes

* remove useless casts
2024-06-28 10:09:05 +10:00
metalgearsloth
bc1703323e Revert "Make wearing an Ushanka also apply accent to your name" (#29524)
Revert "Make wearing an Ushanka also apply accent to your name (#29111)"

This reverts commit e5a85e2a13.
2024-06-28 10:08:09 +10:00
ArkiveDev
d5b5dafb3a Still immovable rods are now actually still (#29518)
Set the still rod's max velocity to 0 so it gets a 0 mangintude impulse on init
2024-06-27 18:07:12 -04:00
Ed
54ecb1b23e added battle staff (#286) 2024-06-27 23:29:27 +03:00
Jaraten
dcfd3f6aa5 New tiles (#274)
* New tiles

* fix yaml & resprite

* migration fix

* ftl fix

* fix typo

* fix typo +1

* fix C# typo

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
2024-06-27 22:16:05 +03:00
comasqw
b592842a66 fix localization helper & protos descriptions in ftl (#282)
* fix localization helper & protos descriptions in ftl

* Update main.py

* Update objects.ftl

* добавил ярлык напрямую к файлу локализации

* megasuperduperpuperTWEAK

* Update yml_parser.py

* Update yml_parser.py

* Update yml_parser.py

* Update yml_parser.py

* Update main.py

* tweak

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Ed <edwardxperia2000@gmail.com>
2024-06-27 22:07:25 +03:00
PJBot
2ed32be514 Automatic changelog update 2024-06-27 15:12:39 +00:00
KonstantinAngelov
64192b3506 CookBook name,id and description changed to not be "meta" (#29467)
* CookBook name,id and description changed

* Id isues with CookBook fixed

* Maps not added
2024-06-27 11:11:33 -04:00
PJBot
331c0fe326 Automatic changelog update 2024-06-27 14:59:02 +00:00
Pieter-Jan Briers
ced15b7934 Fix coords monitor in replays (#29512)
The F3 coords manager is blocked if you're not an admin. This check happened even when playing a replay, where you actually aren't. There's now a check to make sure you are actually server-connected-to-game before running the logic.

Also moved it to a manager because this *shouldn't be a bloody entity system in the first place*.
2024-06-27 16:58:51 +02:00
Pieter-Jan Briers
45cc19f315 Add InteractUsing admin logs. (#29514)
Apparently we did not have these.
2024-06-27 16:58:42 +02:00
Pieter-Jan Briers
0896edf06c Remove placing items on tabletop boards. (#29513)
This feature should never have been merged, it can be trivially abused to break the entire server.

It's behind a CVar because honestly that's the easiest way to 1984 the feature.
2024-06-27 16:57:55 +02:00
Partmedia
849a790617 Increase lockout threshold (#29504) 2024-06-27 01:05:27 -07:00
PJBot
4ec2966f47 Automatic changelog update 2024-06-27 02:10:04 +00:00
Tayrtahn
f1e7b4c499 Fix double labels on pills and pill canisters (#29499) 2024-06-26 22:08:56 -04:00
PJBot
fb705ab3ef Automatic changelog update 2024-06-26 14:26:49 +00:00
Doomsdrayk
441325347c Fix disposals being effective nuclear bunkers (#29438)
Make disposals report their contents to the explosion system
2024-06-27 00:25:42 +10:00
Plykiya
4a0c637ee8 Fixes magic mirror interactions (#29491)
* Fix for magic mirror interaction

* Works for all cases

* swap the order, works

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
2024-06-27 00:25:11 +10:00
DrSmugleaf
58efe4fdd1 Fix storages bugging out if an open storage has its component removed (#29485)
* Fix storages bugging out if an open storage has its component removed

* Fix error on close
2024-06-27 00:11:51 +10:00
PJBot
063011ec8d Automatic changelog update 2024-06-26 13:44:50 +00:00
Chief-Engineer
c81ba6e4a9 Alert shared connections (#29405)
* add admin alert for active shared connections

* update wizden config

* review
2024-06-26 15:43:43 +02:00
Tayrtahn
1a67ab8c95 Forcemap can be cleared with empty string again (#29472) 2024-06-26 16:41:31 +10:00
PJBot
c34fb39cf3 Automatic changelog update 2024-06-26 03:28:05 +00:00
VeritableCalamity
4241ad34b6 Give moldy food the "Trash" tag (#29380)
Make moldy food items have the "Trash" tag, so they can be collected.
2024-06-25 23:26:59 -04:00
PJBot
7ee2b6f397 Automatic changelog update 2024-06-26 02:28:17 +00:00
lzk
a540d1ab17 Make blood less satiate hunger (#29433) 2024-06-25 22:27:11 -04:00
DieselMohawk
90c33da521 Security Webbing Resprite (#29441) 2024-06-25 22:00:16 -04:00
Джексон Миссиссиппи
33dd7d4965 Fix dragon ghost role rules (#29474)
q
2024-06-26 11:20:45 +10:00
PJBot
06e21aae6e Automatic changelog update 2024-06-26 00:49:35 +00:00
Pieter-Jan Briers
37fffca615 Cut low pressure damage to 1/4 (#29478) 2024-06-25 20:48:26 -04:00
Snicket
231e180ff3 reclaimer-lobby-art (#29343)
* reclaimer-lobby-art

* fixed attribution from my part-Snicket

* fixed atributions this this time fr

* man

* Grobletombus
2024-06-25 15:28:37 +02:00
IProduceWidgets
d2eff3efa3 Oasis update (#29440)
* very minor things, mostly issue resolutions.

* purge invalids
2024-06-25 00:44:09 -06:00
PJBot
866ca966b1 Automatic changelog update 2024-06-25 06:29:54 +00:00
Tayrtahn
3009687326 Fix internals not auto-activating for entities spawned in space (#29213)
* Add organs before trying to breathe

* Add tests for auto-internals

* EntMan to the rescue
2024-06-25 16:28:48 +10:00
PJBot
84a54406dc Automatic changelog update 2024-06-25 03:57:52 +00:00
Elysium206
8c7fc9890c Increase of riot shield durability (#29239) 2024-06-24 23:56:46 -04:00
DrSmugleaf
a4d93362c3 Attempt to fix random test fail by undeleted AlertControl._spriteViewEntity (#29424) 2024-06-25 11:31:38 +10:00
Vasilis
27665e44a9 Fix filter yml names in the lobby so they actually work (#29435)
Fix filter yml names so they actually work
2024-06-25 02:53:16 +02:00
Pieter-Jan Briers
ebbe3c9144 Revert "TEG can power itself when turned on" (#29434)
Revert "TEG can power itself when turned on (#29072)"

This reverts commit 9f9cf08d72.
2024-06-25 10:38:06 +10:00
PJBot
56c4e60e45 Automatic changelog update 2024-06-24 22:41:26 +00:00
deathride58
bd3508d803 Colorblind friendly thermomachine LED colors (#29397)
Colorblind friendly thermomachines
2024-06-24 15:40:19 -07:00
Tayrtahn
8aea47a7ee Fix forcemap not bypassing requirements (#29426)
* Fix forcemap not bypassing requirements

* Add integration test for forcemap
2024-06-24 18:29:44 -04:00
PJBot
0822284cba Automatic changelog update 2024-06-24 22:04:11 +00:00
Emisse
7453f459c9 hardsuit fireproof nerf (#29416)
hardsuit nerf
2024-06-24 18:03:05 -04:00
PJBot
5aaac8b774 Automatic changelog update 2024-06-24 21:57:35 +00:00
Chief-Engineer
fd0511144a Use moderator perms for grant_connect_bypass (#29406)
use moderator perms for grant_connect_bypass
2024-06-24 23:56:29 +02:00
Pieter-Jan Briers
c1ad5cded0 Fix gay nuke layering (#29410)
I fucked up while exporting from aseprite whoops.
2024-06-24 20:01:24 +02:00
Pieter-Jan Briers
3df7309dbf Hotfix examine (#29408)
#55328 was failing tests and shouldn't have been merged, it broke examine.

The problem is that for some reason, client-side examine system doesn't call base Initialize. So my entity query change (that I did not test) broke.

By the way, this same "not calling base" meant that group examine system wasn't predicting properly when it totally could've. Incredible.
2024-06-24 18:02:43 +02:00
PJBot
f068687306 Automatic changelog update 2024-06-24 15:38:00 +00:00
Pieter-Jan Briers
e7bcb270e4 Ghosts can now always see examine details (#29404)
* Ghosts can now always see examine details

This means they bypass range and occlusion checks for getting extra detail, like the charge on an SMES.

* EntityQuery
2024-06-24 17:36:52 +02:00
ArkiveDev
d9506ce3a6 Force map confirmation (#29391)
* Add map check to forcemap command

* remove debug line

* remove accidental newline
2024-06-24 13:56:21 +03:00
metalgearsloth
c6e5b2339e Network BaseEmitSoundComponent (#29400)
* Network BaseEmitSoundComponent

* high intelligence
2024-06-24 19:55:28 +10:00
MureixloI
6888511e03 Fix cargo and salvage's computer point light (#29384) 2024-06-23 18:17:59 -04:00
PJBot
c41558aa6e Automatic changelog update 2024-06-23 19:34:18 +00:00
DrEnzyme
659010993f Add bagels (#24799)
Bagels are made by using a rolling pin on a dough slice to make a dough rope, then cooking the dough rope in a microwave for 5 seconds. There are two types: a normal bagel and a poppyseed bagel. The poppyseed bagel requires a poppy and a dough rope and has a small (5u) quantity of Bicaridine inside of it in addition to its nutriment.

Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
2024-06-23 12:33:12 -07:00
PJBot
08352151e3 Automatic changelog update 2024-06-23 17:32:41 +00:00
Tayrtahn
ac1bdd2c84 Fix unlabeled jugs in ChemVend (#29178)
* Spawn dummy entities on client for vending machine UI

* Asked sloth, and we kinda need this pr

---------

Co-authored-by: Vasilis <vasilis@pikachu.systems>
2024-06-23 19:31:34 +02:00
mhamster
ba164f9e48 ContainmentFieldComponent's garbage destruction can now be disabled (#29376)
* Garbage Vaporizer 3000

+ DestroyGarbage bool property
+ DestroyGarbage property check when dealing with incoming trash

* Update ContainmentFieldComponent.cs

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>

---------

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
2024-06-23 11:34:32 -04:00
Pieter-Jan Briers
0c34eb6138 Ban template system (#29365)
To help out admins, so they can easily fill out datacenter bans and stuff. Supports ban exemption flags and everything.

This is for use with SS14.Admin so it's just DB models here.
2024-06-23 17:33:54 +02:00
Nemanja
19bc6f961d ironrock ores (#29381) 2024-06-24 01:02:16 +10:00
PJBot
6385c8c530 Automatic changelog update 2024-06-23 14:53:38 +00:00
eoineoineoin
2762470096 Add "Structure" tag to switches, buttons, and levers (#29378)
Co-authored-by: Eoin Mcloughlin <helloworld@eoinrul.es>
2024-06-23 10:52:30 -04:00
Errant
ba39b6f551 Survival box loadout group cleanup (#29379)
cleanup
2024-06-23 08:41:34 -04:00
Brandon Hu
e8a4808f16 fix(atlas): Replace mindshield crate with implanter crate (#29184) 2024-06-23 02:04:31 -06:00
Brandon Hu
93eded4803 fix: Adds a missing defribilator to nukie planet (#28362)
* fix: Adds a missing defribilator to nukie planet

* Fix: unpause nukie map

* What changes?
2024-06-23 02:04:09 -06:00
Brandon Hu
801c4f9181 tweak(medical): Reduce chemist slots (#28711)
* tweak(medical): Reduce chemist slots

* tweak(medical): roundstart chemists slot set to 2 on some maps

* tweak(fland): Chemist slots to 3

fland is target to 80-100 players
2024-06-23 02:03:00 -06:00
Brandon Hu
7399c758d3 fix(oasis): Replace mindshield crate with implanter crate (#29181) 2024-06-23 02:02:21 -06:00
Brandon Hu
33baf418cd fix(cluster): Replace mindshield crate with implanter crate (#29182) 2024-06-23 02:02:08 -06:00
Brandon Hu
8573eda852 fix(origin): Replace mindshield crate with implanter crate (#29183) 2024-06-23 02:01:54 -06:00
Brandon Hu
00e7aa4976 tweak(marathon): Fix some stuff (#29256)
* tweak(marathon): Add cargo request computer to bridge

* fix everything else
2024-06-23 02:01:11 -06:00
Brandon Hu
32e2a4e9ce tweak(meta): Swap around some of the computers in bridge (#29263)
* tweak(meta): Swap around some of the computers in bridge

* tweak(meta): unpause map
2024-06-23 02:00:42 -06:00
Brandon Hu
6ba2df7fa4 tweak(fland): Add radiation shutters to front of PA (#29265) 2024-06-23 02:00:13 -06:00
Brandon Hu
9455d0da7f tweak(emergency_box): Swap out Salvage Material crate with Engineering crate (#29269) 2024-06-23 01:59:57 -06:00
Brandon Hu
b1955f72d7 tweat(emergency_delta): Add screens around the evacuation shuttle (#29267) 2024-06-23 01:59:37 -06:00
Brandon Hu
252a3e6be4 tweak(saltern): Place a red phone in bridge meeting room, add another artifact spawn (#29359)
* tweak(saltern): Place a red phone in bridge meeting room

* add artifact spawn
2024-06-23 01:59:07 -06:00
Brandon Hu
bada3bc75b fix(omega): Connect the disposal unit in medbay to the disposal "network" (#29305)
fix(omega): Connect the disposal unit in medbay to the disposal pipe system
2024-06-23 01:57:20 -06:00
Brandon Hu
de22f659e8 fix(packed): Fill the medical lockers in medbay (#29319) 2024-06-23 01:57:04 -06:00
Nemanja
c90c065431 swap siren (#29369) 2024-06-23 00:38:41 -04:00
Tayrtahn
c2f8984e6c Apply RoleLoadout MinLimit fix to EnsureValid too (#29358)
Apply MinLimit fix to EnsureValid too
2024-06-23 12:17:28 +10:00
metalgearsloth
0546c9bf64 Revert "Weapon Reflection Movement Mechanic (#27219)" (#29326)
* Revert "Weapon Reflection Movement Mechanic (#27219)"

This reverts commit b90373356e.

# Conflicts:
#	Content.Shared/Alert/AlertType.cs
#	Content.Shared/Weapons/Reflect/ReflectSystem.cs

* Add myself to codeowners

* Add myself to codeowners

* Also the alerts
2024-06-22 22:16:08 -04:00
PJBot
089cdcf777 Automatic changelog update 2024-06-23 01:47:38 +00:00
WarMechanic
9f9cf08d72 TEG can power itself when turned on (#29072) 2024-06-22 18:46:31 -07:00
github-actions[bot]
f15ccea6dd Update Credits (#29363)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-06-23 02:29:52 +02:00
PJBot
dbe283cb1f Automatic changelog update 2024-06-23 00:29:26 +00:00
Cojoke
966aca437c Add the ability to put hats on medibots (#28584) 2024-06-22 20:28:20 -04:00
PJBot
627b19c8fb Automatic changelog update 2024-06-22 23:47:25 +00:00
Floofi
3284c24ece add lemon juice and fix bad sprite allocation (#27465) 2024-06-22 19:46:19 -04:00
Pieter-Jan Briers
f582e690eb Remove robotics and supermatter lobby images (#29355)
They don't look good, we have way better ones now.
2024-06-22 17:00:09 -04:00
Vasilis
ae84889235 Don't add untriage lable if it has been labeled at issue creation (#29356) 2024-06-22 21:47:59 +02:00
PJBot
640115d646 Automatic changelog update 2024-06-22 17:50:56 +00:00
nikthechampiongr
6aced66406 Firelocks are no longer pryable by hand if they are powered (#29221) 2024-06-22 10:49:50 -07:00
PJBot
061445ef6e Automatic changelog update 2024-06-22 15:48:08 +00:00
lzk
325ab97a7d Prying reinforced tile now will give you back metal rod (#29084)
* Reinforced tile can we welded back into metal rod

* more changes

* weh

* fix

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2024-06-23 01:47:02 +10:00
PJBot
b9172a7823 Automatic changelog update 2024-06-22 15:45:24 +00:00
K-Dynamic
2a6fc45ab5 Thief toolbox minor rebalance & description clean-up (#27771)
* thief clean-up

* anatomy set description change

* description changes
2024-06-23 01:44:18 +10:00
PJBot
f954970db8 Automatic changelog update 2024-06-22 15:23:12 +00:00
Partmedia
8112063a8b Add air alarm hysteresis (#29223)
Add firelock hysteresis
2024-06-23 01:22:17 +10:00
Partmedia
02fb432b05 Adjust some gas thresholds (#29331) 2024-06-23 01:22:06 +10:00
PJBot
4d6da0017c Automatic changelog update 2024-06-22 15:14:04 +00:00
deltanedas
475c2a0b42 add access reader log wire (#29094)
* add LoggingDisabled to AccessReader

* add LogWireAction

* -m give everything besides high-security door a log wire

* make LogAccess public and support string arg

* add log when pulsing

* m

* l

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-06-23 01:12:58 +10:00
PJBot
092cad4ba1 Automatic changelog update 2024-06-22 15:10:48 +00:00
marbow
5ee79b51ca Sound Station 14 like a nukie song (#29345)
Nukie song!!
2024-06-23 01:09:41 +10:00
Flareguy
45a4596e8b Disk """resprite""" (#29277)
* disk ""resprite""

* fix holodisk
2024-06-22 23:06:17 +10:00
MetalSage
061c1f520c Admin UI localization (#29340)
admin ui localization

Co-authored-by: MetalSage <metalsage.official@gmail.com>
2024-06-22 23:05:33 +10:00
PJBot
df5c4df894 Automatic changelog update 2024-06-22 10:44:24 +00:00
Errant
c418758a3a Fix for missing survival boxes (#29336)
storagefill order fix
2024-06-22 20:43:18 +10:00
Partmedia
dfe01c7bb1 Fix comments (#29330) 2024-06-21 23:02:06 -07:00
ArkiveDev
b5f6aa0c9d Pacifist messages use target's identity name instead of entity name (#29325) 2024-06-22 15:19:40 +10:00
Partmedia
bb61f44d92 Move air sensor components into abstract base prototype (#29261) 2024-06-21 21:57:14 -07:00
PJBot
104881763c Automatic changelog update 2024-06-22 04:16:27 +00:00
Nemanja
be7ffd89e2 AME Deconstruction Changes (#29317)
* AME deconstruction complexity

* review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2024-06-22 14:15:21 +10:00
metalgearsloth
892263302f Update submodule to 226.3.0 (#29323) 2024-06-22 14:13:11 +10:00
Pieter-Jan Briers
07fe1a6b5a Rewrite the options menu (#28389)
* Basic attempt at rewriting how the options menu works, move accessibility settings into their own tab.

* Audio tab uses the new options system.

* Rewrite Misc tab

* Clean up heading styling

* Rewrite options tab and other minor cleanup all over the place.

* Documentation comments and minor cleanup.

---------

Co-authored-by: AJCM <AJCM@tutanota.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2024-06-22 14:11:14 +10:00
Doomsdrayk
e0a6604d06 Fix pistols not displaying ammo count in-hand (#29289)
* Make Drozd and C-20r not unwield on use

* Fix wielding mispredict

* add AmmoCounter to pistols
2024-06-22 11:46:51 +10:00
Ko4ergaPunk
6aa7e2edce Fix noticeboard drawdepth (#29262)
darwdepth added
2024-06-22 11:45:33 +10:00
PJBot
0ff144af73 Automatic changelog update 2024-06-22 01:12:48 +00:00
Alex Evgrashin
b7c088fbf3 Fix SSD indicator for scaled humanoids (#29310)
Fix ssd
2024-06-22 11:11:40 +10:00
1862 changed files with 106518 additions and 35466 deletions

7
.github/CODEOWNERS vendored
View File

@@ -55,3 +55,10 @@
#Jezi
/Content.*/Medical @Jezithyr
/Content.*/Body @Jezithyr
# Sloth
/Content.*/Audio @metalgearsloth
/Content.*/Movement @metalgearsloth
/Content.*/NPC @metalgearsloth
/Content.*/Shuttles @metalgearsloth
/Content.*/Weapons @metalgearsloth

4
.github/labeler.yml vendored
View File

@@ -5,8 +5,8 @@
"Changes: Map":
- changed-files:
- any-glob-to-any-file:
- 'Resources/Maps/*.yml'
- 'Resources/Prototypes/Maps/*.yml'
- 'Resources/Maps/**/*.yml'
- 'Resources/Prototypes/Maps/**/*.yml'
"Changes: UI":
- changed-files:

View File

@@ -9,5 +9,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions-ecosystem/action-add-labels@v1
if: join(github.event.issue.labels) == ''
with:
labels: "Status: Untriaged"

View File

@@ -41,31 +41,22 @@ jobs:
- name: Package client
run: dotnet run --project Content.Packaging client --no-wipe-release
- name: Update Build Info
run: Tools/gen_build_info.py
- name: Shuffle files around
run: |
mkdir "release/${{ github.sha }}"
mv release/*.zip "release/${{ github.sha }}"
- name: Upload files to centcomm
uses: appleboy/scp-action@master
- name: Upload build artifact
id: artifact-upload-step
uses: actions/upload-artifact@v4
with:
host: centcomm.spacestation14.io
username: wizards-build-push
key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }}
source: "release/${{ github.sha }}"
target: "/home/wizards-build-push/builds_dir/builds/"
strip_components: 1
name: build
path: release/*.zip
compression-level: 0
retention-days: 0
- name: Update manifest JSON
uses: appleboy/ssh-action@master
with:
host: centcomm.spacestation14.io
username: wizards-build-push
key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }}
script: /home/wizards-build-push/push.ps1 ${{ github.sha }}
- name: Publish version
run: Tools/publish_github_artifact.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
ARTIFACT_ID: ${{ steps.artifact-upload-step.outputs.artifact-id }}
GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }}
- name: Publish changelog (Discord)
run: Tools/actions_changelogs_since_last_run.py
@@ -77,3 +68,8 @@ jobs:
run: Tools/actions_changelog_rss.py
env:
CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }}
- uses: geekyeggo/delete-artifact@v5
if: always()
with:
name: build

View File

@@ -64,11 +64,3 @@ jobs:
- name: Package client
run: dotnet run --project Content.Packaging client --no-wipe-release
- name: Update Build Info
run: Tools/gen_build_info.py
- name: Shuffle files around
run: |
mkdir "release/${{ github.sha }}"
mv release/*.zip "release/${{ github.sha }}"

1
.gitignore vendored
View File

@@ -306,3 +306,4 @@ Resources/MapImages
# Direnv stuff
.direnv/
/Tools/_CP14/LocalizationHelper/last_launch

View File

@@ -1,4 +0,0 @@
{
"omnisharp.analyzeOpenDocumentsOnly": true,
"dotnet.defaultSolution": "SpaceStation14.sln"
}

View File

@@ -12,11 +12,18 @@ namespace Content.Client.Access.UI;
[GenerateTypedNameReferences]
public sealed partial class AccessLevelControl : GridContainer
{
[Dependency] private readonly ILogManager _logManager = default!;
private ISawmill _sawmill = default!;
public readonly Dictionary<ProtoId<AccessLevelPrototype>, Button> ButtonsList = new();
public AccessLevelControl()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_sawmill = _logManager.GetSawmill("accesslevelcontrol");
}
public void Populate(List<ProtoId<AccessLevelPrototype>> accessLevels, IPrototypeManager prototypeManager)
@@ -25,7 +32,7 @@ public sealed partial class AccessLevelControl : GridContainer
{
if (!prototypeManager.TryIndex(access, out var accessLevel))
{
Logger.Error($"Unable to find accesslevel for {access}");
_sawmill.Error($"Unable to find accesslevel for {access}");
continue;
}

View File

@@ -1,4 +1,4 @@
using Content.Client.Stylesheets;
using Content.Client.Stylesheets;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -77,9 +77,12 @@ namespace Content.Client.Actions.UI
MaxWidth = TooltipTextMaxWidth,
StyleClasses = {StyleNano.StyleClassTooltipActionRequirements}
};
requiresLabel.SetMessage(FormattedMessage.FromMarkup("[color=#635c5c]" +
requires +
"[/color]"));
if (!FormattedMessage.TryFromMarkup("[color=#635c5c]" + requires + "[/color]", out var markup))
return;
requiresLabel.SetMessage(markup);
vbox.AddChild(requiresLabel);
}
}
@@ -97,8 +100,11 @@ namespace Content.Client.Actions.UI
if (timeLeft > TimeSpan.Zero)
{
var duration = Cooldown.Value.End - Cooldown.Value.Start;
_cooldownLabel.SetMessage(FormattedMessage.FromMarkup(
$"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]"));
if (!FormattedMessage.TryFromMarkup($"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]", out var markup))
return;
_cooldownLabel.SetMessage(markup);
_cooldownLabel.Visible = true;
}
else

View File

@@ -3,38 +3,57 @@ using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI
namespace Content.Client.Administration.UI;
[GenerateTypedNameReferences]
public sealed partial class AdminMenuWindow : DefaultWindow
{
[GenerateTypedNameReferences]
public sealed partial class AdminMenuWindow : DefaultWindow
public event Action? OnDisposed;
public AdminMenuWindow()
{
public event Action? OnDisposed;
MinSize = new Vector2(650, 250);
Title = Loc.GetString("admin-menu-title");
RobustXamlLoader.Load(this);
MasterTabContainer.SetTabTitle((int) TabIndex.Admin, Loc.GetString("admin-menu-admin-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Adminbus, Loc.GetString("admin-menu-adminbus-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Atmos, Loc.GetString("admin-menu-atmos-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Round, Loc.GetString("admin-menu-round-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Server, Loc.GetString("admin-menu-server-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.PanicBunker, Loc.GetString("admin-menu-panic-bunker-tab"));
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
MasterTabContainer.SetTabTitle((int) TabIndex.BabyJail, Loc.GetString("admin-menu-baby-jail-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Players, Loc.GetString("admin-menu-players-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Objects, Loc.GetString("admin-menu-objects-tab"));
MasterTabContainer.OnTabChanged += OnTabChanged;
}
public AdminMenuWindow()
{
MinSize = new Vector2(650, 250);
Title = Loc.GetString("admin-menu-title");
RobustXamlLoader.Load(this);
MasterTabContainer.SetTabTitle(0, Loc.GetString("admin-menu-admin-tab"));
MasterTabContainer.SetTabTitle(1, Loc.GetString("admin-menu-adminbus-tab"));
MasterTabContainer.SetTabTitle(2, Loc.GetString("admin-menu-atmos-tab"));
MasterTabContainer.SetTabTitle(3, Loc.GetString("admin-menu-round-tab"));
MasterTabContainer.SetTabTitle(4, Loc.GetString("admin-menu-server-tab"));
MasterTabContainer.SetTabTitle(5, Loc.GetString("admin-menu-panic-bunker-tab"));
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
MasterTabContainer.SetTabTitle(6, Loc.GetString("admin-menu-baby-jail-tab"));
MasterTabContainer.SetTabTitle(7, Loc.GetString("admin-menu-players-tab"));
MasterTabContainer.SetTabTitle(8, Loc.GetString("admin-menu-objects-tab"));
}
private void OnTabChanged(int tabIndex)
{
var tabEnum = (TabIndex)tabIndex;
if (tabEnum == TabIndex.Objects)
ObjectsTabControl.RefreshObjectList();
}
protected override void Dispose(bool disposing)
{
OnDisposed?.Invoke();
base.Dispose(disposing);
OnDisposed = null;
}
protected override void Dispose(bool disposing)
{
OnDisposed?.Invoke();
base.Dispose(disposing);
OnDisposed = null;
}
private enum TabIndex
{
Admin = 0,
Adminbus,
Atmos,
Round,
Server,
PanicBunker,
BabyJail,
Players,
Objects,
}
}

View File

@@ -5,7 +5,7 @@
<LineEdit Name="FilterLineEdit"
MinSize="100 0"
HorizontalExpand="True"
PlaceHolder="{Loc Filter}"/>
PlaceHolder="{Loc player-list-filter}"/>
<PanelContainer Name="BackgroundPanel"
VerticalExpand="True"
HorizontalExpand="True">

View File

@@ -1,10 +1,10 @@
<Popup xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client">
<PanelContainer StyleClasses="BackgroundDark">
<PanelContainer>
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BorderThickness="1" BorderColor="#18181B"/>
<gfx:StyleBoxFlat BorderThickness="2" BorderColor="#18181B" BackgroundColor="#25252a"/>
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Vertical" Margin="4 4 4 4">
<Label Name="PlayerNameLabel"/>
<Label Name="IdLabel"/>
<Label Name="TypeLabel"/>

View File

@@ -4,7 +4,7 @@
Title="{Loc admin-player-actions-window-title}" MinSize="425 272">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Reason}" MinWidth="100" />
<Label Text="{Loc admin-player-actions-reason}" MinWidth="100" />
<Control MinWidth="50" />
<LineEdit Name="ReasonLine" MinWidth="100" HorizontalExpand="True" />
</BoxContainer>

View File

@@ -1,9 +1,9 @@
<DefaultWindow
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc Teleport}" MinSize="425 230">
Title="{Loc admin-ui-teleport}" MinSize="425 230">
<BoxContainer Orientation="Vertical">
<cc:PlayerListControl Name="PlayerList" />
<Button Name="SubmitButton" Text="{Loc Teleport}" />
<Button Name="SubmitButton" Text="{Loc admin-ui-teleport}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -1,33 +1,33 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc Load Blueprint}">
xmlns="https://spacestation14.io" Title="{Loc admin-ui-blueprint-load}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Map}" MinSize="100 0" />
<Label Text="{Loc admin-ui-blueprint-map}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="MapOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Path}" MinSize="100 0" />
<Label Text="{Loc admin-ui-blueprint-path}" MinSize="100 0" />
<Control MinSize="50 0" />
<LineEdit Name="MapPath" MinSize="200 0" HorizontalExpand="True" Text="/Maps/" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc X}" MinSize="100 0" />
<Label Text="{Loc admin-ui-blueprint-x}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="XCoordinate" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Y}" MinSize="100 0" />
<Label Text="{Loc admin-ui-blueprint-y}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="YCoordinate" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Rotation}" MinSize="100 0" />
<Label Text="{Loc admin-ui-blueprint-rotation}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="RotationSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc Load Blueprint}" />
<Button Name="TeleportButton" Text="{Loc Teleport to}" />
<Button Name="ResetButton" Text="{Loc Reset to default}"></Button>
<Button Name="SubmitButton" Text="{Loc admin-ui-blueprint-load}" />
<Button Name="TeleportButton" Text="{Loc admin-ui-blueprint-teleport}" />
<Button Name="ResetButton" Text="{Loc admin-ui-blueprint-reset}"></Button>
</BoxContainer>
</DefaultWindow>

View File

@@ -1,11 +1,11 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc Add Atmos}">
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-add}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc Add Atmos}" />
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-add}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -35,7 +35,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
while (query.MoveNext(out var uid, out var grid))
{
_data.Add((uid, grid));
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString($"admin-ui-atmos-grid-current") : "")}");
}
GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id);

View File

@@ -1,31 +1,31 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc Add Gas}">
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-add-gas}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileX}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-tile-x}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileY}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-tile-y}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Gas}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-gas}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Amount}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-gas-amount}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc Add Gas}" />
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-add-gas}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -33,7 +33,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
_gridData.Add(entManager.GetNetEntity(uid));
var player = playerManager.LocalEntity;
var playerGrid = entManager.GetComponentOrNull<TransformComponent>(player)?.GridUid;
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString("admin-ui-atmos-grid-current") : "")}");
}
GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id);

View File

@@ -6,10 +6,10 @@
Margin="4"
MinSize="50 50">
<GridContainer Columns="4">
<cc:UICommandButton Text="{Loc Add Atmos}" Command="addatmos" WindowType="{x:Type at:AddAtmosWindow}" />
<cc:UICommandButton Text="{Loc Add Gas}" Command="addgas" WindowType="{x:Type at:AddGasWindow}" />
<cc:UICommandButton Text="{Loc Fill Gas}" Command="fillgas" WindowType="{x:Type at:FillGasWindow}" />
<cc:UICommandButton Text="{Loc Set Temperature}" Command="settemp"
<cc:UICommandButton Text="{Loc admin-ui-atmos-add}" Command="addatmos" WindowType="{x:Type at:AddAtmosWindow}" />
<cc:UICommandButton Text="{Loc admin-ui-atmos-add-gas}" Command="addgas" WindowType="{x:Type at:AddGasWindow}" />
<cc:UICommandButton Text="{Loc admin-ui-atmos-fill-gas}" Command="fillgas" WindowType="{x:Type at:FillGasWindow}" />
<cc:UICommandButton Text="{Loc admin-ui-atmos-set-temperature}" Command="settemp"
WindowType="{x:Type at:SetTemperatureWindow}" />
</GridContainer>
</Control>

View File

@@ -1,21 +1,21 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc Fill Gas}">
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-fill-gas}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Gas}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-gas}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Amount}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-gas-amount}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc Fill Gas}" />
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-fill-gas}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -36,7 +36,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
{
var player = playerManager.LocalEntity;
var playerGrid = entManager.GetComponentOrNull<TransformComponent>(player)?.GridUid;
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString($"admin-ui-atmos-grid-current") : "")}");
_gridData.Add(entManager.GetNetEntity(uid));
}

View File

@@ -1,26 +1,26 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc Set Temperature}">
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-set-temperature}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Grid}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileX}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-tile-x}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc TileY}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-tile-y}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc Temperature}" MinSize="100 0" />
<Label Text="{Loc admin-ui-atmos-temperature}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TemperatureSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc Set Temperature}" />
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-set-temperature}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -32,7 +32,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
{
var player = playerManager.LocalEntity;
var playerGrid = entManager.GetComponentOrNull<TransformComponent>(player)?.GridUid;
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString($"admin-ui-atmos-grid-current") : "")}");
_data.Add(entManager.GetNetEntity(uid));
}

View File

@@ -4,18 +4,17 @@
xmlns:co="clr-namespace:Content.Client.UserInterface.Controls">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label HorizontalExpand="True" SizeFlagsStretchRatio="0.50"
Text="{Loc Object type:}" />
<LineEdit Name="SearchLineEdit" PlaceHolder="{Loc Search...}" HorizontalExpand="True" SizeFlagsStretchRatio="1"/>
<OptionButton Name="ObjectTypeOptions" HorizontalExpand="True" SizeFlagsStretchRatio="0.25"/>
<Label Text="{Loc object-tab-object-type}" />
<OptionButton Name="ObjectTypeOptions" HorizontalAlignment="Left" />
<LineEdit Name="SearchLineEdit" PlaceHolder="{Loc object-tab-object-search}" HorizontalExpand="True"
SizeFlagsStretchRatio="1" />
<Button Name="RefreshListButton" Text="{Loc object-tab-refresh-button}" ToggleMode="False" />
</BoxContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
</BoxContainer>
<cc:HSeparator/>
<cc:HSeparator />
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<ot:ObjectsTabHeader Name="ListHeader"/>
<cc:HSeparator/>
<co:SearchListContainer Name="SearchList" Access="Public" VerticalExpand="True"/>
<ot:ObjectsTabHeader Name="ListHeader" />
<cc:HSeparator />
<co:SearchListContainer Name="SearchList" Access="Public" VerticalExpand="True" />
</BoxContainer>
</BoxContainer>
</Control>

View File

@@ -3,6 +3,7 @@ using Content.Client.UserInterface.Controls;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
@@ -15,17 +16,14 @@ public sealed partial class ObjectsTab : Control
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly List<ObjectsTabEntry> _objects = new();
private readonly List<ObjectsTabSelection> _selections = new();
private bool _ascending = false; // Set to false for descending order by default
private ObjectsTabHeader.Header _headerClicked = ObjectsTabHeader.Header.ObjectName;
private readonly Color _altColor = Color.FromHex("#292B38");
private readonly Color _defaultColor = Color.FromHex("#2F2F3B");
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
private bool _ascending;
private ObjectsTabHeader.Header _headerClicked = ObjectsTabHeader.Header.ObjectName;
private readonly TimeSpan _updateFrequency = TimeSpan.FromSeconds(2);
private TimeSpan _nextUpdate;
private readonly List<ObjectsTabSelection> _selections = [];
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
public ObjectsTab()
{
@@ -38,40 +36,25 @@ public sealed partial class ObjectsTab : Control
RefreshObjectList(_selections[ev.Id]);
};
foreach (var type in Enum.GetValues(typeof(ObjectsTabSelection)))
foreach (var type in Enum.GetValues<ObjectsTabSelection>())
{
_selections.Add((ObjectsTabSelection)type!);
ObjectTypeOptions.AddItem(Enum.GetName((ObjectsTabSelection)type)!);
_selections.Add(type);
ObjectTypeOptions.AddItem(GetLocalizedEnumValue(type));
}
ListHeader.OnHeaderClicked += HeaderClicked;
SearchList.SearchBar = SearchLineEdit;
SearchList.GenerateItem += GenerateButton;
SearchList.DataFilterCondition += DataFilterCondition;
SearchList.ItemKeyBindDown += (args, data) => OnEntryKeyBindDown?.Invoke(args, data);
RefreshListButton.OnPressed += _ => RefreshObjectList();
RefreshObjectList();
// Set initial selection and refresh the list to apply the initial sort order
var defaultSelection = ObjectsTabSelection.Grids;
ObjectTypeOptions.SelectId((int)defaultSelection); // Set the default selection
RefreshObjectList(defaultSelection); // Refresh the list with the default selection
// Initialize the next update time
_nextUpdate = TimeSpan.Zero;
ObjectTypeOptions.SelectId((int) defaultSelection);
RefreshObjectList(defaultSelection);
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (_timing.CurTime < _nextUpdate)
return;
_nextUpdate = _timing.CurTime + _updateFrequency;
RefreshObjectList();
}
private void RefreshObjectList()
public void RefreshObjectList()
{
RefreshObjectList(_selections[ObjectTypeOptions.SelectedId]);
}
@@ -101,6 +84,7 @@ public sealed partial class ObjectsTab : Control
{
entities.Add((metadata.EntityName, _entityManager.GetNetEntity(uid)));
}
break;
}
default:
@@ -111,14 +95,18 @@ public sealed partial class ObjectsTab : Control
{
var valueA = GetComparableValue(a, _headerClicked);
var valueB = GetComparableValue(b, _headerClicked);
return _ascending ? Comparer<object>.Default.Compare(valueA, valueB) : Comparer<object>.Default.Compare(valueB, valueA);
return _ascending
? Comparer<object>.Default.Compare(valueA, valueB)
: Comparer<object>.Default.Compare(valueB, valueA);
});
var listData = new List<ObjectsListData>();
for (int index = 0; index < entities.Count; index++)
for (var index = 0; index < entities.Count; index++)
{
var info = entities[index];
listData.Add(new ObjectsListData(info, $"{info.Name} {info.Entity}", index % 2 == 0 ? _altColor : _defaultColor));
listData.Add(new ObjectsListData(info,
$"{info.Name} {info.Entity}",
index % 2 == 0 ? _altColor : _defaultColor));
}
SearchList.PopulateList(listData);
@@ -129,10 +117,11 @@ public sealed partial class ObjectsTab : Control
if (data is not ObjectsListData { Info: var info, BackgroundColor: var backgroundColor })
return;
var entry = new ObjectsTabEntry(info.Name, info.Entity, new StyleBoxFlat { BackgroundColor = backgroundColor });
var entry = new ObjectsTabEntry(info.Name,
info.Entity,
new StyleBoxFlat { BackgroundColor = backgroundColor });
button.ToolTip = $"{info.Name}, {info.Entity}";
button.OnKeyBindDown += args => OnEntryKeyBindDown?.Invoke(args, data);
button.AddChild(entry);
}
@@ -154,7 +143,7 @@ public sealed partial class ObjectsTab : Control
{
ObjectsTabHeader.Header.ObjectName => entity.Name,
ObjectsTabHeader.Header.EntityID => entity.Entity.ToString(),
_ => entity.Name
_ => entity.Name,
};
}
@@ -174,6 +163,17 @@ public sealed partial class ObjectsTab : Control
RefreshObjectList();
}
private string GetLocalizedEnumValue(ObjectsTabSelection selection)
{
return selection switch
{
ObjectsTabSelection.Grids => Loc.GetString("object-tab-object-type-grids"),
ObjectsTabSelection.Maps => Loc.GetString("object-tab-object-type-maps"),
ObjectsTabSelection.Stations => Loc.GetString("object-tab-object-type-stations"),
_ => throw new ArgumentOutOfRangeException(nameof(selection), selection, null),
};
}
private enum ObjectsTabSelection
{
Grids,
@@ -182,4 +182,5 @@ public sealed partial class ObjectsTab : Control
}
}
public record ObjectsListData((string Name, NetEntity Entity) Info, string FilteringString, Color BackgroundColor) : ListData;
public record ObjectsListData((string Name, NetEntity Entity) Info, string FilteringString, Color BackgroundColor)
: ListData;

View File

@@ -4,7 +4,7 @@
xmlns:co="clr-namespace:Content.Client.UserInterface.Controls">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Name="PlayerCount" HorizontalExpand="True" Text="{Loc Player Count}" />
<Label Name="PlayerCount" HorizontalExpand="True" Text="{Loc player-tab-player-count}" />
<LineEdit Name="SearchLineEdit" HorizontalExpand="True"
PlaceHolder="{Loc player-tab-filter-line-edit-placeholder}" />
<Button Name="ShowDisconnectedButton" HorizontalExpand="True"

View File

@@ -109,7 +109,7 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
{
_players = players;
PlayerCount.Text = $"Players: {_playerMan.PlayerCount}";
PlayerCount.Text = Loc.GetString("player-tab-player-count", ("count", _playerMan.PlayerCount));
var filteredPlayers = players.Where(info => _showDisconnected || info.Connected).ToList();

View File

@@ -5,9 +5,9 @@
MinSize="50 50">
<GridContainer
Columns="3">
<cc:CommandButton Command="startround" Text="{Loc Start Round}" />
<cc:CommandButton Command="endround" Text="{Loc End Round}" />
<cc:CommandButton Command="restartround" Text="{Loc Restart Round}" />
<cc:CommandButton Command="startround" Text="{Loc administration-ui-round-tab-start-round}" />
<cc:CommandButton Command="endround" Text="{Loc administration-ui-round-tab-end-round}" />
<cc:CommandButton Command="restartround" Text="{Loc administration-ui-round-tab-restart-round}" />
<cc:CommandButton Command="restartroundnow" Text="{Loc administration-ui-round-tab-restart-round-now}" />
</GridContainer>
</Control>

View File

@@ -54,7 +54,7 @@ public sealed class AudioUIController : UIController
{
if (!string.IsNullOrEmpty(value))
{
var resource = _cache.GetResource<AudioResource>(value);
var resource = GetSoundOrFallback(value, CCVars.UIClickSound.DefaultValue);
var source =
_audioManager.CreateAudioSource(resource);
@@ -77,7 +77,7 @@ public sealed class AudioUIController : UIController
{
if (!string.IsNullOrEmpty(value))
{
var hoverResource = _cache.GetResource<AudioResource>(value);
var hoverResource = GetSoundOrFallback(value, CCVars.UIHoverSound.DefaultValue);
var hoverSource =
_audioManager.CreateAudioSource(hoverResource);
@@ -95,4 +95,12 @@ public sealed class AudioUIController : UIController
UIManager.SetHoverSound(null);
}
}
private AudioResource GetSoundOrFallback(string path, string fallback)
{
if (!_cache.TryGetResource(path, out AudioResource? resource))
return _cache.GetResource<AudioResource>(fallback);
return resource;
}
}

View File

@@ -4,6 +4,7 @@ using Content.Shared.Audio;
using Content.Shared.CCVar;
using Content.Shared.GameTicking;
using Content.Shared.Random;
using Content.Shared.Random.Rules;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.ResourceManagement;
@@ -116,6 +117,7 @@ public sealed partial class ContentAudioSystem
private void OnRoundEndMessage(RoundEndMessageEvent ev)
{
OnRoundEndMessageAmbientLoop(); //CP14
// If scoreboard shows then just stop the music
_ambientMusicStream = _audio.Stop(_ambientMusicStream);
_nextAudio = TimeSpan.FromMinutes(3);

View File

@@ -0,0 +1,122 @@
using System.Linq;
using Content.Client.Gameplay;
using Content.Shared.Audio;
using Content.Shared.CCVar;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
namespace Content.Client.Audio;
public sealed partial class ContentAudioSystem
{
private const float AmbientLoopFadeInTime = 1f;
private const float AmbientLoopFadeOutTime = 4f;
private Dictionary<CP14AmbientLoopPrototype, EntityUid> _loopStreams = new();
private TimeSpan _nextUpdateTime = TimeSpan.Zero;
private readonly TimeSpan _updateFrequency = TimeSpan.FromSeconds(1f);
private void CP14InitializeAmbientLoops()
{
Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChangedAmbientMusic, true);
}
private void AmbienceCVarChangedAmbientMusic(float obj)
{
_volumeSlider = SharedAudioSystem.GainToVolume(obj);
foreach (var loop in _loopStreams)
{
_audio.SetVolume(loop.Value, loop.Key.Sound.Params.Volume + _volumeSlider);
}
}
private void OnRoundEndMessageAmbientLoop()
{
foreach (var loop in _loopStreams)
{
StopAmbientLoop(loop.Key);
}
}
private void CP14UpdateAmbientLoops()
{
if (_timing.CurTime <= _nextUpdateTime)
return;
_nextUpdateTime = _timing.CurTime + _updateFrequency;
if (_state.CurrentState is not GameplayState)
return;
var requiredLoops = GetAmbientLoops();
foreach (var loop in _loopStreams)
{
if (!requiredLoops.Contains(loop.Key)) //If ambient is playing and it shouldn't, stop it.
StopAmbientLoop(loop.Key);
}
foreach (var loop in requiredLoops)
{
if (!_loopStreams.ContainsKey(loop)) //If it's not playing, but should, run it
StartAmbientLoop(loop);
}
}
private void StartAmbientLoop(CP14AmbientLoopPrototype proto)
{
if (_loopStreams.ContainsKey(proto))
return;
var newLoop = _audio.PlayGlobal(
proto.Sound,
Filter.Local(),
false,
AudioParams.Default
.WithLoop(true)
.WithVolume(proto.Sound.Params.Volume + _volumeSlider)
.WithPlayOffset(_random.NextFloat(0f, 100f)));
_loopStreams.Add(proto, newLoop.Value.Entity);
FadeIn(newLoop.Value.Entity, newLoop.Value.Component, AmbientLoopFadeInTime);
}
private void StopAmbientLoop(CP14AmbientLoopPrototype proto)
{
if (!_loopStreams.TryGetValue(proto, out var audioEntity))
return;
FadeOut(audioEntity, duration: AmbientLoopFadeOutTime);
_loopStreams.Remove(proto);
}
/// <summary>
/// Checks the player's environment, and returns a list of all ambients that should currently be playing around the player
/// </summary>
/// <returns></returns>
private List<CP14AmbientLoopPrototype> GetAmbientLoops()
{
List<CP14AmbientLoopPrototype> list = new();
var player = _player.LocalEntity;
if (player == null)
return list;
var ambientLoops = _proto.EnumeratePrototypes<CP14AmbientLoopPrototype>().ToList();
foreach (var loop in ambientLoops)
{
if (_rules.IsTrue(player.Value, _proto.Index(loop.Rules)))
{
list.Add(loop);
}
}
return list;
}
}

View File

@@ -29,13 +29,14 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem
public const float AmbientMusicMultiplier = 3f;
public const float LobbyMultiplier = 3f;
public const float InterfaceMultiplier = 2f;
public override void Initialize()
{
base.Initialize();
UpdatesOutsidePrediction = true;
InitializeAmbientMusic();
CP14InitializeAmbientLoops(); //CP14 ambient loops
InitializeLobbyMusic();
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundCleanup);
}
@@ -82,6 +83,7 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem
return;
UpdateAmbientMusic();
CP14UpdateAmbientLoops(); //CP14
UpdateLobbyMusic();
UpdateFades(frameTime);
}

View File

@@ -1,3 +1,4 @@
using Content.Client.BarSign.Ui;
using Content.Shared.BarSign;
using Content.Shared.Power;
using Robust.Client.GameObjects;
@@ -8,6 +9,7 @@ namespace Content.Client.BarSign;
public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
public override void Initialize()
{
@@ -17,6 +19,9 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
private void OnAfterAutoHandleState(EntityUid uid, BarSignComponent component, ref AfterAutoHandleStateEvent args)
{
if (_ui.TryGetOpenUi<BarSignBoundUserInterface>(uid, BarSignUiKey.Key, out var bui))
bui.Update(component.Current);
UpdateAppearance(uid, component);
}
@@ -34,9 +39,9 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
if (powered
&& sign.Current != null
&& _prototypeManager.TryIndex(sign.Current, out BarSignPrototype? proto))
&& _prototypeManager.TryIndex(sign.Current, out var proto))
{
sprite.LayerSetState(0, proto.Icon);
sprite.LayerSetSprite(0, proto.Icon);
sprite.LayerSetShader(0, "unshaded");
}
else

View File

@@ -0,0 +1,50 @@
using System.Linq;
using Content.Shared.BarSign;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
namespace Content.Client.BarSign.Ui;
[UsedImplicitly]
public sealed class BarSignBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
private BarSignMenu? _menu;
protected override void Open()
{
base.Open();
var sign = EntMan.GetComponentOrNull<BarSignComponent>(Owner)?.Current is { } current
? _prototype.Index(current)
: null;
var allSigns = Shared.BarSign.BarSignSystem.GetAllBarSigns(_prototype)
.OrderBy(p => Loc.GetString(p.Name))
.ToList();
_menu = new(sign, allSigns);
_menu.OnSignSelected += id =>
{
SendMessage(new SetBarSignMessage(id));
};
_menu.OnClose += Close;
_menu.OpenCentered();
}
public void Update(ProtoId<BarSignPrototype>? sign)
{
if (_prototype.TryIndex(sign, out var signPrototype))
_menu?.UpdateState(signPrototype);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}

View File

@@ -0,0 +1,19 @@
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'barsign-ui-menu'}"
MinSize="280 180"
SetSize="280 180">
<BoxContainer VerticalExpand="True" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 5 10 10">
<BoxContainer Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center">
<Label Text="{Loc 'barsign-ui-set-label'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="30 0"/>
<customControls:HSeparator Margin="0 0 0 5"/>
</BoxContainer>
<OptionButton Name="SignOptions" HorizontalAlignment="Center" VerticalAlignment="Center" MinSize="175 60" Margin="0 0 0 20"/>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,50 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.BarSign;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.BarSign.Ui;
[GenerateTypedNameReferences]
public sealed partial class BarSignMenu : FancyWindow
{
private string? _currentId;
private readonly List<BarSignPrototype> _cachedPrototypes = new();
public event Action<string>? OnSignSelected;
public BarSignMenu(BarSignPrototype? currentSign, List<BarSignPrototype> signs)
{
RobustXamlLoader.Load(this);
_currentId = currentSign?.ID;
_cachedPrototypes.Clear();
_cachedPrototypes = signs;
foreach (var proto in _cachedPrototypes)
{
SignOptions.AddItem(Loc.GetString(proto.Name));
}
SignOptions.OnItemSelected += idx =>
{
OnSignSelected?.Invoke(_cachedPrototypes[idx.Id].ID);
SignOptions.SelectId(idx.Id);
};
if (currentSign != null)
{
var idx = _cachedPrototypes.IndexOf(currentSign);
SignOptions.TrySelectId(idx);
}
}
public void UpdateState(BarSignPrototype newSign)
{
if (_currentId != null && newSign.ID == _currentId)
return;
_currentId = newSign.ID;
var idx = _cachedPrototypes.IndexOf(newSign);
SignOptions.TrySelectId(idx);
}
}

View File

@@ -65,14 +65,13 @@ public sealed class TypingIndicatorSystem : SharedTypingIndicatorSystem
{
if (_isClientTyping == isClientTyping)
return;
_isClientTyping = isClientTyping;
// check if player controls any pawn
// check if player controls any entity.
if (_playerManager.LocalEntity == null)
return;
// send a networked event to server
RaiseNetworkEvent(new TypingChangedEvent(isClientTyping));
_isClientTyping = isClientTyping;
RaisePredictiveEvent(new TypingChangedEvent(isClientTyping));
}
private void OnShowTypingChanged(bool showTyping)

View File

@@ -2,21 +2,36 @@
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;
using Content.Shared.Inventory;
namespace Content.Client.Chat.TypingIndicator;
public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem<TypingIndicatorComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
protected override void OnAppearanceChange(EntityUid uid, TypingIndicatorComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
if (!_prototypeManager.TryIndex<TypingIndicatorPrototype>(component.Prototype, out var proto))
var currentTypingIndicator = component.TypingIndicatorPrototype;
var evt = new BeforeShowTypingIndicatorEvent();
if (TryComp<InventoryComponent>(uid, out var inventoryComp))
_inventory.RelayEvent((uid, inventoryComp), ref evt);
var overrideIndicator = evt.GetMostRecentIndicator();
if (overrideIndicator != null)
currentTypingIndicator = overrideIndicator.Value;
if (!_prototypeManager.TryIndex(currentTypingIndicator, out var proto))
{
Log.Error($"Unknown typing indicator id: {component.Prototype}");
Log.Error($"Unknown typing indicator id: {component.TypingIndicatorPrototype}");
return;
}

View File

@@ -48,7 +48,7 @@ namespace Content.Client.Clickable
Angle cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero;
// First we get `localPos`, the clicked location in the sprite-coordinate frame.
var entityXform = Matrix3Helpers.CreateInverseTransform(transform.WorldPosition, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var entityXform = Matrix3Helpers.CreateInverseTransform(spritePos, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var localPos = Vector2.Transform(Vector2.Transform(worldPos, entityXform), invSpriteMatrix);
// Check explicitly defined click-able bounds
@@ -58,8 +58,11 @@ namespace Content.Client.Clickable
// Next check each individual sprite layer using automatically computed click maps.
foreach (var spriteLayer in sprite.AllLayers)
{
if (!spriteLayer.Visible || spriteLayer is not Layer layer)
// TODO: Move this to a system and also use SpriteSystem.IsVisible instead.
if (!spriteLayer.Visible || spriteLayer is not Layer layer || layer.CopyToShaderParameters != null)
{
continue;
}
// Check the layer's texture, if it has one
if (layer.Texture != null)

View File

@@ -0,0 +1,26 @@
using Content.Shared.Clock;
using Robust.Client.GameObjects;
namespace Content.Client.Clock;
public sealed class ClockSystem : SharedClockSystem
{
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<ClockComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out var comp, out var sprite))
{
if (!sprite.LayerMapTryGet(ClockVisualLayers.HourHand, out var hourLayer) ||
!sprite.LayerMapTryGet(ClockVisualLayers.MinuteHand, out var minuteLayer))
continue;
var time = GetClockTime((uid, comp));
var hourState = $"{comp.HoursBase}{time.Hours % 12}";
var minuteState = $"{comp.MinutesBase}{time.Minutes / 5}";
sprite.LayerSetState(hourLayer, hourState);
sprite.LayerSetState(minuteLayer, minuteState);
}
}
}

View File

@@ -331,7 +331,19 @@ public sealed class ClientClothingSystem : ClothingSystem
continue;
}
var displacementLayer = _serialization.CreateCopy(displacementData.Layer, notNullableOverride: true);
//CP14 48*48 displacement maps support
var displacementDataLayer = displacementData.Layer;
var actualRSI = sprite.LayerGetActualRSI(index);
if (actualRSI != null)
{
var layerSize = actualRSI.Size;
if (layerSize.X == 48 && displacementData.Layer48 != null)
displacementDataLayer = displacementData.Layer48;
}
var displacementLayer = _serialization.CreateCopy(displacementDataLayer, notNullableOverride: true);
//CP14 48*48 displacement maps support end
displacementLayer.CopyToShaderParameters!.LayerKey = key;
// Add before main layer for this item.

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using System.Numerics;
using Content.Client.Clothing.Systems;
using Content.Client.Stylesheets;
@@ -74,13 +74,9 @@ public sealed partial class ChameleonMenu : DefaultWindow
};
button.OnPressed += _ => OnIdSelected?.Invoke(id);
Grid.AddChild(button);
var texture = _sprite.GetPrototypeIcon(proto);
button.AddChild(new TextureRect
{
Stretch = TextureRect.StretchMode.KeepAspectCentered,
Texture = texture.Default
});
var entityPrototypeView = new EntityPrototypeView();
button.AddChild(entityPrototypeView);
entityPrototypeView.SetPrototype(proto);
}
}

View File

@@ -20,7 +20,7 @@ public sealed class ZoomCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
Vector2 zoom;
if (args.Length is not (1 or 2))
if (args.Length is not (1 or 2 or 3))
{
shell.WriteLine(Help);
return;
@@ -57,11 +57,18 @@ public sealed class ZoomCommand : LocalizedCommands
}
}
var scalePvs = true;
if (args.Length == 3 && !bool.TryParse(args[2], out scalePvs))
{
shell.WriteError(LocalizationManager.GetString("cmd-parse-failure-bool", ("arg", args[2])));
return;
}
var player = _playerManager.LocalSession?.AttachedEntity;
if (_entityManager.TryGetComponent<ContentEyeComponent>(player, out var content))
{
_entityManager.System<ContentEyeSystem>().RequestZoom(player.Value, zoom, true, content);
_entityManager.System<ContentEyeSystem>().RequestZoom(player.Value, zoom, true, scalePvs, content);
return;
}

View File

@@ -113,7 +113,9 @@ namespace Content.Client.Communications.UI
}
EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-recall-shuttle");
CountdownLabel.SetMessage($"Time remaining\n{Owner.Countdown.ToString()}s");
var infoText = Loc.GetString($"comms-console-menu-time-remaining",
("time", Owner.Countdown.ToString()));
CountdownLabel.SetMessage(infoText);
}
public override void Close()

View File

@@ -48,11 +48,11 @@ namespace Content.Client.Construction
CommandBinds.Builder
.Bind(ContentKeyFunctions.OpenCraftingMenu,
new PointerInputCmdHandler(HandleOpenCraftingMenu, outsidePrediction:true))
new PointerInputCmdHandler(HandleOpenCraftingMenu, outsidePrediction: true))
.Bind(EngineKeyFunctions.Use,
new PointerInputCmdHandler(HandleUse, outsidePrediction: true))
.Bind(ContentKeyFunctions.EditorFlipObject,
new PointerInputCmdHandler(HandleFlip, outsidePrediction:true))
new PointerInputCmdHandler(HandleFlip, outsidePrediction: true))
.Register<ConstructionSystem>();
SubscribeLocalEvent<ConstructionGhostComponent, ExaminedEvent>(HandleConstructionGhostExamined);
@@ -196,7 +196,7 @@ namespace Content.Client.Construction
if (GhostPresent(loc))
return false;
var predicate = GetPredicate(prototype.CanBuildInImpassable, loc.ToMap(EntityManager, _transformSystem));
var predicate = GetPredicate(prototype.CanBuildInImpassable, _transformSystem.ToMapCoordinates(loc));
if (!_examineSystem.InRangeUnOccluded(user, loc, 20f, predicate: predicate))
return false;

View File

@@ -1,29 +1,33 @@
<DefaultWindow xmlns="https://spacestation14.io">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4" Margin="0 0 5 0">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 0 0 5">
<LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/>
<OptionButton Name="Category" Access="Public" MinSize="130 0"/>
<OptionButton Name="OptionCategories" Access="Public" MinSize="130 0"/>
</BoxContainer>
<ItemList Name="Recipes" Access="Public" SelectMode="Single" VerticalExpand="True"/>
</BoxContainer>
<Control MinSize="10 0"/>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.6">
<Button Name="FavoriteButton" Visible="false" HorizontalExpand="False"
HorizontalAlignment="Right" Margin="0 0 0 15"/>
<Control>
<BoxContainer Orientation="Horizontal" Align="Center">
<TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep"/>
<Control MinSize="10 0"/>
<BoxContainer Orientation="Vertical">
<RichTextLabel Name="TargetName"/>
<RichTextLabel Name="TargetDesc"/>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="0 0 0 5">
<BoxContainer Orientation="Horizontal" Align="Center">
<TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep" Margin="0 0 10 0"/>
<BoxContainer Orientation="Vertical">
<RichTextLabel Name="TargetName"/>
<RichTextLabel Name="TargetDesc"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</Control>
<ItemList Name="RecipeStepList" Access="Public" VerticalExpand="True"/>
<ItemList Name="RecipeStepList" Access="Public" VerticalExpand="True" Margin="0 0 0 5"/>
<BoxContainer Orientation="Vertical">
<Button Name="BuildButton" Disabled="True" ToggleMode="True" VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
<Button Name="BuildButton" Disabled="True" ToggleMode="True"
VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
<BoxContainer Orientation="Horizontal" VerticalExpand="True" SizeFlagsStretchRatio="0.5">
<Button Name="EraseButton" ToggleMode="True" HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
<Button Name="EraseButton" ToggleMode="True"
HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
<Button Name="ClearButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3"/>
</BoxContainer>
</BoxContainer>

View File

@@ -22,7 +22,7 @@ namespace Content.Client.Construction.UI
// It isn't optimal to expose UI controls like this, but the UI control design is
// questionable so it can't be helped.
string[] Categories { get; set; }
OptionButton Category { get; }
OptionButton OptionCategories { get; }
bool EraseButtonPressed { get; set; }
bool BuildButtonPressed { get; set; }
@@ -32,12 +32,13 @@ namespace Content.Client.Construction.UI
event EventHandler<(string search, string catagory)> PopulateRecipes;
event EventHandler<ItemList.Item?> RecipeSelected;
event EventHandler RecipeFavorited;
event EventHandler<bool> BuildButtonToggled;
event EventHandler<bool> EraseButtonToggled;
event EventHandler ClearAllGhosts;
void ClearRecipeInfo();
void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem);
void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem, bool isFavorite);
void ResetPlacement();
#region Window Control
@@ -84,10 +85,12 @@ namespace Content.Client.Construction.UI
Recipes.OnItemSelected += obj => RecipeSelected?.Invoke(this, obj.ItemList[obj.ItemIndex]);
Recipes.OnItemDeselected += _ => RecipeSelected?.Invoke(this, null);
SearchBar.OnTextChanged += _ => PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[Category.SelectedId]));
Category.OnItemSelected += obj =>
SearchBar.OnTextChanged += _ =>
PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[OptionCategories.SelectedId]));
OptionCategories.OnItemSelected += obj =>
{
Category.SelectId(obj.Id);
OptionCategories.SelectId(obj.Id);
SearchBar.SetText(string.Empty);
PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[obj.Id]));
};
@@ -97,12 +100,14 @@ namespace Content.Client.Construction.UI
ClearButton.OnPressed += _ => ClearAllGhosts?.Invoke(this, EventArgs.Empty);
EraseButton.Text = Loc.GetString("construction-menu-eraser-mode");
EraseButton.OnToggled += args => EraseButtonToggled?.Invoke(this, args.Pressed);
FavoriteButton.OnPressed += args => RecipeFavorited?.Invoke(this, EventArgs.Empty);
}
public event EventHandler? ClearAllGhosts;
public event EventHandler<(string search, string catagory)>? PopulateRecipes;
public event EventHandler<ItemList.Item?>? RecipeSelected;
public event EventHandler? RecipeFavorited;
public event EventHandler<bool>? BuildButtonToggled;
public event EventHandler<bool>? EraseButtonToggled;
@@ -112,13 +117,17 @@ namespace Content.Client.Construction.UI
EraseButton.Pressed = false;
}
public void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem)
public void SetRecipeInfo(
string name, string description, Texture iconTexture, bool isItem, bool isFavorite)
{
BuildButton.Disabled = false;
BuildButton.Text = Loc.GetString(isItem ? "construction-menu-place-ghost" : "construction-menu-craft");
TargetName.SetMessage(name);
TargetDesc.SetMessage(description);
TargetTexture.Texture = iconTexture;
FavoriteButton.Visible = true;
FavoriteButton.Text = Loc.GetString(
isFavorite ? "construction-add-favorite-button" : "construction-remove-from-favorite-button");
}
public void ClearRecipeInfo()
@@ -127,6 +136,7 @@ namespace Content.Client.Construction.UI
TargetName.SetMessage(string.Empty);
TargetDesc.SetMessage(string.Empty);
TargetTexture.Texture = null;
FavoriteButton.Visible = false;
RecipeStepList.Clear();
}
}

View File

@@ -36,7 +36,10 @@ namespace Content.Client.Construction.UI
private ConstructionSystem? _constructionSystem;
private ConstructionPrototype? _selected;
private List<ConstructionPrototype> _favoritedRecipes = [];
private string _selectedCategory = string.Empty;
private string _favoriteCatName = "construction-category-favorites";
private string _forAllCategoryName = "construction-category-all";
private bool CraftingAvailable
{
get => _uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.Visible;
@@ -65,7 +68,7 @@ namespace Content.Client.Construction.UI
else
_constructionView.OpenCentered();
if(_selected != null)
if (_selected != null)
PopulateInfo(_selected);
}
else
@@ -105,9 +108,10 @@ namespace Content.Client.Construction.UI
_constructionView.EraseButtonPressed = b;
};
_constructionView.RecipeFavorited += (_, _) => OnViewFavoriteRecipe();
PopulateCategories();
OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
}
public void OnHudCraftingButtonToggled(ButtonToggledEventArgs args)
@@ -154,6 +158,13 @@ namespace Content.Client.Construction.UI
recipesList.Clear();
var recipes = new List<ConstructionPrototype>();
var isEmptyCategory = string.IsNullOrEmpty(category) || category == _forAllCategoryName;
if (isEmptyCategory)
_selectedCategory = string.Empty;
else
_selectedCategory = category;
foreach (var recipe in _prototypeManager.EnumeratePrototypes<ConstructionPrototype>())
{
if (recipe.Hide)
@@ -173,10 +184,19 @@ namespace Content.Client.Construction.UI
continue;
}
if (!string.IsNullOrEmpty(category) && category != "construction-category-all")
if (!isEmptyCategory)
{
if (recipe.Category != category)
if (category == _favoriteCatName)
{
if (!_favoritedRecipes.Contains(recipe))
{
continue;
}
}
else if (recipe.Category != category)
{
continue;
}
}
recipes.Add(recipe);
@@ -192,13 +212,10 @@ namespace Content.Client.Construction.UI
// There is apparently no way to set which
}
private void PopulateCategories()
private void PopulateCategories(string? selectCategory = null)
{
var uniqueCategories = new HashSet<string>();
// hard-coded to show all recipes
uniqueCategories.Add("construction-category-all");
foreach (var prototype in _prototypeManager.EnumeratePrototypes<ConstructionPrototype>())
{
var category = prototype.Category;
@@ -207,25 +224,49 @@ namespace Content.Client.Construction.UI
uniqueCategories.Add(category);
}
_constructionView.Category.Clear();
var isFavorites = _favoritedRecipes.Count > 0;
var categoriesArray = new string[isFavorites ? uniqueCategories.Count + 2 : uniqueCategories.Count + 1];
var array = uniqueCategories.OrderBy(Loc.GetString).ToArray();
Array.Sort(array);
// hard-coded to show all recipes
var idx = 0;
categoriesArray[idx++] = _forAllCategoryName;
for (var i = 0; i < array.Length; i++)
// hard-coded to show favorites if it need
if (isFavorites)
{
var category = array[i];
_constructionView.Category.AddItem(Loc.GetString(category), i);
categoriesArray[idx++] = _favoriteCatName;
}
_constructionView.Categories = array;
var sortedProtoCategories = uniqueCategories.OrderBy(Loc.GetString);
foreach (var cat in sortedProtoCategories)
{
categoriesArray[idx++] = cat;
}
_constructionView.OptionCategories.Clear();
for (var i = 0; i < categoriesArray.Length; i++)
{
_constructionView.OptionCategories.AddItem(Loc.GetString(categoriesArray[i]), i);
if (!string.IsNullOrEmpty(selectCategory) && selectCategory == categoriesArray[i])
_constructionView.OptionCategories.SelectId(i);
}
_constructionView.Categories = categoriesArray;
}
private void PopulateInfo(ConstructionPrototype prototype)
{
var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
_constructionView.ClearRecipeInfo();
_constructionView.SetRecipeInfo(prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon), prototype.Type != ConstructionType.Item);
_constructionView.SetRecipeInfo(
prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon),
prototype.Type != ConstructionType.Item,
!_favoritedRecipes.Contains(prototype));
var stepList = _constructionView.RecipeStepList;
GenerateStepList(prototype, stepList);
@@ -243,7 +284,7 @@ namespace Content.Client.Construction.UI
var text = entry.Arguments != null
? Loc.GetString(entry.Localization, entry.Arguments) : Loc.GetString(entry.Localization);
if (entry.EntryNumber is {} number)
if (entry.EntryNumber is { } number)
{
text = Loc.GetString("construction-presenter-step-wrapper",
("step-number", number), ("text", text));
@@ -335,6 +376,26 @@ namespace Content.Client.Construction.UI
if (args.System is ConstructionSystem) SystemBindingChanged(null);
}
private void OnViewFavoriteRecipe()
{
if (_selected is not ConstructionPrototype recipe)
return;
if (!_favoritedRecipes.Remove(_selected))
_favoritedRecipes.Add(_selected);
if (_selectedCategory == _favoriteCatName)
{
if (_favoritedRecipes.Count > 0)
OnViewPopulateRecipes(_constructionView, (string.Empty, _favoriteCatName));
else
OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
}
PopulateInfo(_selected);
PopulateCategories(_selectedCategory);
}
private void SystemBindingChanged(ConstructionSystem? newSystem)
{
if (newSystem is null)

View File

@@ -170,7 +170,7 @@ namespace Content.Client.ContextMenu.UI
if (_combatMode.IsInCombatMode(args.Session?.AttachedEntity))
return false;
var coords = args.Coordinates.ToMap(_entityManager, _xform);
var coords = _xform.ToMapCoordinates(args.Coordinates);
if (_verbSystem.TryGetEntityMenuEntities(coords, out var entities))
OpenRootMenu(entities);

View File

@@ -1,23 +1,28 @@
using Content.Client.Administration.Managers;
using Content.Client.Administration.Managers;
using Content.Shared.CCVar;
using Robust.Client;
using Robust.Client.UserInterface;
using Robust.Shared.Configuration;
namespace Content.Client.DebugMon;
/// <summary>
/// This handles preventing certain debug monitors from appearing.
/// This handles preventing certain debug monitors from being usable by non-admins.
/// </summary>
public sealed class DebugMonitorSystem : EntitySystem
internal sealed class DebugMonitorManager
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IClientAdminManager _admin = default!;
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
[Dependency] private readonly IBaseClient _baseClient = default!;
public override void FrameUpdate(float frameTime)
public void FrameUpdate()
{
if (!_admin.IsActive() && _cfg.GetCVar(CCVars.DebugCoordinatesAdminOnly))
if (_baseClient.RunLevel == ClientRunLevel.InGame
&& !_admin.IsActive()
&& _cfg.GetCVar(CCVars.DebugCoordinatesAdminOnly))
{
_userInterface.DebugMonitors.SetMonitor(DebugMonitor.Coords, false);
}
}
}

View File

@@ -8,6 +8,7 @@ using Robust.Client.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.Containers;
namespace Content.Client.DoAfter;
@@ -19,6 +20,7 @@ public sealed class DoAfterOverlay : Overlay
private readonly SharedTransformSystem _transform;
private readonly MetaDataSystem _meta;
private readonly ProgressColorSystem _progressColor;
private readonly SharedContainerSystem _container;
private readonly Texture _barTexture;
private readonly ShaderInstance _unshadedShader;
@@ -41,6 +43,7 @@ public sealed class DoAfterOverlay : Overlay
_player = player;
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
_meta = _entManager.EntitySysManager.GetEntitySystem<MetaDataSystem>();
_container = _entManager.EntitySysManager.GetEntitySystem<SharedContainerSystem>();
_progressColor = _entManager.System<ProgressColorSystem>();
var sprite = new SpriteSpecifier.Rsi(new("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
_barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
@@ -98,11 +101,13 @@ public sealed class DoAfterOverlay : Overlay
var offset = 0f;
var isInContainer = _container.IsEntityOrParentInContainer(uid, meta, xform);
foreach (var doAfter in comp.DoAfters.Values)
{
// Hide some DoAfters from other players for stealthy actions (ie: thieving gloves)
var alpha = 1f;
if (doAfter.Args.Hidden)
if (doAfter.Args.Hidden || isInContainer)
{
if (uid != localEnt)
continue;

View File

@@ -1,6 +1,7 @@
using Content.Client.Administration.Managers;
using Content.Client.Changelog;
using Content.Client.Chat.Managers;
using Content.Client.DebugMon;
using Content.Client.Eui;
using Content.Client.Fullscreen;
using Content.Client.GhostKick;
@@ -34,6 +35,7 @@ using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
using Robust.Shared.Replays;
using Robust.Shared.Timing;
namespace Content.Client.Entry
{
@@ -69,6 +71,7 @@ namespace Content.Client.Entry
[Dependency] private readonly IReplayLoadManager _replayLoad = default!;
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly ContentReplayPlaybackManager _replayMan = default!;
[Dependency] private readonly DebugMonitorManager _debugMonitorManager = default!;
public override void Init()
{
@@ -206,5 +209,13 @@ namespace Content.Client.Entry
_stateManager.RequestStateChange<MainScreen>();
}
}
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
{
if (level == ModUpdateLevel.FramePreEngine)
{
_debugMonitorManager.FrameUpdate();
}
}
}
}

View File

@@ -1,5 +1,4 @@
using Content.Client.Verbs;
using Content.Shared.Eye.Blinding;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Input;
@@ -16,8 +15,6 @@ using Robust.Shared.Utility;
using System.Linq;
using System.Numerics;
using System.Threading;
using Content.Shared.Eye.Blinding.Components;
using Robust.Client;
using static Content.Shared.Interaction.SharedInteractionSystem;
using static Robust.Client.UserInterface.Controls.BoxContainer;
using Content.Shared.Interaction.Events;
@@ -46,6 +43,8 @@ namespace Content.Client.Examine
public override void Initialize()
{
base.Initialize();
UpdatesOutsidePrediction = true;
SubscribeLocalEvent<GetVerbsEvent<ExamineVerb>>(AddExamineVerb);
@@ -358,10 +357,7 @@ namespace Content.Client.Examine
FormattedMessage message;
// Basically this just predicts that we can't make out the entity if we have poor vision.
var canSeeClearly = !HasComp<BlurryVisionComponent>(playerEnt);
OpenTooltip(playerEnt.Value, entity, centeredOnCursor, false, knowTarget: canSeeClearly);
OpenTooltip(playerEnt.Value, entity, centeredOnCursor, false);
// Always update tooltip info from client first.
// If we get it wrong, server will correct us later anyway.

View File

@@ -1,7 +0,0 @@
using Content.Shared.Extinguisher;
using Robust.Shared.GameStates;
namespace Content.Client.Extinguisher;
[RegisterComponent]
public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent;

View File

@@ -16,7 +16,7 @@ public sealed class AdminFaxEui : BaseEui
_window.OnClose += () => SendMessage(new AdminFaxEuiMsg.Close());
_window.OnFollowFax += entity => SendMessage(new AdminFaxEuiMsg.Follow(entity));
_window.OnMessageSend += args => SendMessage(new AdminFaxEuiMsg.Send(args.entity, args.title,
args.stampedBy, args.message, args.stampSprite, args.stampColor));
args.stampedBy, args.message, args.stampSprite, args.stampColor, args.locked));
}
public override void Opened()

View File

@@ -23,7 +23,7 @@
</BoxContainer>
<Label Text="{Loc admin-fax-stamp-color}" />
<ColorSelectorSliders Margin="12 0 0 0" Name="StampColorSelector" Color="#BB3232"/>
<Control MinHeight="10" />
<Button Name="SendButton" Text="{Loc admin-fax-send}"></Button>
<CheckBox Name="LockPageCheckbox" Text="{Loc admin-fax-lock-page}" ToolTip="{Loc admin-fax-lock-page-tooltip}"/>
<Button Name="SendButton" Text="{Loc admin-fax-send}" Margin="0 10 0 0" />
</BoxContainer>
</DefaultWindow>

View File

@@ -14,7 +14,7 @@ public sealed partial class AdminFaxWindow : DefaultWindow
{
private const string StampsRsiPath = "/Textures/Objects/Misc/bureaucracy.rsi";
public Action<(NetEntity entity, string title, string stampedBy, string message, string stampSprite, Color stampColor)>? OnMessageSend;
public Action<(NetEntity entity, string title, string stampedBy, string message, string stampSprite, Color stampColor, bool locked)>? OnMessageSend;
public Action<NetEntity>? OnFollowFax;
[Dependency] private readonly IResourceCache _resCache = default!;
@@ -98,6 +98,7 @@ public sealed partial class AdminFaxWindow : DefaultWindow
var from = FromEdit.Text;
var stampColor = StampColorSelector.Color;
OnMessageSend?.Invoke((faxEntity.Value, title, from, message, stamp, stampColor));
var locked = LockPageCheckbox.Pressed;
OnMessageSend?.Invoke((faxEntity.Value, title, from, message, stamp, stampColor, locked));
}
}

View File

@@ -1,27 +1,22 @@
using Content.Shared.Flash;
using Content.Shared.Flash.Components;
using Content.Shared.StatusEffect;
using Content.Client.Viewport;
using Robust.Client.Graphics;
using Robust.Client.State;
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using SixLabors.ImageSharp.PixelFormats;
namespace Content.Client.Flash
{
public sealed class FlashOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClyde _displayManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly StatusEffectsSystem _statusSys;
private readonly StatusEffectsSystem _statusSys;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _shader;
@@ -56,20 +51,6 @@ namespace Content.Client.Flash
PercentComplete = timeDone / lastsFor;
}
public void ReceiveFlash()
{
if (_stateManager.CurrentState is IMainViewportState state)
{
// take a screenshot
// note that the callback takes a while and ScreenshotTexture will be null the first few Draws
state.Viewport.Viewport.Screenshot(image =>
{
var rgba32Image = image.CloneAs<Rgba32>(SixLabors.ImageSharp.Configuration.Default);
ScreenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
});
}
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (!_entityManager.TryGetComponent(_playerManager.LocalEntity, out EyeComponent? eyeComp))
@@ -82,6 +63,11 @@ namespace Content.Client.Flash
protected override void Draw(in OverlayDrawArgs args)
{
if (RequestScreenTexture && ScreenTexture != null)
{
ScreenshotTexture = ScreenTexture;
RequestScreenTexture = false; // we only need the first frame, so we can stop the request now for performance reasons
}
if (ScreenshotTexture == null)
return;
@@ -96,7 +82,6 @@ namespace Content.Client.Flash
{
base.DisposeBehavior();
ScreenshotTexture = null;
PercentComplete = 1.0f;
}
}
}

View File

@@ -22,7 +22,6 @@ public sealed class FlashSystem : SharedFlashSystem
SubscribeLocalEvent<FlashedComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<FlashedComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<FlashedComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<FlashedComponent, StatusEffectAddedEvent>(OnStatusAdded);
_overlay = new();
}
@@ -34,8 +33,8 @@ public sealed class FlashSystem : SharedFlashSystem
private void OnPlayerDetached(EntityUid uid, FlashedComponent component, LocalPlayerDetachedEvent args)
{
_overlay.PercentComplete = 1.0f;
_overlay.ScreenshotTexture = null;
_overlay.RequestScreenTexture = false;
_overlayMan.RemoveOverlay(_overlay);
}
@@ -43,6 +42,7 @@ public sealed class FlashSystem : SharedFlashSystem
{
if (_player.LocalEntity == uid)
{
_overlay.RequestScreenTexture = true;
_overlayMan.AddOverlay(_overlay);
}
}
@@ -51,17 +51,9 @@ public sealed class FlashSystem : SharedFlashSystem
{
if (_player.LocalEntity == uid)
{
_overlay.PercentComplete = 1.0f;
_overlay.ScreenshotTexture = null;
_overlay.RequestScreenTexture = false;
_overlayMan.RemoveOverlay(_overlay);
}
}
private void OnStatusAdded(EntityUid uid, FlashedComponent component, StatusEffectAddedEvent args)
{
if (_player.LocalEntity == uid && args.Key == FlashedKey)
{
_overlay.ReceiveFlash();
}
}
}

View File

@@ -104,7 +104,8 @@ namespace Content.Client.Gameplay
public IEnumerable<EntityUid> GetClickableEntities(EntityCoordinates coordinates)
{
return GetClickableEntities(coordinates.ToMap(_entityManager, _entitySystemManager.GetEntitySystem<SharedTransformSystem>()));
var transformSystem = _entitySystemManager.GetEntitySystem<SharedTransformSystem>();
return GetClickableEntities(transformSystem.ToMapCoordinates(coordinates));
}
public IEnumerable<EntityUid> GetClickableEntities(MapCoordinates coordinates)

View File

@@ -15,6 +15,7 @@ using Robust.Client.UserInterface;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Timing;
namespace Content.Client.Hands.Systems
@@ -28,6 +29,7 @@ namespace Content.Client.Hands.Systems
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly StrippableSystem _stripSys = default!;
[Dependency] private readonly ExamineSystem _examine = default!;
[Dependency] private readonly ISerializationManager _serialization = default!; //CP14
public event Action<string, HandLocation>? OnPlayerAddHand;
public event Action<string>? OnPlayerRemoveHand;
@@ -322,6 +324,8 @@ namespace Content.Client.Hands.Systems
return;
}
var displacementData = handComp.Displacements.GetValueOrDefault("Hands"); //CP14 hands displacements
// add the new layers
foreach (var (key, layerData) in ev.Layers)
{
@@ -345,6 +349,39 @@ namespace Content.Client.Hands.Systems
}
sprite.LayerSetData(index, layerData);
//CP14 Hands displacement maps
if (displacementData != null)
{
if (displacementData.ShaderOverride != null)
sprite.LayerSetShader(index, displacementData.ShaderOverride);
var displacementKey = $"{key}-displacement";
if (!revealedLayers.Add(displacementKey))
{
Log.Warning($"Duplicate key for inhand layers DISPLACEMENT: {displacementKey}.");
continue;
}
var displacementDataLayer = displacementData.Layer;
var actualRSI = sprite.LayerGetActualRSI(index);
if (actualRSI != null)
{
var layerSize = actualRSI.Size;
if (layerSize.X == 48 && displacementData.Layer48 != null)
displacementDataLayer = displacementData.Layer48;
}
var displacementLayer = _serialization.CreateCopy(displacementDataLayer, notNullableOverride: true);
displacementLayer.CopyToShaderParameters!.LayerKey = key;
// Add before main layer for this item.
sprite.AddLayer(displacementLayer, index);
sprite.LayerMapSet(displacementKey, index);
revealedLayers.Add(displacementKey);
}
//CP14 Hands displacement maps - end
}
RaiseLocalEvent(held, new HeldVisualsUpdatedEvent(uid, revealedLayers), true);

View File

@@ -2,6 +2,7 @@ using Content.Client.Administration.Managers;
using Content.Client.Changelog;
using Content.Client.Chat.Managers;
using Content.Client.Clickable;
using Content.Client.DebugMon;
using Content.Client.Eui;
using Content.Client.GhostKick;
using Content.Client.Launcher;
@@ -48,6 +49,7 @@ namespace Content.Client.IoC
collection.Register<DocumentParsingManager>();
collection.Register<ContentReplayPlaybackManager, ContentReplayPlaybackManager>();
collection.Register<ISharedPlaytimeManager, JobRequirementsManager>();
collection.Register<DebugMonitorManager>();
}
}
}

View File

@@ -1,9 +0,0 @@
using Content.Shared.Item.ItemToggle;
namespace Content.Shared.Item;
/// <inheritdoc/>
public sealed class ItemToggleSystem : SharedItemToggleSystem
{
}

View File

@@ -48,6 +48,9 @@ namespace Content.Client.Jittering
if(args.Key != _jitterAnimationKey)
return;
if (!args.Finished)
return;
if (TryComp(uid, out AnimationPlayerComponent? animationPlayer)
&& TryComp(uid, out SpriteComponent? sprite))
_animationPlayer.Play(uid, animationPlayer, GetAnimation(jittering, sprite), _jitterAnimationKey);

View File

@@ -217,12 +217,12 @@ public sealed partial class LatheMenu : DefaultWindow
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;
var queuedRecipeProto = new EntityPrototypeView();
queuedRecipeBox.AddChild(queuedRecipeProto);
if (_prototypeManager.TryIndex(recipe.Result, out EntityPrototype? entityProto) && entityProto != null)
queuedRecipeProto.SetPrototype(entityProto);
var queuedRecipeLabel = new Label();
queuedRecipeLabel.Text = $"{idx}. {recipe.Name}";
queuedRecipeBox.AddChild(queuedRecipeProto);
queuedRecipeBox.AddChild(queuedRecipeLabel);
QueueList.AddChild(queuedRecipeBox);
idx++;

View File

@@ -116,7 +116,7 @@ namespace Content.Client.Launcher
private void ChangeLoginTip()
{
var tipsDataset = _cfg.GetCVar(CCVars.LoginTipsDataset);
var loginTipsEnabled = _prototype.TryIndex<DatasetPrototype>(tipsDataset, out var tips);
var loginTipsEnabled = _prototype.TryIndex<LocalizedDatasetPrototype>(tipsDataset, out var tips);
LoginTips.Visible = loginTipsEnabled;
if (!loginTipsEnabled)
@@ -131,7 +131,7 @@ namespace Content.Client.Launcher
var randomIndex = _random.Next(tipList.Count);
var tip = tipList[randomIndex];
LoginTip.SetMessage(tip);
LoginTip.SetMessage(Loc.GetString(tip));
LoginTipTitle.Text = Loc.GetString("connecting-window-tip", ("numberTip", randomIndex));
}

View File

@@ -19,6 +19,9 @@ public sealed class LightBehaviorSystem : EntitySystem
private void OnBehaviorAnimationCompleted(EntityUid uid, LightBehaviourComponent component, AnimationCompletedEvent args)
{
if (!args.Finished)
return;
var container = component.Animations.FirstOrDefault(x => x.FullKey == args.Key);
if (container == null)

View File

@@ -69,6 +69,9 @@ public sealed class RotatingLightSystem : SharedRotatingLightSystem
private void OnAnimationComplete(EntityUid uid, RotatingLightComponent comp, AnimationCompletedEvent args)
{
if (!args.Finished)
return;
PlayAnimation(uid, comp);
}

View File

@@ -46,6 +46,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
private CharacterSetupGui? _characterSetup;
private HumanoidProfileEditor? _profileEditor;
private CharacterSetupGuiSavePanel? _savePanel;
/// <summary>
/// This is the characher preview panel in the chat. This should only update if their character updates.
@@ -214,6 +215,46 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
ReloadCharacterSetup();
}
private void CloseProfileEditor()
{
if (_profileEditor == null)
return;
_profileEditor.SetProfile(null, null);
_profileEditor.Visible = false;
if (_stateManager.CurrentState is LobbyState lobbyGui)
{
lobbyGui.SwitchState(LobbyGui.LobbyGuiState.Default);
}
}
private void OpenSavePanel()
{
if (_savePanel is { IsOpen: true })
return;
_savePanel = new CharacterSetupGuiSavePanel();
_savePanel.SaveButton.OnPressed += _ =>
{
SaveProfile();
_savePanel.Close();
CloseProfileEditor();
};
_savePanel.NoSaveButton.OnPressed += _ =>
{
_savePanel.Close();
CloseProfileEditor();
};
_savePanel.OpenCentered();
}
private (CharacterSetupGui, HumanoidProfileEditor) EnsureGui()
{
if (_characterSetup != null && _profileEditor != null)
@@ -240,14 +281,16 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
_characterSetup.CloseButton.OnPressed += _ =>
{
// Reset sliders etc.
_profileEditor.SetProfile(null, null);
_profileEditor.Visible = false;
if (_stateManager.CurrentState is LobbyState lobbyGui)
// Open the save panel if we have unsaved changes.
if (_profileEditor.Profile != null && _profileEditor.IsDirty)
{
lobbyGui.SwitchState(LobbyGui.LobbyGuiState.Default);
OpenSavePanel();
return;
}
// Reset sliders etc.
CloseProfileEditor();
};
_profileEditor.Save += SaveProfile;

View File

@@ -0,0 +1,10 @@
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'character-setup-gui-save-panel-title'}"
Resizable="False">
<BoxContainer Orientation="Horizontal" SeparationOverride="4" MinSize="200 40">
<Button Name="SaveButton" Access="Public" Text="{Loc 'character-setup-gui-save-panel-save'}" StyleClasses="ButtonBig"/>
<Button Name="NoSaveButton" Access="Public" Text="{Loc 'character-setup-gui-save-panel-nosave'}" StyleClasses="ButtonBig"/>
<Button Name="CancelButton" Access="Public" Text="{Loc 'character-setup-gui-save-panel-cancel'}" StyleClasses="ButtonBig"/>
</BoxContainer>
</DefaultWindow>

View File

@@ -0,0 +1,21 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Lobby.UI;
[GenerateTypedNameReferences]
public sealed partial class CharacterSetupGuiSavePanel : DefaultWindow
{
public CharacterSetupGuiSavePanel()
{
RobustXamlLoader.Load(this);
CancelButton.OnPressed += _ =>
{
Close();
};
CloseButton.Visible = false;
}
}

View File

@@ -480,10 +480,10 @@ namespace Content.Client.Lobby.UI
return;
}
//Setup model
Dictionary<string, List<string>> model = new();
// Setup model
Dictionary<string, List<string>> traitGroups = new();
List<string> defaultTraits = new();
model.Add("default", defaultTraits);
traitGroups.Add(TraitCategoryPrototype.Default, defaultTraits);
foreach (var trait in traits)
{
@@ -493,18 +493,19 @@ namespace Content.Client.Lobby.UI
continue;
}
if (!model.ContainsKey(trait.Category))
{
model.Add(trait.Category, new());
}
model[trait.Category].Add(trait.ID);
if (!_prototypeManager.HasIndex(trait.Category))
continue;
var group = traitGroups.GetOrNew(trait.Category);
group.Add(trait.ID);
}
//Create UI view from model
foreach (var (categoryId, traitId) in model)
// Create UI view from model
foreach (var (categoryId, categoryTraits) in traitGroups)
{
TraitCategoryPrototype? category = null;
if (categoryId != "default")
if (categoryId != TraitCategoryPrototype.Default)
{
category = _prototypeManager.Index<TraitCategoryPrototype>(categoryId);
// Label
@@ -519,7 +520,7 @@ namespace Content.Client.Lobby.UI
List<TraitPreferenceSelector?> selectors = new();
var selectionCount = 0;
foreach (var traitProto in traitId)
foreach (var traitProto in categoryTraits)
{
var trait = _prototypeManager.Index<TraitPrototype>(traitProto);
var selector = new TraitPreferenceSelector(trait);
@@ -530,7 +531,15 @@ namespace Content.Client.Lobby.UI
selector.PreferenceChanged += preference =>
{
Profile = Profile?.WithTraitPreference(trait.ID, categoryId, preference);
if (preference)
{
Profile = Profile?.WithTraitPreference(trait.ID, _prototypeManager);
}
else
{
Profile = Profile?.WithoutTraitPreference(trait.ID, _prototypeManager);
}
SetDirty();
RefreshTraits(); // If too many traits are selected, they will be reset to the real value.
};
@@ -1198,7 +1207,7 @@ namespace Content.Client.Lobby.UI
SetDirty();
}
private bool IsDirty
public bool IsDirty
{
get => _isDirty;
set

View File

@@ -25,6 +25,9 @@ namespace Content.Client.MainMenu
[Dependency] private readonly IGameController _controllerProxy = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly ILogManager _logManager = default!;
private ISawmill _sawmill = default!;
private MainMenuControl _mainMenuControl = default!;
private bool _isConnecting;
@@ -35,6 +38,8 @@ namespace Content.Client.MainMenu
/// <inheritdoc />
protected override void Startup()
{
_sawmill = _logManager.GetSawmill("mainmenu");
_mainMenuControl = new MainMenuControl(_resourceCache, _configurationManager);
_userInterfaceManager.StateRoot.AddChild(_mainMenuControl);
@@ -116,7 +121,7 @@ namespace Content.Client.MainMenu
catch (ArgumentException e)
{
_userInterfaceManager.Popup($"Unable to connect: {e.Message}", "Connection error.");
Logger.Warning(e.ToString());
_sawmill.Warning(e.ToString());
_netManager.ConnectFailed -= _onConnectFailed;
_setConnectingState(false);
}

View File

@@ -1,4 +1,4 @@
using Content.Shared.Materials;
using Content.Shared.Materials;
using Robust.Client.GameObjects;
namespace Content.Client.Materials;
@@ -49,7 +49,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
{
if (!base.TryInsertMaterialEntity(user, toInsert, receiver, storage, material, composition))
return false;
_transform.DetachParentToNull(toInsert, Transform(toInsert));
_transform.DetachEntity(toInsert, Transform(toInsert));
return true;
}
}

View File

@@ -2,7 +2,6 @@
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.Replays.Loading;
using Robust.Shared.Map;
using Robust.Shared.Timing;
@@ -46,13 +45,19 @@ public sealed class MouseRotatorSystem : SharedMouseRotatorSystem
// only raise event if the cardinal direction has changed
if (rotator.Simple4DirMode)
{
var angleDir = angle.GetCardinalDir();
if (angleDir == curRot.GetCardinalDir())
var eyeRot = _eye.CurrentEye.Rotation; // camera rotation
var angleDir = (angle + eyeRot).GetCardinalDir(); // apply GetCardinalDir in the camera frame, not in the world frame
if (angleDir == (curRot + eyeRot).GetCardinalDir())
return;
RaisePredictiveEvent(new RequestMouseRotatorRotationSimpleEvent()
var rotation = angleDir.ToAngle() - eyeRot; // convert back to world frame
if (rotation >= Math.PI) // convert to [-PI, +PI)
rotation -= 2 * Math.PI;
else if (rotation < -Math.PI)
rotation += 2 * Math.PI;
RaisePredictiveEvent(new RequestMouseRotatorRotationEvent
{
Direction = angleDir,
Rotation = rotation
});
return;

View File

@@ -9,7 +9,7 @@ public sealed class ContentEyeSystem : SharedContentEyeSystem
{
[Dependency] private readonly IPlayerManager _player = default!;
public void RequestZoom(EntityUid uid, Vector2 zoom, bool ignoreLimit, ContentEyeComponent? content = null)
public void RequestZoom(EntityUid uid, Vector2 zoom, bool ignoreLimit, bool scalePvs, ContentEyeComponent? content = null)
{
if (!Resolve(uid, ref content, false))
return;
@@ -19,6 +19,14 @@ public sealed class ContentEyeSystem : SharedContentEyeSystem
TargetZoom = zoom,
IgnoreLimit = ignoreLimit,
});
if (scalePvs)
RequestPvsScale(Math.Max(zoom.X, zoom.Y));
}
public void RequestPvsScale(float scale)
{
RaiseNetworkEvent(new RequestPvsScaleEvent(scale));
}
public void RequestToggleFov()

View File

@@ -15,6 +15,7 @@ public sealed class JetpackSystem : SharedJetpackSystem
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
public override void Initialize()
{
@@ -73,11 +74,11 @@ public sealed class JetpackSystem : SharedJetpackSystem
var uidXform = Transform(uid);
var coordinates = uidXform.Coordinates;
var gridUid = coordinates.GetGridUid(EntityManager);
var gridUid = _transform.GetGrid(coordinates);
if (TryComp<MapGridComponent>(gridUid, out var grid))
{
coordinates = new EntityCoordinates(gridUid.Value, grid.WorldToLocal(coordinates.ToMapPos(EntityManager, _transform)));
coordinates = new EntityCoordinates(gridUid.Value, _mapSystem.WorldToLocal(gridUid.Value, grid, _transform.ToMapCoordinates(coordinates).Position));
}
else if (uidXform.MapUid != null)
{

View File

@@ -203,7 +203,7 @@ namespace Content.Client.NPC
if (found || !_system.Breadcrumbs.TryGetValue(netGrid, out var crumbs) || !xformQuery.TryGetComponent(grid, out var gridXform))
continue;
var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform);
var localAABB = invWorldMatrix.TransformBox(aabb.Enlarged(float.Epsilon - SharedPathfindingSystem.ChunkSize));
foreach (var chunk in crumbs)
@@ -287,7 +287,7 @@ namespace Content.Client.NPC
return;
}
var invGridMatrix = gridXform.InvWorldMatrix;
var invGridMatrix = _transformSystem.GetInvWorldMatrix(gridXform);
DebugPathPoly? nearest = null;
foreach (var poly in tile)
@@ -359,7 +359,7 @@ namespace Content.Client.NPC
continue;
}
var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform);
worldHandle.SetTransform(worldMatrix);
var localAABB = invWorldMatrix.TransformBox(aabb);
@@ -419,7 +419,7 @@ namespace Content.Client.NPC
!xformQuery.TryGetComponent(grid, out var gridXform))
continue;
var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform);
worldHandle.SetTransform(worldMatrix);
var localAABB = invWorldMatrix.TransformBox(aabb);
@@ -458,7 +458,7 @@ namespace Content.Client.NPC
!xformQuery.TryGetComponent(grid, out var gridXform))
continue;
var (_, _, worldMatrix, invMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
var (_, _, worldMatrix, invMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform);
worldHandle.SetTransform(worldMatrix);
var localAABB = invMatrix.TransformBox(aabb);
@@ -483,7 +483,7 @@ namespace Content.Client.NPC
if (neighborPoly.NetEntity != poly.GraphUid)
{
color = Color.Green;
var neighborMap = _entManager.GetCoordinates(neighborPoly).ToMap(_entManager, _transformSystem);
var neighborMap = _transformSystem.ToMapCoordinates(_entManager.GetCoordinates(neighborPoly));
if (neighborMap.MapId != args.MapId)
continue;
@@ -517,7 +517,7 @@ namespace Content.Client.NPC
!xformQuery.TryGetComponent(grid, out var gridXform))
continue;
var (_, _, worldMatrix, invWorldMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
var (_, _, worldMatrix, invWorldMatrix) = _transformSystem.GetWorldPositionRotationMatrixWithInv(gridXform);
worldHandle.SetTransform(worldMatrix);
var localAABB = invWorldMatrix.TransformBox(args.WorldBounds);
@@ -544,7 +544,7 @@ namespace Content.Client.NPC
if (!_entManager.TryGetComponent<TransformComponent>(_entManager.GetEntity(node.GraphUid), out var graphXform))
continue;
worldHandle.SetTransform(graphXform.WorldMatrix);
worldHandle.SetTransform(_transformSystem.GetWorldMatrix(graphXform));
worldHandle.DrawRect(node.Box, Color.Orange.WithAlpha(0.10f));
}
}
@@ -568,7 +568,7 @@ namespace Content.Client.NPC
continue;
matrix = graph;
worldHandle.SetTransform(graphXform.WorldMatrix);
worldHandle.SetTransform(_transformSystem.GetWorldMatrix(graphXform));
}
worldHandle.DrawRect(node.Box, new Color(0f, cost / highestGScore, 1f - (cost / highestGScore), 0.10f));

View File

@@ -0,0 +1,5 @@
using Content.Shared.Ninja.Systems;
namespace Content.Client.Ninja.Systems;
public sealed class ItemCreatorSystem : SharedItemCreatorSystem;

View File

@@ -2,9 +2,4 @@ using Content.Shared.Ninja.Systems;
namespace Content.Client.Ninja.Systems;
/// <summary>
/// Does nothing special, only exists to provide a client implementation.
/// </summary>
public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem
{
}
public sealed class NinjaGlovesSystem : SharedNinjaGlovesSystem;

View File

@@ -1,24 +1,5 @@
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
namespace Content.Client.Ninja.Systems;
/// <summary>
/// Disables cloak prediction since client has no knowledge of battery power.
/// Cloak will still be enabled after server tells it.
/// </summary>
public sealed class NinjaSuitSystem : SharedNinjaSuitSystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<NinjaSuitComponent, AttemptStealthEvent>(OnAttemptStealth);
}
private void OnAttemptStealth(EntityUid uid, NinjaSuitComponent comp, AttemptStealthEvent args)
{
args.Cancel();
}
}
public sealed class NinjaSuitSystem : SharedNinjaSuitSystem;

View File

@@ -2,11 +2,4 @@ using Content.Shared.Ninja.Systems;
namespace Content.Client.Ninja.Systems;
/// <summary>
/// Currently does nothing special clientside.
/// All functionality is in shared and server.
/// Only exists to prevent crashing.
/// </summary>
public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
{
}
public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem;

View File

@@ -0,0 +1,5 @@
using Content.Shared.Ninja.Systems;
namespace Content.Client.Ninja.Systems;
public sealed class SpiderChargeSystem : SharedSpiderChargeSystem;

View File

@@ -0,0 +1,6 @@
<Control xmlns="https://spacestation14.io">
<BoxContainer Orientation="Horizontal">
<Label Name="NameLabel" MinWidth="400" />
<OptionButton Name="Button" Access="Public" />
</BoxContainer>
</Control>

View File

@@ -0,0 +1,21 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client.Options.UI;
/// <summary>
/// Standard UI control used for drop-downs in the options menu. Intended for use with <see cref="OptionsTabControlRow"/>.
/// </summary>
/// <seealso cref="OptionsTabControlRow.AddOptionDropDown{T}"/>
[GenerateTypedNameReferences]
public sealed partial class OptionDropDown : Control
{
/// <summary>
/// The text describing what this drop-down controls.
/// </summary>
public string? Title
{
get => NameLabel.Text;
set => NameLabel.Text = value;
}
}

View File

@@ -0,0 +1,7 @@
<Control xmlns="https://spacestation14.io">
<BoxContainer Orientation="Horizontal">
<Label Name="NameLabel" MinWidth="400" />
<Slider Name="Slider" Access="Public" HorizontalExpand="True" />
<Label Name="ValueLabel" Access="Public" Margin="8 0 4 0" MinWidth="48" Align="Right" />
</BoxContainer>
</Control>

View File

@@ -0,0 +1,22 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client.Options.UI;
/// <summary>
/// Standard UI control used for sliders in the options menu. Intended for use with <see cref="OptionsTabControlRow"/>.
/// </summary>
/// <seealso cref="OptionsTabControlRow.AddOptionSlider"/>
/// <seealso cref="OptionsTabControlRow.AddOptionPercentSlider"/>
[GenerateTypedNameReferences]
public sealed partial class OptionSlider : Control
{
/// <summary>
/// The text describing what this slider controls.
/// </summary>
public string? Title
{
get => NameLabel.Text;
set => NameLabel.Text = value;
}
}

View File

@@ -7,5 +7,6 @@
<tabs:GraphicsTab Name="GraphicsTab" />
<tabs:KeyRebindTab Name="KeyRebindTab" />
<tabs:AudioTab Name="AudioTab" />
<tabs:AccessibilityTab Name="AccessibilityTab" />
</TabContainer>
</DefaultWindow>

View File

@@ -1,9 +1,6 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.IoC;
using Content.Client.Options.UI.Tabs;
namespace Content.Client.Options.UI
{
@@ -19,13 +16,17 @@ namespace Content.Client.Options.UI
Tabs.SetTabTitle(1, Loc.GetString("ui-options-tab-graphics"));
Tabs.SetTabTitle(2, Loc.GetString("ui-options-tab-controls"));
Tabs.SetTabTitle(3, Loc.GetString("ui-options-tab-audio"));
Tabs.SetTabTitle(4, Loc.GetString("ui-options-tab-accessibility"));
UpdateTabs();
}
public void UpdateTabs()
{
GraphicsTab.UpdateProperties();
GraphicsTab.Control.ReloadValues();
MiscTab.Control.ReloadValues();
AccessibilityTab.Control.ReloadValues();
AudioTab.Control.ReloadValues();
}
}
}

View File

@@ -0,0 +1,18 @@
<Control xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls">
<controls:StripeBack HasBottomEdge="False">
<BoxContainer Orientation="Horizontal" Align="End" Margin="2">
<Button Name="DefaultButton"
Text="{Loc 'ui-options-default'}"
TextAlign="Center"
Margin="8 0" />
<Button Name="ResetButton"
Text="{Loc 'ui-options-reset-all'}"
StyleClasses="Caution" />
<Button Name="ApplyButton"
Text="{Loc 'ui-options-apply'}"
StyleClasses="OpenLeft" />
</BoxContainer>
</controls:StripeBack>
</Control>

View File

@@ -0,0 +1,684 @@
using System.Linq;
using Content.Client.Stylesheets;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Collections;
using Robust.Shared.Configuration;
namespace Content.Client.Options.UI;
/// <summary>
/// Control used on all tabs of the in-game options menu,
/// contains the "save" and "reset" buttons and controls the entire logic.
/// </summary>
/// <remarks>
/// <para>
/// Basic operation is simple: options tabs put this control at the bottom of the tab,
/// they bind UI controls to it with calls such as <see cref="AddOptionCheckBox"/>,
/// then they call <see cref="Initialize"/>. The rest is all handled by the control.
/// </para>
/// <para>
/// Individual options are implementations of <see cref="BaseOption"/>. See the type for details.
/// Common implementations for building on top of CVars are already exist,
/// but tabs can define their own if they need to.
/// </para>
/// <para>
/// Generally, options are added via helper methods such as <see cref="AddOptionCheckBox"/>,
/// however it is totally possible to directly instantiate the backing types
/// and add them via <see cref="AddOption{T}"/>.
/// </para>
/// <para>
/// The options system is general purpose enough that <see cref="OptionsTabControlRow"/> does not, itself,
/// know what a CVar is. It does automatically save CVars to config when save is pressed, but otherwise CVar interaction
/// is handled by <see cref="BaseOption"/> implementations.
/// </para>
/// <para>
/// Behaviorally, the row has 3 control buttons: save, reset changed, and reset to default.
/// "Save" writes the configuration changes and saves the configuration.
/// "Reset changed" discards changes made in the menu and re-loads the saved settings.
/// "Reset to default" resets the settings on the menu to be the default, out-of-the-box values.
/// Note that "Reset to default" does not save immediately, the user must still press save manually.
/// </para>
/// <para>
/// The disabled state of the 3 buttons is updated dynamically based on the values of the options.
/// </para>
/// </remarks>
[GenerateTypedNameReferences]
public sealed partial class OptionsTabControlRow : Control
{
[Dependency] private readonly ILocalizationManager _loc = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private ValueList<BaseOption> _options;
public OptionsTabControlRow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
ResetButton.StyleClasses.Add(StyleBase.ButtonOpenRight);
ApplyButton.OnPressed += ApplyButtonPressed;
ResetButton.OnPressed += ResetButtonPressed;
DefaultButton.OnPressed += DefaultButtonPressed;
}
/// <summary>
/// Add a new option to be tracked by the control.
/// </summary>
/// <param name="option">The option object that manages this object's logic</param>
/// <typeparam name="T">
/// The type of option being passed in. Necessary to allow the return type to match the parameter type
/// for easy chaining.
/// </typeparam>
/// <returns>The same <paramref name="option"/> as passed in, for easy chaining.</returns>
public T AddOption<T>(T option) where T : BaseOption
{
_options.Add(option);
return option;
}
/// <summary>
/// Add a checkbox option backed by a simple boolean CVar.
/// </summary>
/// <param name="cVar">The CVar represented by the checkbox.</param>
/// <param name="checkBox">The UI control for the option.</param>
/// <param name="invert">
/// If true, the checkbox is inverted relative to the CVar: if the CVar is true, the checkbox will be unchecked.
/// </param>
/// <returns>The option instance backing the added option.</returns>
/// <seealso cref="OptionCheckboxCVar"/>
public OptionCheckboxCVar AddOptionCheckBox(CVarDef<bool> cVar, CheckBox checkBox, bool invert = false)
{
return AddOption(new OptionCheckboxCVar(this, _cfg, cVar, checkBox, invert));
}
/// <summary>
/// Add a slider option, displayed in percent, backed by a simple float CVar.
/// </summary>
/// <param name="cVar">The CVar represented by the slider.</param>
/// <param name="slider">The UI control for the option.</param>
/// <param name="min">The minimum value the slider should allow. The default value represents "0%"</param>
/// <param name="max">The maximum value the slider should allow. The default value represents "100%"</param>
/// <param name="scale">
/// Scale with which to multiply slider values when mapped to the backing CVar.
/// For example, if a scale of 2 is set, a slider at 75% writes a value of 1.5 to the CVar.
/// </param>
/// <returns>The option instance backing the added option.</returns>
/// <remarks>
/// <para>
/// Note that percentage values are represented as ratios in code, i.e. a value of 100% is "1".
/// </para>
/// </remarks>
public OptionSliderFloatCVar AddOptionPercentSlider(
CVarDef<float> cVar,
OptionSlider slider,
float min = 0,
float max = 1,
float scale = 1)
{
return AddOption(new OptionSliderFloatCVar(this, _cfg, cVar, slider, min, max, scale, FormatPercent));
}
/// <summary>
/// Add a slider option, backed by a simple integer CVar.
/// </summary>
/// <param name="cVar">The CVar represented by the slider.</param>
/// <param name="slider">The UI control for the option.</param>
/// <param name="min">The minimum value the slider should allow.</param>
/// <param name="max">The maximum value the slider should allow.</param>
/// <param name="format">
/// An optional delegate used to format the textual value display of the slider.
/// If not provided, the default behavior is to directly format the integer value as text.
/// </param>
/// <returns>The option instance backing the added option.</returns>
public OptionSliderIntCVar AddOptionSlider(
CVarDef<int> cVar,
OptionSlider slider,
int min,
int max,
Func<OptionSliderIntCVar, int, string>? format = null)
{
return AddOption(new OptionSliderIntCVar(this, _cfg, cVar, slider, min, max, format ?? FormatInt));
}
/// <summary>
/// Add a drop-down option, backed by a CVar.
/// </summary>
/// <param name="cVar">The CVar represented by the drop-down.</param>
/// <param name="dropDown">The UI control for the option.</param>
/// <param name="options">
/// The set of options that will be shown in the drop-down. Items are ordered as provided.
/// </param>
/// <typeparam name="T">The type of the CVar being controlled.</typeparam>
/// <returns>The option instance backing the added option.</returns>
public OptionDropDownCVar<T> AddOptionDropDown<T>(
CVarDef<T> cVar,
OptionDropDown dropDown,
IReadOnlyCollection<OptionDropDownCVar<T>.ValueOption> options)
where T : notnull
{
return AddOption(new OptionDropDownCVar<T>(this, _cfg, cVar, dropDown, options));
}
/// <summary>
/// Initializes the control row. This should be called after all options have been added.
/// </summary>
public void Initialize()
{
foreach (var option in _options)
{
option.LoadValue();
}
UpdateButtonState();
}
/// <summary>
/// Re-loads options in the settings from backing values.
/// Should be called when the options window is opened to make sure all values are up-to-date.
/// </summary>
public void ReloadValues()
{
Initialize();
}
/// <summary>
/// Called by <see cref="BaseOption"/> to signal that an option's value changed through user interaction.
/// </summary>
/// <remarks>
/// <see cref="BaseOption"/> implementations should not call this function directly,
/// instead they should call <see cref="BaseOption.ValueChanged"/>.
/// </remarks>
public void ValueChanged()
{
UpdateButtonState();
}
private void UpdateButtonState()
{
var anyModified = _options.Any(option => option.IsModified());
var anyModifiedFromDefault = _options.Any(option => option.IsModifiedFromDefault());
DefaultButton.Disabled = !anyModifiedFromDefault;
ApplyButton.Disabled = !anyModified;
ResetButton.Disabled = !anyModified;
}
private void ApplyButtonPressed(BaseButton.ButtonEventArgs obj)
{
foreach (var option in _options)
{
if (option.IsModified())
option.SaveValue();
}
_cfg.SaveToFile();
UpdateButtonState();
}
private void ResetButtonPressed(BaseButton.ButtonEventArgs obj)
{
foreach (var option in _options)
{
option.LoadValue();
}
UpdateButtonState();
}
private void DefaultButtonPressed(BaseButton.ButtonEventArgs obj)
{
foreach (var option in _options)
{
option.ResetToDefault();
}
UpdateButtonState();
}
private string FormatPercent(OptionSliderFloatCVar slider, float value)
{
return _loc.GetString("ui-options-value-percent", ("value", value));
}
private static string FormatInt(OptionSliderIntCVar slider, int value)
{
return value.ToString();
}
}
/// <summary>
/// Base class of a single "option" for <see cref="OptionsTabControlRow"/>.
/// </summary>
/// <remarks>
/// <para>
/// Implementations of this class handle loading values from backing storage or defaults,
/// handling UI controls, and saving. The main <see cref="OptionsTabControlRow"/> does not know what a CVar is.
/// </para>
/// <para>
/// <see cref="BaseOptionCVar{TValue}"/> is a derived class that makes it easier to work with options
/// backed by a single CVar.
/// </para>
/// </remarks>
/// <param name="controller">The control row that owns this option.</param>
/// <seealso cref="OptionsTabControlRow"/>
public abstract class BaseOption(OptionsTabControlRow controller)
{
/// <summary>
/// Should be called by derived implementations to indicate that their value changed, due to user interaction.
/// </summary>
protected virtual void ValueChanged()
{
controller.ValueChanged();
}
/// <summary>
/// Loads the value represented by this option from its backing store, into the UI state.
/// </summary>
public abstract void LoadValue();
/// <summary>
/// Saves the value in the UI state to the backing store.
/// </summary>
public abstract void SaveValue();
/// <summary>
/// Resets the UI state to that of the factory-default value. This should not write to the backing store.
/// </summary>
public abstract void ResetToDefault();
/// <summary>
/// Called to check if this option's UI value is different from the backing store value.
/// </summary>
/// <returns>If true, the UI value is different and was modified by the user.</returns>
public abstract bool IsModified();
/// <summary>
/// Called to check if this option's UI value is different from the backing store's default value.
/// </summary>
/// <returns>If true, the UI value is different.</returns>
public abstract bool IsModifiedFromDefault();
}
/// <summary>
/// Derived class of <see cref="BaseOption"/> intended for making mappings to simple CVars easier.
/// </summary>
/// <typeparam name="TValue">The type of the CVar.</typeparam>
/// <seealso cref="OptionsTabControlRow"/>
public abstract class BaseOptionCVar<TValue> : BaseOption
where TValue : notnull
{
/// <summary>
/// Raised immediately when the UI value of this option is changed by the user, even before saving.
/// </summary>
/// <remarks>
/// <para>
/// This can be used to update parts of the options UI based on the state of a checkbox.
/// </para>
/// </remarks>
public event Action<TValue>? ImmediateValueChanged;
private readonly IConfigurationManager _cfg;
private readonly CVarDef<TValue> _cVar;
/// <summary>
/// Sets and gets the actual CVar value to/from the frontend UI state or control.
/// </summary>
/// <remarks>
/// <para>
/// In the simplest case, this function should set a UI control's state to represent the CVar,
/// and inversely conver the UI control's state to the CVar value. For simple controls like a checkbox or slider,
/// this just means passing through their value property.
/// </para>
/// </remarks>
protected abstract TValue Value { get; set; }
protected BaseOptionCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<TValue> cVar)
: base(controller)
{
_cfg = cfg;
_cVar = cVar;
}
public override void LoadValue()
{
Value = _cfg.GetCVar(_cVar);
}
public override void SaveValue()
{
_cfg.SetCVar(_cVar, Value);
}
public override void ResetToDefault()
{
Value = _cVar.DefaultValue;
}
public override bool IsModified()
{
return !IsValueEqual(Value, _cfg.GetCVar(_cVar));
}
public override bool IsModifiedFromDefault()
{
return !IsValueEqual(Value, _cVar.DefaultValue);
}
protected virtual bool IsValueEqual(TValue a, TValue b)
{
// Use different logic for floats so there's some error margin.
// This check is handled cleanly at compile-time by the JIT.
if (typeof(TValue) == typeof(float))
return MathHelper.CloseToPercent((float) (object) a, (float) (object) b);
return EqualityComparer<TValue>.Default.Equals(a, b);
}
protected override void ValueChanged()
{
base.ValueChanged();
ImmediateValueChanged?.Invoke(Value);
}
}
/// <summary>
/// Implementation of a CVar option that simply corresponds with a <see cref="CheckBox"/>.
/// </summary>
/// <remarks>
/// <para>
/// Generally, you should just call <c>AddOption</c> methods on <see cref="OptionsTabControlRow"/>
/// instead of instantiating this type directly.
/// </para>
/// </remarks>
/// <seealso cref="OptionsTabControlRow"/>
public sealed class OptionCheckboxCVar : BaseOptionCVar<bool>
{
private readonly CheckBox _checkBox;
private readonly bool _invert;
protected override bool Value
{
get => _checkBox.Pressed ^ _invert;
set => _checkBox.Pressed = value ^ _invert;
}
/// <summary>
/// Creates a new instance of this type.
/// </summary>
/// <param name="controller">The control row that owns this option.</param>
/// <param name="cfg">The configuration manager to get and set values from.</param>
/// <param name="cVar">The CVar that is being controlled by this option.</param>
/// <param name="checkBox">The UI control for the option.</param>
/// <param name="invert">
/// If true, the checkbox is inverted relative to the CVar: if the CVar is true, the checkbox will be unchecked.
/// </param>
/// <remarks>
/// <para>
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
/// such as <see cref="OptionsTabControlRow.AddOptionCheckBox"/> instead of instantiating this type directly.
/// </para>
/// </remarks>
public OptionCheckboxCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<bool> cVar,
CheckBox checkBox,
bool invert)
: base(controller, cfg, cVar)
{
_checkBox = checkBox;
_invert = invert;
checkBox.OnToggled += _ =>
{
ValueChanged();
};
}
}
/// <summary>
/// Implementation of a CVar option that simply corresponds with a floating-point <see cref="OptionSlider"/>.
/// </summary>
/// <seealso cref="OptionsTabControlRow"/>
public sealed class OptionSliderFloatCVar : BaseOptionCVar<float>
{
/// <summary>
/// Scale with which to multiply slider values when mapped to the backing CVar.
/// </summary>
/// <remarks>
/// For example, if a scale of 2 is set, a slider at 75% writes a value of 1.5 to the CVar.
/// </remarks>
public float Scale { get; }
private readonly OptionSlider _slider;
private readonly Func<OptionSliderFloatCVar, float, string> _format;
protected override float Value
{
get => _slider.Slider.Value * Scale;
set
{
_slider.Slider.Value = value / Scale;
UpdateLabelValue();
}
}
/// <summary>
/// Creates a new instance of this type.
/// </summary>
/// <remarks>
/// <para>
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
/// such as <see cref="OptionsTabControlRow.AddOptionPercentSlider"/> instead of instantiating this type directly.
/// </para>
/// </remarks>
/// <param name="controller">The control row that owns this option.</param>
/// <param name="cfg">The configuration manager to get and set values from.</param>
/// <param name="cVar">The CVar that is being controlled by this option.</param>
/// <param name="slider">The UI control for the option.</param>
/// <param name="minValue">The minimum value the slider should allow.</param>
/// <param name="maxValue">The maximum value the slider should allow.</param>
/// <param name="scale">
/// Scale with which to multiply slider values when mapped to the backing CVar. See <see cref="Scale"/>.
/// </param>
/// <param name="format">Function that will be called to format the value display next to the slider.</param>
public OptionSliderFloatCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<float> cVar,
OptionSlider slider,
float minValue,
float maxValue,
float scale,
Func<OptionSliderFloatCVar, float, string> format) : base(controller, cfg, cVar)
{
Scale = scale;
_slider = slider;
_format = format;
slider.Slider.MinValue = minValue;
slider.Slider.MaxValue = maxValue;
slider.Slider.OnValueChanged += _ =>
{
ValueChanged();
UpdateLabelValue();
};
}
private void UpdateLabelValue()
{
_slider.ValueLabel.Text = _format(this, _slider.Slider.Value);
}
}
/// <summary>
/// Implementation of a CVar option that simply corresponds with an integer <see cref="OptionSlider"/>.
/// </summary>
/// <seealso cref="OptionsTabControlRow"/>
public sealed class OptionSliderIntCVar : BaseOptionCVar<int>
{
private readonly OptionSlider _slider;
private readonly Func<OptionSliderIntCVar, int, string> _format;
protected override int Value
{
get => (int) _slider.Slider.Value;
set
{
_slider.Slider.Value = value;
UpdateLabelValue();
}
}
/// <summary>
/// Creates a new instance of this type.
/// </summary>
/// <remarks>
/// <para>
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
/// such as <see cref="OptionsTabControlRow.AddOptionPercentSlider"/> instead of instantiating this type directly.
/// </para>
/// </remarks>
/// <param name="controller">The control row that owns this option.</param>
/// <param name="cfg">The configuration manager to get and set values from.</param>
/// <param name="cVar">The CVar that is being controlled by this option.</param>
/// <param name="slider">The UI control for the option.</param>
/// <param name="minValue">The minimum value the slider should allow.</param>
/// <param name="maxValue">The maximum value the slider should allow.</param>
/// <param name="format">Function that will be called to format the value display next to the slider.</param>
public OptionSliderIntCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<int> cVar,
OptionSlider slider,
int minValue,
int maxValue,
Func<OptionSliderIntCVar, int, string> format) : base(controller, cfg, cVar)
{
_slider = slider;
_format = format;
slider.Slider.MinValue = minValue;
slider.Slider.MaxValue = maxValue;
slider.Slider.Rounded = true;
slider.Slider.OnValueChanged += _ =>
{
ValueChanged();
UpdateLabelValue();
};
}
private void UpdateLabelValue()
{
_slider.ValueLabel.Text = _format(this, (int) _slider.Slider.Value);
}
}
/// <summary>
/// Implementation of a CVar option via a drop-down.
/// </summary>
/// <seealso cref="OptionsTabControlRow"/>
public sealed class OptionDropDownCVar<T> : BaseOptionCVar<T> where T : notnull
{
private readonly OptionDropDown _dropDown;
private readonly ItemEntry[] _entries;
protected override T Value
{
get => (T) _dropDown.Button.SelectedMetadata!;
set => _dropDown.Button.SelectId(FindValueId(value));
}
/// <summary>
/// Creates a new instance of this type.
/// </summary>
/// <remarks>
/// <para>
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
/// such as <see cref="OptionsTabControlRow.AddOptionDropDown{T}"/> instead of instantiating this type directly.
/// </para>
/// </remarks>
/// <param name="controller">The control row that owns this option.</param>
/// <param name="cfg">The configuration manager to get and set values from.</param>
/// <param name="cVar">The CVar that is being controlled by this option.</param>
/// <param name="dropDown">The UI control for the option.</param>
/// <param name="options">The list of options shown to the user.</param>
public OptionDropDownCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<T> cVar,
OptionDropDown dropDown,
IReadOnlyCollection<ValueOption> options) : base(controller, cfg, cVar)
{
if (options.Count == 0)
throw new ArgumentException("Need at least one option!");
_dropDown = dropDown;
_entries = new ItemEntry[options.Count];
var button = dropDown.Button;
var i = 0;
foreach (var option in options)
{
_entries[i] = new ItemEntry
{
Key = option.Key,
};
button.AddItem(option.Label, i);
button.SetItemMetadata(button.GetIdx(i), option.Key);
i += 1;
}
dropDown.Button.OnItemSelected += args =>
{
dropDown.Button.SelectId(args.Id);
ValueChanged();
};
}
private int FindValueId(T value)
{
for (var i = 0; i < _entries.Length; i++)
{
if (IsValueEqual(_entries[i].Key, value))
return i;
}
// This will just default select the first entry or whatever.
return 0;
}
/// <summary>
/// A single option for a drop-down.
/// </summary>
/// <param name="key">The value that this option has. This is what will be written to the CVar if selected.</param>
/// <param name="label">The visual text shown to the user for the option.</param>
/// <seealso cref="OptionDropDownCVar{T}"/>
/// <seealso cref="OptionsTabControlRow.AddOptionDropDown{T}"/>
public sealed class ValueOption(T key, string label)
{
/// <summary>
/// The value that this option has. This is what will be written to the CVar if selected.
/// </summary>
public readonly T Key = key;
/// <summary>
/// The visual text shown to the user for the option.
/// </summary>
public readonly string Label = label;
}
private struct ItemEntry
{
public T Key;
}
}

View File

@@ -0,0 +1,16 @@
<Control xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="clr-namespace:Content.Client.Options.UI">
<BoxContainer Orientation="Vertical">
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
<BoxContainer Orientation="Vertical" Margin="8">
<CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
<CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
<CheckBox Name="ColorblindFriendlyCheckBox" Text="{Loc 'ui-options-colorblind-friendly'}" />
<ui:OptionSlider Name="ChatWindowOpacitySlider" Title="{Loc 'ui-options-chat-window-opacity'}" />
<ui:OptionSlider Name="ScreenShakeIntensitySlider" Title="{Loc 'ui-options-screen-shake-intensity'}" />
</BoxContainer>
</ScrollContainer>
<ui:OptionsTabControlRow Name="Control" Access="Public" />
</BoxContainer>
</Control>

View File

@@ -0,0 +1,24 @@
using Content.Shared.CCVar;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Options.UI.Tabs;
[GenerateTypedNameReferences]
public sealed partial class AccessibilityTab : Control
{
public AccessibilityTab()
{
RobustXamlLoader.Load(this);
Control.AddOptionCheckBox(CCVars.ChatEnableColorName, EnableColorNameCheckBox);
Control.AddOptionCheckBox(CCVars.AccessibilityColorblindFriendly, ColorblindFriendlyCheckBox);
Control.AddOptionCheckBox(CCVars.ReducedMotion, ReducedMotionCheckBox);
Control.AddOptionPercentSlider(CCVars.ChatWindowOpacity, ChatWindowOpacitySlider);
Control.AddOptionPercentSlider(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider);
Control.Initialize();
}
}

View File

@@ -1,128 +1,26 @@
<Control xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls">
xmlns:ui="clr-namespace:Content.Client.Options.UI">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Vertical" Margin="8 8 8 8" VerticalExpand="True">
<Label Text="{Loc 'ui-options-volume-label'}"
FontColorOverride="{x:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<BoxContainer Orientation="Vertical" Margin="0 3 0 0">
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-master-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="MasterVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="MasterVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<Control MinSize="0 8" />
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-midi-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="MidiVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="MidiVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-ambient-music-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="AmbientMusicVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="AmbientMusicVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-ambience-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="AmbienceVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="AmbienceVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-lobby-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="LobbyVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="LobbyVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-interface-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="InterfaceVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="InterfaceVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-ambience-max-sounds'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="AmbienceSoundsSlider"
MinValue="0"
MaxValue="1"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="AmbienceSoundsLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<Control MinSize="0 8" />
<ui:OptionSlider Name="SliderVolumeMaster" Title="{Loc 'ui-options-master-volume'}"
Margin="0 0 0 8" />
<ui:OptionSlider Name="SliderVolumeMidi" Title="{Loc 'ui-options-midi-volume'}" />
<ui:OptionSlider Name="SliderVolumeAmbientMusic" Title="{Loc 'ui-options-ambient-music-volume'}" />
<ui:OptionSlider Name="SliderVolumeAmbience" Title="{Loc 'ui-options-ambience-volume'}" />
<ui:OptionSlider Name="SliderVolumeLobby" Title="{Loc 'ui-options-lobby-volume'}" />
<ui:OptionSlider Name="SliderVolumeInterface" Title="{Loc 'ui-options-interface-volume'}" />
<ui:OptionSlider Name="SliderMaxAmbienceSounds" Title="{Loc 'ui-options-ambience-max-sounds'}"
Margin="0 0 0 8" />
<CheckBox Name="LobbyMusicCheckBox" Text="{Loc 'ui-options-lobby-music'}" />
<CheckBox Name="RestartSoundsCheckBox" Text="{Loc 'ui-options-restart-sounds'}" />
<CheckBox Name="EventMusicCheckBox" Text="{Loc 'ui-options-event-music'}" />
<CheckBox Name="AdminSoundsCheckBox" Text="{Loc 'ui-options-admin-sounds'}" />
</BoxContainer>
</BoxContainer>
<controls:StripeBack HasBottomEdge="False" HasMargins="False">
<BoxContainer Orientation="Horizontal"
Align="End"
HorizontalExpand="True"
VerticalExpand="True">
<Button Name="ResetButton"
Text="{Loc 'ui-options-reset-all'}"
StyleClasses="Caution"
HorizontalExpand="True"
HorizontalAlignment="Right" />
<Control MinSize="2 0" />
<Button Name="ApplyButton"
Text="{Loc 'ui-options-apply'}"
TextAlign="Center"
HorizontalAlignment="Right" />
</BoxContainer>
</controls:StripeBack>
<ui:OptionsTabControlRow Name="Control" Access="Public" />
</BoxContainer>
</Control>

View File

@@ -3,200 +3,72 @@ using Content.Shared.CCVar;
using Robust.Client.Audio;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared;
using Robust.Shared.Configuration;
using Range = Robust.Client.UserInterface.Controls.Range;
namespace Content.Client.Options.UI.Tabs
namespace Content.Client.Options.UI.Tabs;
[GenerateTypedNameReferences]
public sealed partial class AudioTab : Control
{
[GenerateTypedNameReferences]
public sealed partial class AudioTab : Control
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IAudioManager _audio = default!;
public AudioTab()
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
private readonly IAudioManager _audio;
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
public AudioTab()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
var masterVolume = Control.AddOptionPercentSlider(
CVars.AudioMasterVolume,
SliderVolumeMaster,
scale: ContentAudioSystem.MasterVolumeMultiplier);
masterVolume.ImmediateValueChanged += OnMasterVolumeSliderChanged;
_audio = IoCManager.Resolve<IAudioManager>();
LobbyMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.LobbyMusicEnabled);
RestartSoundsCheckBox.Pressed = _cfg.GetCVar(CCVars.RestartSoundsEnabled);
EventMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.EventMusicEnabled);
AdminSoundsCheckBox.Pressed = _cfg.GetCVar(CCVars.AdminSoundsEnabled);
Control.AddOptionPercentSlider(
CVars.MidiVolume,
SliderVolumeMidi,
scale: ContentAudioSystem.MidiVolumeMultiplier);
ApplyButton.OnPressed += OnApplyButtonPressed;
ResetButton.OnPressed += OnResetButtonPressed;
MasterVolumeSlider.OnValueChanged += OnMasterVolumeSliderChanged;
MidiVolumeSlider.OnValueChanged += OnMidiVolumeSliderChanged;
AmbientMusicVolumeSlider.OnValueChanged += OnAmbientMusicVolumeSliderChanged;
AmbienceVolumeSlider.OnValueChanged += OnAmbienceVolumeSliderChanged;
AmbienceSoundsSlider.OnValueChanged += OnAmbienceSoundsSliderChanged;
LobbyVolumeSlider.OnValueChanged += OnLobbyVolumeSliderChanged;
InterfaceVolumeSlider.OnValueChanged += OnInterfaceVolumeSliderChanged;
LobbyMusicCheckBox.OnToggled += OnLobbyMusicCheckToggled;
RestartSoundsCheckBox.OnToggled += OnRestartSoundsCheckToggled;
EventMusicCheckBox.OnToggled += OnEventMusicCheckToggled;
AdminSoundsCheckBox.OnToggled += OnAdminSoundsCheckToggled;
Control.AddOptionPercentSlider(
CCVars.AmbientMusicVolume,
SliderVolumeAmbientMusic,
scale: ContentAudioSystem.AmbientMusicMultiplier);
AmbienceSoundsSlider.MinValue = _cfg.GetCVar(CCVars.MinMaxAmbientSourcesConfigured);
AmbienceSoundsSlider.MaxValue = _cfg.GetCVar(CCVars.MaxMaxAmbientSourcesConfigured);
Control.AddOptionPercentSlider(
CCVars.AmbienceVolume,
SliderVolumeAmbience,
scale: ContentAudioSystem.AmbienceMultiplier);
Reset();
}
Control.AddOptionPercentSlider(
CCVars.LobbyMusicVolume,
SliderVolumeLobby,
scale: ContentAudioSystem.LobbyMultiplier);
protected override void Dispose(bool disposing)
{
ApplyButton.OnPressed -= OnApplyButtonPressed;
ResetButton.OnPressed -= OnResetButtonPressed;
MasterVolumeSlider.OnValueChanged -= OnMasterVolumeSliderChanged;
MidiVolumeSlider.OnValueChanged -= OnMidiVolumeSliderChanged;
AmbientMusicVolumeSlider.OnValueChanged -= OnAmbientMusicVolumeSliderChanged;
AmbienceVolumeSlider.OnValueChanged -= OnAmbienceVolumeSliderChanged;
LobbyVolumeSlider.OnValueChanged -= OnLobbyVolumeSliderChanged;
InterfaceVolumeSlider.OnValueChanged -= OnInterfaceVolumeSliderChanged;
base.Dispose(disposing);
}
Control.AddOptionPercentSlider(
CCVars.InterfaceVolume,
SliderVolumeInterface,
scale: ContentAudioSystem.InterfaceMultiplier);
private void OnLobbyVolumeSliderChanged(Range obj)
{
UpdateChanges();
}
Control.AddOptionSlider(
CCVars.MaxAmbientSources,
SliderMaxAmbienceSounds,
_cfg.GetCVar(CCVars.MinMaxAmbientSourcesConfigured),
_cfg.GetCVar(CCVars.MaxMaxAmbientSourcesConfigured));
private void OnInterfaceVolumeSliderChanged(Range obj)
{
UpdateChanges();
}
Control.AddOptionCheckBox(CCVars.LobbyMusicEnabled, LobbyMusicCheckBox);
Control.AddOptionCheckBox(CCVars.RestartSoundsEnabled, RestartSoundsCheckBox);
Control.AddOptionCheckBox(CCVars.EventMusicEnabled, EventMusicCheckBox);
Control.AddOptionCheckBox(CCVars.AdminSoundsEnabled, AdminSoundsCheckBox);
private void OnAmbientMusicVolumeSliderChanged(Range obj)
{
UpdateChanges();
}
Control.Initialize();
}
private void OnAmbienceVolumeSliderChanged(Range obj)
{
UpdateChanges();
}
private void OnAmbienceSoundsSliderChanged(Range obj)
{
UpdateChanges();
}
private void OnMasterVolumeSliderChanged(Range range)
{
_audio.SetMasterGain(MasterVolumeSlider.Value / 100f * ContentAudioSystem.MasterVolumeMultiplier);
UpdateChanges();
}
private void OnMidiVolumeSliderChanged(Range range)
{
UpdateChanges();
}
private void OnLobbyMusicCheckToggled(BaseButton.ButtonEventArgs args)
{
UpdateChanges();
}
private void OnRestartSoundsCheckToggled(BaseButton.ButtonEventArgs args)
{
UpdateChanges();
}
private void OnEventMusicCheckToggled(BaseButton.ButtonEventArgs args)
{
UpdateChanges();
}
private void OnAdminSoundsCheckToggled(BaseButton.ButtonEventArgs args)
{
UpdateChanges();
}
private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
{
_cfg.SetCVar(CVars.AudioMasterVolume, MasterVolumeSlider.Value / 100f * ContentAudioSystem.MasterVolumeMultiplier);
// Want the CVar updated values to have the multiplier applied
// For the UI we just display 0-100 still elsewhere
_cfg.SetCVar(CVars.MidiVolume, MidiVolumeSlider.Value / 100f * ContentAudioSystem.MidiVolumeMultiplier);
_cfg.SetCVar(CCVars.AmbienceVolume, AmbienceVolumeSlider.Value / 100f * ContentAudioSystem.AmbienceMultiplier);
_cfg.SetCVar(CCVars.AmbientMusicVolume, AmbientMusicVolumeSlider.Value / 100f * ContentAudioSystem.AmbientMusicMultiplier);
_cfg.SetCVar(CCVars.LobbyMusicVolume, LobbyVolumeSlider.Value / 100f * ContentAudioSystem.LobbyMultiplier);
_cfg.SetCVar(CCVars.InterfaceVolume, InterfaceVolumeSlider.Value / 100f * ContentAudioSystem.InterfaceMultiplier);
_cfg.SetCVar(CCVars.MaxAmbientSources, (int)AmbienceSoundsSlider.Value);
_cfg.SetCVar(CCVars.LobbyMusicEnabled, LobbyMusicCheckBox.Pressed);
_cfg.SetCVar(CCVars.RestartSoundsEnabled, RestartSoundsCheckBox.Pressed);
_cfg.SetCVar(CCVars.EventMusicEnabled, EventMusicCheckBox.Pressed);
_cfg.SetCVar(CCVars.AdminSoundsEnabled, AdminSoundsCheckBox.Pressed);
_cfg.SaveToFile();
UpdateChanges();
}
private void OnResetButtonPressed(BaseButton.ButtonEventArgs args)
{
Reset();
}
private void Reset()
{
MasterVolumeSlider.Value = _cfg.GetCVar(CVars.AudioMasterVolume) * 100f / ContentAudioSystem.MasterVolumeMultiplier;
MidiVolumeSlider.Value = _cfg.GetCVar(CVars.MidiVolume) * 100f / ContentAudioSystem.MidiVolumeMultiplier;
AmbienceVolumeSlider.Value = _cfg.GetCVar(CCVars.AmbienceVolume) * 100f / ContentAudioSystem.AmbienceMultiplier;
AmbientMusicVolumeSlider.Value = _cfg.GetCVar(CCVars.AmbientMusicVolume) * 100f / ContentAudioSystem.AmbientMusicMultiplier;
LobbyVolumeSlider.Value = _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier;
InterfaceVolumeSlider.Value = _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier;
AmbienceSoundsSlider.Value = _cfg.GetCVar(CCVars.MaxAmbientSources);
LobbyMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.LobbyMusicEnabled);
RestartSoundsCheckBox.Pressed = _cfg.GetCVar(CCVars.RestartSoundsEnabled);
EventMusicCheckBox.Pressed = _cfg.GetCVar(CCVars.EventMusicEnabled);
AdminSoundsCheckBox.Pressed = _cfg.GetCVar(CCVars.AdminSoundsEnabled);
UpdateChanges();
}
private void UpdateChanges()
{
// y'all need jesus.
var isMasterVolumeSame =
Math.Abs(MasterVolumeSlider.Value - _cfg.GetCVar(CVars.AudioMasterVolume) * 100f / ContentAudioSystem.MasterVolumeMultiplier) < 0.01f;
var isMidiVolumeSame =
Math.Abs(MidiVolumeSlider.Value - _cfg.GetCVar(CVars.MidiVolume) * 100f / ContentAudioSystem.MidiVolumeMultiplier) < 0.01f;
var isAmbientVolumeSame =
Math.Abs(AmbienceVolumeSlider.Value - _cfg.GetCVar(CCVars.AmbienceVolume) * 100f / ContentAudioSystem.AmbienceMultiplier) < 0.01f;
var isAmbientMusicVolumeSame =
Math.Abs(AmbientMusicVolumeSlider.Value - _cfg.GetCVar(CCVars.AmbientMusicVolume) * 100f / ContentAudioSystem.AmbientMusicMultiplier) < 0.01f;
var isLobbyVolumeSame =
Math.Abs(LobbyVolumeSlider.Value - _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier) < 0.01f;
var isInterfaceVolumeSame =
Math.Abs(InterfaceVolumeSlider.Value - _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier) < 0.01f;
var isAmbientSoundsSame = (int)AmbienceSoundsSlider.Value == _cfg.GetCVar(CCVars.MaxAmbientSources);
var isLobbySame = LobbyMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.LobbyMusicEnabled);
var isRestartSoundsSame = RestartSoundsCheckBox.Pressed == _cfg.GetCVar(CCVars.RestartSoundsEnabled);
var isEventSame = EventMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.EventMusicEnabled);
var isAdminSoundsSame = AdminSoundsCheckBox.Pressed == _cfg.GetCVar(CCVars.AdminSoundsEnabled);
var isEverythingSame = isMasterVolumeSame && isMidiVolumeSame && isAmbientVolumeSame && isAmbientMusicVolumeSame && isAmbientSoundsSame && isLobbySame && isRestartSoundsSame && isEventSame
&& isAdminSoundsSame && isLobbyVolumeSame && isInterfaceVolumeSame;
ApplyButton.Disabled = isEverythingSame;
ResetButton.Disabled = isEverythingSame;
MasterVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", MasterVolumeSlider.Value / 100));
MidiVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", MidiVolumeSlider.Value / 100));
AmbientMusicVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", AmbientMusicVolumeSlider.Value / 100));
AmbienceVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", AmbienceVolumeSlider.Value / 100));
LobbyVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", LobbyVolumeSlider.Value / 100));
InterfaceVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", InterfaceVolumeSlider.Value / 100));
AmbienceSoundsLabel.Text = ((int)AmbienceSoundsSlider.Value).ToString();
}
private void OnMasterVolumeSliderChanged(float value)
{
// TODO: I was thinking of giving OptionsTabControlRow a flag to "set CVar immediately", but I'm deferring that
// until there's a proper system for enforcing people don't close the window with pending changes.
_audio.SetMasterGain(value);
}
}

View File

@@ -1,53 +1,38 @@
<tabs:GraphicsTab xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:tabs="clr-namespace:Content.Client.Options.UI.Tabs">
xmlns:tabs="clr-namespace:Content.Client.Options.UI.Tabs"
xmlns:ui="clr-namespace:Content.Client.Options.UI">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Vertical" Margin="8 8 8 8" VerticalExpand="True">
<CheckBox Name="VSyncCheckBox" Text="{Loc 'ui-options-vsync'}" />
<CheckBox Name="FullscreenCheckBox" Text="{Loc 'ui-options-fullscreen'}" />
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-lighting-label'}" />
<Control MinSize="4 0" />
<OptionButton Name="LightingPresetOption" MinSize="100 0" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-scale-label'}" />
<Control MinSize="4 0" />
<OptionButton Name="UIScaleOption" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<ScrollContainer VerticalExpand="True">
<BoxContainer Orientation="Vertical" Margin="8 8 8 8">
<!-- Display -->
<Label Text="{Loc 'ui-options-display-label'}" StyleClasses="LabelKeyText"/>
<CheckBox Name="VSyncCheckBox" Text="{Loc 'ui-options-vsync'}" />
<CheckBox Name="FullscreenCheckBox" Text="{Loc 'ui-options-fullscreen'}" />
<!-- Quality -->
<Label Text="{Loc 'ui-options-quality-label'}" StyleClasses="LabelKeyText"/>
<ui:OptionDropDown Name="DropDownLightingQuality" Title="{Loc 'ui-options-lighting-label'}" />
<CheckBox Name="ViewportLowResCheckBox" Text="{Loc 'ui-options-vp-low-res'}" />
<CheckBox Name="ParallaxLowQualityCheckBox" Text="{Loc 'ui-options-parallax-low-quality'}" />
<!-- Interface -->
<Label Text="{Loc 'ui-options-interface-label'}" StyleClasses="LabelKeyText"/>
<ui:OptionDropDown Name="DropDownUIScale" Title="{Loc 'ui-options-scale-label'}" />
<CheckBox Name="ViewportStretchCheckBox" Text="{Loc 'ui-options-vp-stretch'}" />
<BoxContainer Name="ViewportScaleBox" Orientation="Horizontal">
<Label Name="ViewportScaleText" Margin="8 0" />
<Slider Name="ViewportScaleSlider"
MinValue="1"
MaxValue="5"
Rounded="True"
MinWidth="200" />
</BoxContainer>
<ui:OptionSlider Name="ViewportScaleSlider" Title="{Loc ui-options-vp-scale}" />
<ui:OptionSlider Name="ViewportWidthSlider" Title="{Loc ui-options-vp-width}" />
<CheckBox Name="IntegerScalingCheckBox"
Text="{Loc 'ui-options-vp-integer-scaling'}"
ToolTip="{Loc 'ui-options-vp-integer-scaling-tooltip'}" />
<CheckBox Name="ViewportVerticalFitCheckBox"
Text="{Loc 'ui-options-vp-vertical-fit'}"
ToolTip="{Loc 'ui-options-vp-vertical-fit-tooltip'}" />
<!-- Misc -->
<Label Text="{Loc 'ui-options-misc-label'}" StyleClasses="LabelKeyText"/>
<CheckBox Name="FpsCounterCheckBox" Text="{Loc 'ui-options-fps-counter'}" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Name="ViewportWidthSliderDisplay" />
<Control MinSize="4 0" />
<Slider Name="ViewportWidthSlider"
Rounded="True"
MinWidth="200" />
</BoxContainer>
<CheckBox Name="IntegerScalingCheckBox"
Text="{Loc 'ui-options-vp-integer-scaling'}"
ToolTip="{Loc 'ui-options-vp-integer-scaling-tooltip'}" />
<CheckBox Name="ViewportVerticalFitCheckBox"
Text="{Loc 'ui-options-vp-vertical-fit'}"
ToolTip="{Loc 'ui-options-vp-vertical-fit-tooltip'}" />
<CheckBox Name="ViewportLowResCheckBox" Text="{Loc 'ui-options-vp-low-res'}" />
<CheckBox Name="ParallaxLowQualityCheckBox" Text="{Loc 'ui-options-parallax-low-quality'}" />
<CheckBox Name="FpsCounterCheckBox" Text="{Loc 'ui-options-fps-counter'}" />
</BoxContainer>
<controls:StripeBack HasBottomEdge="False" HasMargins="False">
<Button Name="ApplyButton"
Text="{Loc 'ui-options-apply'}"
TextAlign="Center"
HorizontalAlignment="Right" />
</controls:StripeBack>
</ScrollContainer>
<ui:OptionsTabControlRow Name="Control" Access="Public" />
</BoxContainer>
</tabs:GraphicsTab>

View File

@@ -7,220 +7,141 @@ using Robust.Client.UserInterface.XAML;
using Robust.Shared;
using Robust.Shared.Configuration;
namespace Content.Client.Options.UI.Tabs
namespace Content.Client.Options.UI.Tabs;
[GenerateTypedNameReferences]
public sealed partial class GraphicsTab : Control
{
[GenerateTypedNameReferences]
public sealed partial class GraphicsTab : Control
[Dependency] private readonly IConfigurationManager _cfg = default!;
public GraphicsTab()
{
private static readonly float[] UIScaleOptions =
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
Control.AddOptionCheckBox(CVars.DisplayVSync, VSyncCheckBox);
Control.AddOption(new OptionFullscreen(Control, _cfg, FullscreenCheckBox));
Control.AddOption(new OptionLightingQuality(Control, _cfg, DropDownLightingQuality));
Control.AddOptionDropDown(
CVars.DisplayUIScale,
DropDownUIScale,
[
new OptionDropDownCVar<float>.ValueOption(
0f,
Loc.GetString("ui-options-scale-auto", ("scale", UserInterfaceManager.DefaultUIScale))),
new OptionDropDownCVar<float>.ValueOption(0.75f, Loc.GetString("ui-options-scale-75")),
new OptionDropDownCVar<float>.ValueOption(1.00f, Loc.GetString("ui-options-scale-100")),
new OptionDropDownCVar<float>.ValueOption(1.25f, Loc.GetString("ui-options-scale-125")),
new OptionDropDownCVar<float>.ValueOption(1.50f, Loc.GetString("ui-options-scale-150")),
new OptionDropDownCVar<float>.ValueOption(1.75f, Loc.GetString("ui-options-scale-175")),
new OptionDropDownCVar<float>.ValueOption(2.00f, Loc.GetString("ui-options-scale-200")),
]);
var vpStretch = Control.AddOptionCheckBox(CCVars.ViewportStretch, ViewportStretchCheckBox);
var vpVertFit = Control.AddOptionCheckBox(CCVars.ViewportVerticalFit, ViewportVerticalFitCheckBox);
Control.AddOptionSlider(
CCVars.ViewportFixedScaleFactor,
ViewportScaleSlider,
1,
5,
(_, value) => Loc.GetString("ui-options-vp-scale-value", ("scale", value)));
vpStretch.ImmediateValueChanged += _ => UpdateViewportSettingsVisibility();
vpVertFit.ImmediateValueChanged += _ => UpdateViewportSettingsVisibility();
Control.AddOptionSlider(
CCVars.ViewportWidth,
ViewportWidthSlider,
(int)ViewportWidthSlider.Slider.MinValue,
(int)ViewportWidthSlider.Slider.MaxValue);
Control.AddOption(new OptionIntegerScaling(Control, _cfg, IntegerScalingCheckBox));
Control.AddOptionCheckBox(CCVars.ViewportScaleRender, ViewportLowResCheckBox, invert: true);
Control.AddOptionCheckBox(CCVars.ParallaxLowQuality, ParallaxLowQualityCheckBox);
Control.AddOptionCheckBox(CCVars.HudFpsCounterVisible, FpsCounterCheckBox);
Control.Initialize();
_cfg.OnValueChanged(CCVars.ViewportMinimumWidth, _ => UpdateViewportWidthRange());
_cfg.OnValueChanged(CCVars.ViewportMaximumWidth, _ => UpdateViewportWidthRange());
UpdateViewportWidthRange();
UpdateViewportSettingsVisibility();
}
private void UpdateViewportSettingsVisibility()
{
ViewportScaleSlider.Visible = !ViewportStretchCheckBox.Pressed;
IntegerScalingCheckBox.Visible = ViewportStretchCheckBox.Pressed;
ViewportVerticalFitCheckBox.Visible = ViewportStretchCheckBox.Pressed;
ViewportWidthSlider.Visible = !ViewportStretchCheckBox.Pressed || !ViewportVerticalFitCheckBox.Pressed;
}
private void UpdateViewportWidthRange()
{
var min = _cfg.GetCVar(CCVars.ViewportMinimumWidth);
var max = _cfg.GetCVar(CCVars.ViewportMaximumWidth);
ViewportWidthSlider.Slider.MinValue = min;
ViewportWidthSlider.Slider.MaxValue = max;
}
private sealed class OptionLightingQuality : BaseOption
{
private readonly IConfigurationManager _cfg;
private readonly OptionDropDown _dropDown;
private const int QualityVeryLow = 0;
private const int QualityLow = 1;
private const int QualityMedium = 2;
private const int QualityHigh = 3;
private const int QualityDefault = QualityMedium;
public OptionLightingQuality(OptionsTabControlRow controller, IConfigurationManager cfg, OptionDropDown dropDown) : base(controller)
{
0f,
0.75f,
1f,
1.25f,
1.50f,
1.75f,
2f
};
[Dependency] private readonly IConfigurationManager _cfg = default!;
public GraphicsTab()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
VSyncCheckBox.OnToggled += OnCheckBoxToggled;
FullscreenCheckBox.OnToggled += OnCheckBoxToggled;
LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-very-low"));
LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-low"));
LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-medium"));
LightingPresetOption.AddItem(Loc.GetString("ui-options-lighting-high"));
LightingPresetOption.OnItemSelected += OnLightingQualityChanged;
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-auto",
("scale", UserInterfaceManager.DefaultUIScale)));
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-75"));
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-100"));
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-125"));
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-150"));
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-175"));
UIScaleOption.AddItem(Loc.GetString("ui-options-scale-200"));
UIScaleOption.OnItemSelected += OnUIScaleChanged;
ViewportStretchCheckBox.OnToggled += _ =>
{
UpdateViewportScale();
UpdateApplyButton();
};
ViewportScaleSlider.OnValueChanged += _ =>
{
UpdateApplyButton();
UpdateViewportScale();
};
ViewportWidthSlider.OnValueChanged += _ =>
{
UpdateViewportWidthDisplay();
UpdateApplyButton();
};
ViewportVerticalFitCheckBox.OnToggled += _ =>
{
UpdateViewportScale();
UpdateApplyButton();
};
IntegerScalingCheckBox.OnToggled += OnCheckBoxToggled;
ViewportLowResCheckBox.OnToggled += OnCheckBoxToggled;
ParallaxLowQualityCheckBox.OnToggled += OnCheckBoxToggled;
FpsCounterCheckBox.OnToggled += OnCheckBoxToggled;
ApplyButton.OnPressed += OnApplyButtonPressed;
VSyncCheckBox.Pressed = _cfg.GetCVar(CVars.DisplayVSync);
FullscreenCheckBox.Pressed = ConfigIsFullscreen;
LightingPresetOption.SelectId(GetConfigLightingQuality());
UIScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale));
ViewportScaleSlider.Value = _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
ViewportStretchCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportStretch);
IntegerScalingCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportSnapToleranceMargin) != 0;
ViewportVerticalFitCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportVerticalFit);
ViewportLowResCheckBox.Pressed = !_cfg.GetCVar(CCVars.ViewportScaleRender);
ParallaxLowQualityCheckBox.Pressed = _cfg.GetCVar(CCVars.ParallaxLowQuality);
FpsCounterCheckBox.Pressed = _cfg.GetCVar(CCVars.HudFpsCounterVisible);
ViewportWidthSlider.Value = _cfg.GetCVar(CCVars.ViewportWidth);
_cfg.OnValueChanged(CCVars.ViewportMinimumWidth, _ => UpdateViewportWidthRange());
_cfg.OnValueChanged(CCVars.ViewportMaximumWidth, _ => UpdateViewportWidthRange());
UpdateViewportWidthRange();
UpdateViewportWidthDisplay();
UpdateViewportScale();
UpdateApplyButton();
_cfg = cfg;
_dropDown = dropDown;
var button = dropDown.Button;
button.AddItem(Loc.GetString("ui-options-lighting-very-low"), QualityVeryLow);
button.AddItem(Loc.GetString("ui-options-lighting-low"), QualityLow);
button.AddItem(Loc.GetString("ui-options-lighting-medium"), QualityMedium);
button.AddItem(Loc.GetString("ui-options-lighting-high"), QualityHigh);
button.OnItemSelected += OnOptionSelected;
}
private void OnUIScaleChanged(OptionButton.ItemSelectedEventArgs args)
private void OnOptionSelected(OptionButton.ItemSelectedEventArgs obj)
{
UIScaleOption.SelectId(args.Id);
UpdateApplyButton();
_dropDown.Button.SelectId(obj.Id);
ValueChanged();
}
private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args)
public override void LoadValue()
{
_cfg.SetCVar(CVars.DisplayVSync, VSyncCheckBox.Pressed);
SetConfigLightingQuality(LightingPresetOption.SelectedId);
_cfg.SetCVar(CVars.DisplayWindowMode,
(int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
_cfg.SetCVar(CVars.DisplayUIScale, UIScaleOptions[UIScaleOption.SelectedId]);
_cfg.SetCVar(CCVars.ViewportStretch, ViewportStretchCheckBox.Pressed);
_cfg.SetCVar(CCVars.ViewportFixedScaleFactor, (int) ViewportScaleSlider.Value);
_cfg.SetCVar(CCVars.ViewportSnapToleranceMargin,
IntegerScalingCheckBox.Pressed ? CCVars.ViewportSnapToleranceMargin.DefaultValue : 0);
_cfg.SetCVar(CCVars.ViewportVerticalFit, ViewportVerticalFitCheckBox.Pressed);
_cfg.SetCVar(CCVars.ViewportScaleRender, !ViewportLowResCheckBox.Pressed);
_cfg.SetCVar(CCVars.ParallaxLowQuality, ParallaxLowQualityCheckBox.Pressed);
_cfg.SetCVar(CCVars.HudFpsCounterVisible, FpsCounterCheckBox.Pressed);
_cfg.SetCVar(CCVars.ViewportWidth, (int) ViewportWidthSlider.Value);
_cfg.SaveToFile();
UpdateApplyButton();
_dropDown.Button.SelectId(GetConfigLightingQuality());
}
private void OnCheckBoxToggled(BaseButton.ButtonToggledEventArgs args)
public override void SaveValue()
{
UpdateApplyButton();
}
private void OnLightingQualityChanged(OptionButton.ItemSelectedEventArgs args)
{
LightingPresetOption.SelectId(args.Id);
UpdateApplyButton();
}
private void UpdateApplyButton()
{
var isVSyncSame = VSyncCheckBox.Pressed == _cfg.GetCVar(CVars.DisplayVSync);
var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen;
var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
var isUIScaleSame = MathHelper.CloseToPercent(UIScaleOptions[UIScaleOption.SelectedId], ConfigUIScale);
var isVPStretchSame = ViewportStretchCheckBox.Pressed == _cfg.GetCVar(CCVars.ViewportStretch);
var isVPScaleSame = (int) ViewportScaleSlider.Value == _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
var isIntegerScalingSame = IntegerScalingCheckBox.Pressed == (_cfg.GetCVar(CCVars.ViewportSnapToleranceMargin) != 0);
var isVPVerticalFitSame = ViewportVerticalFitCheckBox.Pressed == _cfg.GetCVar(CCVars.ViewportVerticalFit);
var isVPResSame = ViewportLowResCheckBox.Pressed == !_cfg.GetCVar(CCVars.ViewportScaleRender);
var isPLQSame = ParallaxLowQualityCheckBox.Pressed == _cfg.GetCVar(CCVars.ParallaxLowQuality);
var isFpsCounterVisibleSame = FpsCounterCheckBox.Pressed == _cfg.GetCVar(CCVars.HudFpsCounterVisible);
var isWidthSame = (int) ViewportWidthSlider.Value == _cfg.GetCVar(CCVars.ViewportWidth);
ApplyButton.Disabled = isVSyncSame &&
isFullscreenSame &&
isLightingQualitySame &&
isUIScaleSame &&
isVPStretchSame &&
isVPScaleSame &&
isIntegerScalingSame &&
isVPVerticalFitSame &&
isVPResSame &&
isPLQSame &&
isFpsCounterVisibleSame &&
isWidthSame;
}
private bool ConfigIsFullscreen =>
_cfg.GetCVar(CVars.DisplayWindowMode) == (int) WindowMode.Fullscreen;
public void UpdateProperties()
{
FullscreenCheckBox.Pressed = ConfigIsFullscreen;
}
private float ConfigUIScale => _cfg.GetCVar(CVars.DisplayUIScale);
private int GetConfigLightingQuality()
{
var val = _cfg.GetCVar(CVars.LightResolutionScale);
var soft = _cfg.GetCVar(CVars.LightSoftShadows);
if (val <= 0.125)
switch (_dropDown.Button.SelectedId)
{
return 0;
}
else if ((val <= 0.5) && !soft)
{
return 1;
}
else if (val <= 0.5)
{
return 2;
}
else
{
return 3;
}
}
private void SetConfigLightingQuality(int value)
{
switch (value)
{
case 0:
case QualityVeryLow:
_cfg.SetCVar(CVars.LightResolutionScale, 0.125f);
_cfg.SetCVar(CVars.LightSoftShadows, false);
_cfg.SetCVar(CVars.LightBlur, false);
break;
case 1:
case QualityLow:
_cfg.SetCVar(CVars.LightResolutionScale, 0.5f);
_cfg.SetCVar(CVars.LightSoftShadows, false);
_cfg.SetCVar(CVars.LightBlur, true);
break;
case 2:
default: // = QualityMedium
_cfg.SetCVar(CVars.LightResolutionScale, 0.5f);
_cfg.SetCVar(CVars.LightSoftShadows, true);
_cfg.SetCVar(CVars.LightBlur, true);
break;
case 3:
case QualityHigh:
_cfg.SetCVar(CVars.LightResolutionScale, 1);
_cfg.SetCVar(CVars.LightSoftShadows, true);
_cfg.SetCVar(CVars.LightBlur, true);
@@ -228,40 +149,83 @@ namespace Content.Client.Options.UI.Tabs
}
}
private static int GetConfigUIScalePreset(float value)
public override void ResetToDefault()
{
for (var i = 0; i < UIScaleOptions.Length; i++)
_dropDown.Button.SelectId(QualityDefault);
}
public override bool IsModified()
{
return _dropDown.Button.SelectedId != GetConfigLightingQuality();
}
public override bool IsModifiedFromDefault()
{
return _dropDown.Button.SelectedId != QualityDefault;
}
private int GetConfigLightingQuality()
{
var val = _cfg.GetCVar(CVars.LightResolutionScale);
var soft = _cfg.GetCVar(CVars.LightSoftShadows);
if (val <= 0.125)
return QualityVeryLow;
if ((val <= 0.5) && !soft)
return QualityLow;
if (val <= 0.5)
return QualityMedium;
return QualityHigh;
}
}
private sealed class OptionFullscreen : BaseOptionCVar<int>
{
private readonly CheckBox _checkBox;
protected override int Value
{
get => _checkBox.Pressed ? (int) WindowMode.Fullscreen : (int) WindowMode.Windowed;
set => _checkBox.Pressed = (value == (int) WindowMode.Fullscreen);
}
public OptionFullscreen(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CheckBox checkBox)
: base(controller, cfg, CVars.DisplayWindowMode)
{
_checkBox = checkBox;
_checkBox.OnToggled += _ =>
{
if (MathHelper.CloseToPercent(UIScaleOptions[i], value))
{
return i;
}
}
ValueChanged();
};
}
}
return 0;
private sealed class OptionIntegerScaling : BaseOptionCVar<int>
{
private readonly CheckBox _checkBox;
protected override int Value
{
get => _checkBox.Pressed ? CCVars.ViewportSnapToleranceMargin.DefaultValue : 0;
set => _checkBox.Pressed = (value != 0);
}
private void UpdateViewportScale()
public OptionIntegerScaling(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CheckBox checkBox)
: base(controller, cfg, CCVars.ViewportSnapToleranceMargin)
{
ViewportScaleBox.Visible = !ViewportStretchCheckBox.Pressed;
IntegerScalingCheckBox.Visible = ViewportStretchCheckBox.Pressed;
ViewportVerticalFitCheckBox.Visible = ViewportStretchCheckBox.Pressed;
ViewportWidthSlider.Visible = ViewportWidthSliderDisplay.Visible = !ViewportStretchCheckBox.Pressed || ViewportStretchCheckBox.Pressed && !ViewportVerticalFitCheckBox.Pressed;
ViewportScaleText.Text = Loc.GetString("ui-options-vp-scale", ("scale", ViewportScaleSlider.Value));
}
private void UpdateViewportWidthRange()
{
var min = _cfg.GetCVar(CCVars.ViewportMinimumWidth);
var max = _cfg.GetCVar(CCVars.ViewportMaximumWidth);
ViewportWidthSlider.MinValue = min;
ViewportWidthSlider.MaxValue = max;
}
private void UpdateViewportWidthDisplay()
{
ViewportWidthSliderDisplay.Text = Loc.GetString("ui-options-vp-width", ("width", (int) ViewportWidthSlider.Value));
_checkBox = checkBox;
_checkBox.OnToggled += _ =>
{
ValueChanged();
};
}
}
}

View File

@@ -1,76 +1,34 @@
<tabs:MiscTab xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:tabs="clr-namespace:Content.Client.Options.UI.Tabs"
xmlns:xNamespace="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets">
xmlns:tabs="clr-namespace:Content.Client.Options.UI.Tabs"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="clr-namespace:Content.Client.Options.UI">
<BoxContainer Orientation="Vertical">
<ScrollContainer VerticalExpand="True" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" Margin="8 8 8 8" VerticalExpand="True">
<Label Text="{Loc 'ui-options-general-ui-style'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-hud-theme'}" />
<Control MinSize="4 0" />
<OptionButton Name="HudThemeOption" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-hud-layout'}" />
<Control MinSize="4 0" />
<OptionButton Name="HudLayoutOption" />
</BoxContainer>
<Label Text="{Loc 'ui-options-general-accessibility'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
<CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
<CheckBox Name="ColorblindFriendlyCheckBox" Text="{Loc 'ui-options-colorblind-friendly'}" />
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-chat-window-opacity'}" Margin="8 0" />
<Slider Name="ChatWindowOpacitySlider"
MinValue="0"
MaxValue="1"
MinWidth="200" />
<Label Name="ChatWindowOpacityLabel" Margin="8 0" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-screen-shake-intensity'}" Margin="8 0" />
<Slider Name="ScreenShakeIntensitySlider"
MinValue="0"
MaxValue="100"
Rounded="True"
MinWidth="200" />
<Label Name="ScreenShakeIntensityLabel" Margin="8 0" />
</BoxContainer>
<ui:OptionDropDown Name="DropDownHudTheme" Title="{Loc 'ui-options-hud-theme'}" />
<ui:OptionDropDown Name="DropDownHudLayout" Title="{Loc 'ui-options-hud-layout'}" />
<Label Text="{Loc 'ui-options-general-discord'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="DiscordRich" Text="{Loc 'ui-options-discordrich'}" />
<Label Text="{Loc 'ui-options-general-speech'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ShowOocPatronColor" Text="{Loc 'ui-options-show-ooc-patron-color'}" />
<CheckBox Name="ShowLoocAboveHeadCheckBox" Text="{Loc 'ui-options-show-looc-on-head'}" />
<CheckBox Name="FancySpeechBubblesCheckBox" Text="{Loc 'ui-options-fancy-speech'}" />
<CheckBox Name="FancyNameBackgroundsCheckBox" Text="{Loc 'ui-options-fancy-name-background'}" />
<Label Text="{Loc 'ui-options-general-cursor'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ShowHeldItemCheckBox" Text="{Loc 'ui-options-show-held-item'}" />
<CheckBox Name="ShowCombatModeIndicatorsCheckBox" Text="{Loc 'ui-options-show-combat-mode-indicators'}" />
<Label Text="{Loc 'ui-options-general-storage'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="OpaqueStorageWindowCheckBox" Text="{Loc 'ui-options-opaque-storage-window'}" />
<CheckBox Name="StaticStorageUI" Text="{Loc 'ui-options-static-storage-ui'}" />
<!-- <CheckBox Name="ToggleWalk" Text="{Loc 'ui-options-hotkey-toggle-walk'}" /> -->
</BoxContainer>
</ScrollContainer>
<controls:StripeBack HasBottomEdge="False" HasMargins="False">
<Button Name="ApplyButton"
Text="{Loc 'ui-options-apply'}"
TextAlign="Center"
HorizontalAlignment="Right" />
</controls:StripeBack>
<ui:OptionsTabControlRow Name="Control" Access="Public" />
</BoxContainer>
</tabs:MiscTab>

Some files were not shown because too many files have changed in this diff Show More