Compare commits

...

526 Commits

Author SHA1 Message Date
Nim
ca23fddd8a Lyre and flute (#759)
* music

* fix desc

* Update T1_fire_rune.yml

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Ed <edwardxperia2000@gmail.com>
2025-01-17 01:26:39 +03:00
Ed
50c502f598 AOE Spells (#758)
* AoE gameplay

* Update T1_fire_rune.yml

* test

* add cool AoE visual
2025-01-17 01:01:44 +03:00
Ed
0783eb1380 Knowledge system (#770)
* remove all requirements

* clean up and renaming to knowledge

* update code

* add admin knowledge verbs

* move shoes under pants

* knowledge based recipes

* clean up

* sewing knowledges

* knowledge dependencies

* knowledge learning objects

* more knowledge

* metallforging skill

* knowledge books

* start knowledges, T1 and T2 books in demiplanes

* remove coins from demiplanes

* roundstart knowledge
2025-01-17 00:08:13 +03:00
Nim
5af56d4655 fiiiiiix (#766) 2025-01-16 01:42:20 +03:00
MetalSage
6e77b82da7 fix (#763)
Co-authored-by: MetalSage <metalsage.official@gmail.com>
2025-01-15 20:14:50 +03:00
Nim
02cfcd620c Inter-Monster tolerance (#761)
* Insects ai

* monster
2025-01-15 17:34:38 +03:00
Ed
e6097da7cc Update CP14MagicEnergyPhotosynthesisComponent.cs 2025-01-15 01:05:28 +03:00
Ed
925738afc2 Workbench update (#760)
* fix workbench icons

* workbench search

* fix 1

* UI finalize

* fix material localization

* restore shard sprite

* Update sewing_table.yml
2025-01-15 00:34:08 +03:00
Ed
cf41cabcea Remove OP (#757)
* remove outdated content

* Update migration.yml

* Update twoHandedStaffs.yml
2025-01-14 14:36:10 +03:00
Ed
87d57df0e6 Omsoyk epic clothing pack (#756)
* new shirts

* pants and dresses

* blue cloak
2025-01-14 12:03:10 +03:00
Ed
51a47eaffc Bunch of gameplay issues (#754)
* fix demiplane contetn filtering

* fix day demiplanes

* remove filled crystals from demiplanes

* remove armored zombies

* added candles in town crates

* remove 20% unefficient of mana moving spells

* fix #622

* revert random Viator commit

* Update demiplane_rifts.yml
2025-01-14 01:41:11 +03:00
Nim
c7c5b4dc4c bench fix (#755) 2025-01-13 23:24:33 +03:00
Nim
2644fe26ea Ashes and Russian translation edits with a couple of minor fixes (#735)
* ash++++

* fix

* по запросу
2025-01-13 23:01:34 +03:00
Nim
732bc267f7 Bench (#751)
* bench

* anchored
2025-01-13 22:59:57 +03:00
Viator-MV
ddd61df7b8 изменение текстуры книги законов
текстура книги законов изменена на подходящую к новым книгам
2025-01-13 21:37:30 +03:00
Ed
025753e689 revert 2025-01-13 18:09:40 +03:00
Ed
368839dd68 Bugixes (#750)
* fix #746

* fix #745

* fix #747

* fix #744

* fix #743

* fix #741

* fix #722
2025-01-13 12:54:46 +03:00
vladimir.s
f5edf03bf6 double hp and mana alerts (#749)
* double hp and mana alerts

* Update alerts.yml

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
2025-01-12 23:05:19 +03:00
Ed
b5f70616c3 New lobby art (#748)
* lobby

* back to rus
2025-01-12 22:39:33 +03:00
Nim
e11d8a1c1a fix (#736) 2025-01-12 17:22:19 +03:00
Ed
3cce07be5a switch to eng 2025-01-12 17:10:27 +03:00
Nim
93c4e6068f Balance and fixes (#733)
* issue

* mosquitoes

* 👽
2025-01-12 17:00:35 +03:00
MetalSage
89b9a5c1fe Additive lighting (#685)
* Additive lighting

* adds options for all your optional needs

* one last tiny adjustment before we hit the create pr button

* spaghetti condensing

* add ccvar

* overlight correction

* fix requested changes

* cvar fix

* last fix

* nice

---------

Co-authored-by: deathride58 <deathride58@users.noreply.github.com>
Co-authored-by: MetalSage <metalsage.official@gmail.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Ed <edwardxperia2000@gmail.com>
2025-01-12 13:33:06 +03:00
MetalSage
a6847c08e8 Add "Mana Wasting" trait (#732)
* add trait

* Update Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl

* fix magic item using

---------

Co-authored-by: MetalSage <metalsage.official@gmail.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Ed <edwardxperia2000@gmail.com>
2025-01-12 13:10:45 +03:00
Ed
485ddaa739 map fix 2025-01-12 03:06:51 +03:00
Ed
f2ef46d90e New apprentice role / Новая роль подмастерья (#731)
* new role

* Update role_loadouts.yml

* Update jobs.yml

* Delete g.png
2025-01-12 03:05:47 +03:00
Nim
61897eae4f target (#730) 2025-01-12 02:01:53 +03:00
Ed
4a2c3c9d59 clean up CVars 2025-01-11 13:01:53 +03:00
Ed
3d0f303930 Create Dev.toml 2025-01-11 12:37:03 +03:00
Ed
0af7a7ec64 Alchemist content (#718)
* reinforced vials

* glass recipes

* roundstart alchemist potions
2025-01-10 16:17:32 +03:00
Ed
c41927cdf2 Bugfixes (#716)
* job localization fix

* Update job.ftl

* metall scraps

* tomato seeds craft

* fix #105

* health alerts fixed

* bucket size fix

* hat fix
2025-01-09 22:28:39 +03:00
A.Ne.
c3976dd08d plants inspection, resolve #449 (#615)
* plants inspection, resolve #449

* Update farming.ftl

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2025-01-09 22:05:22 +03:00
Nim
1af112aeb2 candle (#713) 2025-01-09 21:26:14 +03:00
Ed
9ab34417f4 More Bank positions (#715)
* add bank positions

* Update sell.yml
2025-01-09 17:23:35 +03:00
Nim
005a6012be sound (#714) 2025-01-09 16:40:18 +03:00
Ed
f1fc16c6f0 Update CP14IgnitionModifierComponent.cs 2025-01-09 15:27:28 +03:00
Ed
2b0fa46857 david balance pass (#712) 2025-01-09 13:13:35 +03:00
Nim
4366e940cb armor (#710) 2025-01-09 00:46:53 +03:00
Nim
76d828e9fd Мелочи фидбека (#709)
* things

* chees

* hmm

* tag

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2025-01-09 00:46:27 +03:00
Ed
00ecf1f4b6 Health alerts + Modular tools labeling renaming (#708)
* fix health alert

* grips label

* Update grips.yml
2025-01-08 23:22:58 +03:00
Ed
815c031a16 localization sync 2025-01-08 15:31:17 +03:00
Ed
8248fcb07e Events tweaks (#707)
* mosquito + outbreak markers

* Update comoss.yml

* Update monster.yml
2025-01-08 14:16:38 +03:00
Ed
228a7226ff Random events (#706)
* first game event! Closet skeleton!

* demiplane outbreak gamerules

* Update game_presets.yml

* d
2025-01-08 02:55:54 +03:00
Ed
5c21ec2774 fix 2025-01-07 23:41:42 +03:00
Ed
35eb0c48c1 Graves and Tombstones (#705)
* dirt grave

* Update grave.yml

* tombstone

* Update grave.yml
2025-01-07 18:08:47 +03:00
Ed
676b85b22b Update Goblin.xml 2025-01-07 00:24:00 +03:00
Ed
5f2583fab0 Goblin gameplay (#704)
* silva fix

* goblinoids
2025-01-06 23:10:42 +03:00
Ed
8892d3913d Tiefling gameplay (#703)
* tiefling damage mana

* tiefling spell

* tweaks
2025-01-06 17:08:49 +03:00
Ed
71e6bd4f24 Elf (#702) 2025-01-06 14:05:46 +03:00
Ed
b647583b7b Silva species gameplay difference (#701)
* plant growth spell, silva photosyntesis

* playable species guidebook

* fixes
2025-01-06 03:31:59 +03:00
Ed
ed75beb0fb New species: Silva (#700)
* base silva species

* markings

* Update silva.yml
2025-01-05 23:23:18 +03:00
Ed
fe43e51930 Elves are skinny now (#699)
* elf THICC

* Update elf.yml
2025-01-05 20:17:25 +03:00
Nim
9ea8111d9e angel statue (#696) 2025-01-05 19:10:33 +03:00
Ed
639db84a0b dayCycle prototipization (#694) 2025-01-05 19:08:35 +03:00
Ed
9f798b4f6c Sprint loadout action (#698)
* SpellStorage restruct

* Update CP14SpellStorageSystem.cs

* Sprint
2025-01-05 17:46:54 +03:00
Ed
be3064b99c Modular sprites auto coloring (#697)
* axe and dagger update

* more blade processing

* shovel and sickle

* sword

* gardes

* grips

* modular presets

* blade material modifiers

* modular spear blade

* balance sharp garde, add sturdy garde

* Update sturdy.yml
2025-01-05 04:01:31 +03:00
A.Ne.
9a8f66727f modular tool inspection (#683)
* modular tool inspection

* update
2025-01-04 23:43:51 +03:00
Nim
945e74b690 Holiday Gob (#691)
* gob

* festive system
2025-01-04 23:42:09 +03:00
Nim
fc1e9d2638 christmas hat (#695) 2025-01-04 23:34:59 +03:00
Ed
36d02fdf6e Magic spells code expansion (#692)
* split manacost in separate component

* stamina spells

* toggleable actions

* swap activeCasting on ActiveDoAfter

* remove dublication

* Update CP14SharedMagicSystem.ToggleableActions.cs

* EntityWoldTarget

* mana glove done

* fix spell scrolls interrupting

* fix cooldown problem

* clean up, edit stamina system
2025-01-04 21:35:59 +03:00
Ed
a6a4a8da3f Merge pull request #687 from crystallpunk-14/ed-22-12-2024-upstream
Swap to RU lang, + Upstream sync
2025-01-03 18:38:23 +03:00
Ed
be6c2754f9 Update bagel.yml 2025-01-03 18:37:44 +03:00
Ed
86e74a0fc2 Merge branch 'ed-22-12-2024-upstream' of https://github.com/crystallpunk-14/crystall-punk-14 into ed-22-12-2024-upstream 2024-12-30 15:06:39 +03:00
Ed
a75ac73c70 Merge remote-tracking branch 'upstream/master' into ed-22-12-2024-upstream 2024-12-30 15:05:05 +03:00
Ed
4011de828f Merge branch 'master' into ed-22-12-2024-upstream 2024-12-30 15:01:14 +03:00
Ed
5c9ea3f428 fix (#690) 2024-12-30 15:00:02 +03:00
Ed
de6ddb52be pulato (#689) 2024-12-30 13:58:53 +03:00
Viator-MV
3b53c1abbb map update (#688)
* Update comoss.yml

* Update comoss_d.yml

* Update comoss_d.yml

* Update comoss_d.yml

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2024-12-30 13:58:06 +03:00
Southbridge
4acfec8e36 Amber Station Overhaul (#34113)
* Step 01: Remade arrivals

* Nearly finished, also added new beacons and a holopad

* Wrapped up all changes, also added a beacon for the docking arm
2024-12-30 00:37:05 -07:00
Dylan Hunter Whittingham
608b433da4 Added ID entry for captain on Bagel (#34120)
added id for captain

Co-authored-by: dylanhunter <dylan2.whittingham@live.uwe.ac.uk>
2024-12-29 13:23:18 -07:00
Velcroboy
c2ffc25970 Adds kitchen/botany-locked maints airlock (#34116)
Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2024-12-29 21:14:36 +03:00
lzk
072b973f3b fix interdimensional teleporter desc (#34108)
Update hand_teleporter.yml
2024-12-28 22:28:58 -05:00
PJBot
da8bb996b1 Automatic changelog update 2024-12-29 03:26:46 +00:00
Velcroboy
d6a9fe1c84 Rolling joints no longer requires a filter (#34106)
* Remove filters from joint crafting

* err

* hmmm

* guhhh

* yyyy

* whitespace

---------

Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2024-12-28 22:25:39 -05:00
PJBot
a7ca552dfc Automatic changelog update 2024-12-29 02:03:31 +00:00
ArtisticRoomba
e07609b3b3 New cotton baguette, crostini, chevre-chaud, bagel, and croissant foods for moffs (#33508)
* A looooooooot of new cotton foods for the moffs

* address slam's comments on the food for moffs not having any moff food in the food (the food that's intended for moffs)

* alternative sprites for bagel-cottondough.png, baguette-cotton.png, and croissant-cotton.png

* update requested sprites

* change requested sprites

* address part of sloth's review, awaiting response

* address second half of review, fix magical food nutriment mitosis bug
2024-12-29 03:02:24 +01:00
Booblesnoot42
2c41ed0939 Corrected Cotton Dough Recipe (#33988) 2024-12-29 02:56:23 +01:00
PJBot
4bb68c4bac Automatic changelog update 2024-12-29 01:51:56 +00:00
SolStar
bfb256f0ba Add a guaranteed cotton pizza to pizza crates (#33997)
* add guaranteed cotton pizza to pizza crates

* saner parenting

* Use clearer suffix on cotton pizza box
2024-12-29 02:50:49 +01:00
PJBot
9f9553b526 Automatic changelog update 2024-12-29 01:50:11 +00:00
zHonys
5d0d37161d Added support so that smile can use hats (#33924)
* Added support so that smile can use hats

Changed Prototypes/Entities/Mobs/NPCs/pets.yml
Added smile_inventory_template.yml in Resources/Prototypes/inventoryTemplates
Added dir smile_displacement.rsi inside Resources/Textures/Mobs/Pets/smile.rsi
Added smile_displacement.rsi/meta.json
Added smile_displacement.rsi/head.png

* Fixed sprite path in ProtoTypes/Entities/Mobs/NPCs/pets.yml mapping to wrong smile_displacement.rsi
Fixed smile_inventory_template.yml using uiWindowPos as 1,2 instead of 0,1

Moved Resources/Textures/Mobs/Pets/smile.rsi/ to .../Pets/smile/smile.rsi/
Moved Resources/Textures/Mobs/Pets/smile.rsi/smile_displacement.rsi to .../Pets/smile/smile_displacement.rsi

* Minor fixes: removing comments and change naming

Renamed Resources/Textures/Mobs/Pets/smile/smile.rsi To .../Mobs/Pets/Smile/smile.rsi

* Removed smile_inventory_template.yml and used head_inventory_template.yml instead
2024-12-29 02:49:05 +01:00
github-actions[bot]
3f84b04e4c Update Credits (#34109)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-12-29 01:39:04 +01:00
PJBot
4155440a1b Automatic changelog update 2024-12-28 23:34:22 +00:00
chromiumboy
6c465153ab UI improvements for holopads (#34055)
* Initial commit

* Minor update
2024-12-29 00:33:15 +01:00
PursuitInAshes
01980cb0bf Removes weh.txt from Textures/Parallaxes (#34097)
Removes Unneeded File
2024-12-28 17:52:27 +01:00
PJBot
1b478d46f5 Automatic changelog update 2024-12-28 14:50:11 +00:00
psykana
616d34102b Traitor can no longer get multiple objectives to save/help/kill the same person (#33704)
* Deduplicate traitor objectives

* Remove redundant check
2024-12-28 15:49:03 +01:00
PJBot
b24ab38992 Automatic changelog update 2024-12-28 10:14:21 +00:00
Alpaccalypse
a21d8099a9 Removed Power Monitoring Computer boards from research and lathe recipes. Added default engineering sprites for atmos computer boards. (#34078)
* Defined sprites for Atmospheric Alerts and Monitoring computer boards. Added research unlocks and lathe recipes for them.

* Defined default engineering sprite for atmospherics computer boards. Removed Power Monitoring Computer board from research and lathe recipes.

* Defined engineering sprite for atmos computer boards. Removed Power Monitoring Computer board from research and lathe recipes.
2024-12-28 11:13:13 +01:00
lzk
d92ed75703 Fix wagging action name and desc (#34089) 2024-12-28 13:00:12 +03:00
Leon Friedrich
97dd5513f5 Ignore audio entities in SpawnAndDeleteEntityCountTest (#34021) 2024-12-28 11:54:32 +11:00
PJBot
9acce42f92 Automatic changelog update 2024-12-27 13:35:38 +00:00
Plykiya
860052c383 Fix popup on handcuffing for person being handcuffed (#33639)
* Fix popup on handcuffing for person being handcuffed

* wrap onto newlines to appease the style gods
2024-12-27 16:34:32 +03:00
PJBot
ca0596e6f1 Automatic changelog update 2024-12-27 12:35:38 +00:00
crazybrain23
34e9979dc5 Arrivals blacklist for bluespace lockers and QSIs (#34072)
* Ensure Arrivals Blacklist in Bluespace Locker rule

* While I'm at it, stop the QSI too

* fix thing I broke somehow

* Every bluespace locker arrivals blacklisted

* Add ArrivalsBlacklist to the prototypes too
2024-12-27 13:34:30 +01:00
PJBot
fab5dd178d Automatic changelog update 2024-12-26 22:48:31 +00:00
ArtisticRoomba
bf727b0ab6 Reinforced tables require welding to construct/deconstruct (#33992) 2024-12-26 16:47:22 -06:00
Emisse
52d39aac46 bagel update (#34073) 2024-12-26 00:06:48 -07:00
Southbridge
4b34dd672e Amber Station - Fixed evac shuttle screens (#34071)
Added Devicenetwork component to ensure the screens work
2024-12-25 19:43:53 -07:00
TytosB
392046fc70 Loop Station update and fixes (#34067)
* many changes

* contentingregrationtests

* serialized invalid removed

* blank

* "Changes and fixes as suggested"

* blank

* blank

* added desk bells

* engi rework rework rework

* added gate to content integration

* tweaks

* aaa

* bbb

* added holopads

* ccc

* Update default.yml

* hotfix

* aaa

* bbb

* many many tweaks and fixes

* aaa

---------

Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com>
2024-12-25 12:16:58 -07:00
Emisse
7803254b6f bagel update (#34062)
* bagel update

* fixgridatmos

* fdsafds
2024-12-25 00:08:35 -07:00
War Pigeon
4064d554d6 Link Core cargo shuttle atmos devices (#34061)
* Link Core cargo shuttle atmos devices

* Remove configurator lines

This matches what the DeviceNetworks in core.yml look like now. Hopefully it works?
2024-12-24 23:21:39 -07:00
Ed
94186c4a6b Update twoHandedStaffs.yml 2024-12-25 09:04:43 +03:00
PJBot
c83532ec3f Automatic changelog update 2024-12-24 02:26:10 +00:00
lzk
1cbc8c1dcc Allow to paint multiple airlocks (#34001)
* Allow to paint multiple airlocks

* oh right
2024-12-24 03:25:03 +01:00
github-actions[bot]
31aec7385d Update Credits (#33998)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-12-24 03:15:26 +01:00
crazybrain23
4e9862d01f Add crazybrain23 to CODEOWNERS (#34038)
Add myself to CODEOWNERS

Basically just added myself where Nik was since I am also doing headmin things.
2024-12-24 03:14:42 +01:00
PJBot
8fcfca689f Automatic changelog update 2024-12-24 00:25:26 +00:00
Ed
1c33073af4 Multiple items in loadouts (#33193)
* loadouts update

* Update loadout_groups.yml

* darts to candles

* Update Resources/Prototypes/Loadouts/dummy_entities.yml

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-24 01:24:19 +01:00
August Sun
39b2ce8cef Adds more air alarms and sensors throughout Oasis, linked unlinked air devices (#34046)
Adds more air alarms and sensors throughout Oasis

Co-authored-by: august-sun <45527070+august.sun@users.noreply.github.com>
2024-12-23 17:22:37 -07:00
Pieter-Jan Briers
285e9349b6 Fix race condition causing disconnected admins to appear in adminwho (#34033) 2024-12-24 11:18:31 +11:00
August Sun
2c4be6be00 Increases Marathon cryosleep size, added meteor shielding to Marathon chapelroid (#34044)
Increases Marathon cryosleep size, added meteor shielding to chapelroid

Co-authored-by: august-sun <45527070+august.sun@users.noreply.github.com>
2024-12-23 16:34:01 -07:00
PJBot
843a5de809 Automatic changelog update 2024-12-23 23:26:02 +00:00
Booblesnoot42
2dd99b5669 Removed protolathe from cargo on Amber (#34027) 2024-12-23 16:24:54 -07:00
Booblesnoot42
5d8e916cb2 Remove cog cargo protolathe (#34026)
* Removed protolathe from cargo on Amber

* Removed protolathe from cargo on Cog

* Revert "Removed protolathe from cargo on Amber"

This reverts commit 422db6e34a54c9256e3e1aad2098b64ff4cf0f96.

revert commit that should have been done on another branch
2024-12-23 16:24:47 -07:00
PJBot
030f97b2be Automatic changelog update 2024-12-23 19:55:25 +00:00
amatwiedle
b82605b185 Fix borgs being able to drink from buckets and spray bottles. (#32964)
* Added a check for if the entity trying to drink is a borg.

* Fixed missing namespace issue.

* Improved code conciseness.

* Removed borg chassis check, added stomach check.

* Removed unused namespace

---------

Co-authored-by: dankeaj <andrewjdanke@gmail.com>
2024-12-23 13:54:18 -06:00
Pieter-Jan Briers
f98192daff Fix the sensor monitoring console (#34035)
Still isn't really suitable to just map but at least it doesn't outright NRE anymore.

Alternative to #34032
2024-12-23 20:23:03 +01:00
Ed
661e96831f bruh 2024-12-23 22:13:38 +03:00
slarticodefast
dfc0e0199a minor fix to "silent footsteps for ninja" (#34040)
minor fix
2024-12-23 21:25:03 +03:00
PJBot
38bd2e5c1c Automatic changelog update 2024-12-23 14:25:20 +00:00
mubururu_
4ddd7d3c5f silent footsteps for ninja (#33280)
* waow

* nice suggestion

* nullable sound

* fix stuff

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-23 15:24:09 +01:00
slarticodefast
c873f90f6b Train: fix problematic atmos setup (#34018)
fix atmos setup
2024-12-22 13:41:35 -07:00
ScarKy0
f28c8127e2 Localized holopads for Box (#34011)
I love holopads
2024-12-22 12:56:30 -07:00
Pieter-Jan Briers
1450c4cade Specify privacy policy for Wizard's Den (#34013) 2024-12-22 17:12:37 +01:00
slarticodefast
2ff8238030 Merge stable into master (#34008) 2024-12-22 14:38:39 +01:00
Ed
4173d96d83 Merge remote-tracking branch 'upstream/staging' into ed-22-12-2024-upstream
# Conflicts:
#	Content.IntegrationTests/Tests/PostMapInitTest.cs
#	Content.IntegrationTests/Tests/ResearchTest.cs
#	Resources/Prototypes/Entities/Objects/Decoration/flora.yml
#	Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml
#	Resources/Prototypes/Maps/Pools/default.yml
2024-12-22 15:48:30 +03:00
Ed
6331379213 swap to RU 2024-12-22 15:45:16 +03:00
Errant
3358801b42 2024-12-20 Release "HoLoopad Holiday" (#34007) 2024-12-22 09:21:53 +01:00
Errant
58181c3412 adjust eshotgun recharge delay (#33996) 2024-12-22 09:02:55 +01:00
PJBot
1abe9db99c Automatic changelog update 2024-12-21 07:03:11 +00:00
Leon Friedrich
7baa1ae070 Update engine to v238.0.0 (#33980) 2024-12-21 18:02:04 +11:00
PJBot
b3551fb000 Automatic changelog update 2024-12-21 06:46:54 +00:00
Leon Friedrich
06e2bba8ab Toolshed refactor (#33598)
* Content changes for engine toolshed PR

* add contains command

* more permissive commands
2024-12-21 17:45:48 +11:00
metalgearsloth
b011dbb61e Update submodule to 237.4.0 (#33976) 2024-12-21 16:08:39 +11:00
metalgearsloth
9f4aa1ebe0 Implement some field-level deltas (#28242)
* Update GasTileOverlayState

* Update DecalGridState

* Update NavMapState

* poke

* poke2

* poke3

* Implement field deltas for guns

* Content done

* Update

---------

Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
2024-12-21 15:54:11 +11:00
PJBot
1f859167fd Automatic changelog update 2024-12-21 03:29:53 +00:00
JustinWinningham
12c5c7e91b Wood walls from barricades (#33902)
* Wood wall is now built from barricade congraph and on top of a barricade instead of using rods

* Fixed construction instructions for wooden wall

* Wood wall is now built from barricade congraph and on top of a barricade instead of using rods

* Fixed construction instructions for wooden wall

* fixed linter error

* Update Resources/Prototypes/Entities/Structures/Walls/walls.yml

Reasonable suggestion

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Structures/Walls/walls.yml

spelling error

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* removed ability to build wall from 'junk' wood barrier'

* fixed ability to pry overlay barricades and not allow them to extend to full wood walls

* renamed incorrectly named entity

* fixed default entity graph so as to not complain for unit tests

* corrected my incorrect assumptions and fixed destroy cost

---------

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-21 04:28:46 +01:00
PJBot
00f12e092a Automatic changelog update 2024-12-21 02:15:15 +00:00
ScarKy0
03a54e90f5 Increase syndicate uplink discount amount to 6. (#33950)
* Increase uplink discounts from 3 to 7

* nevermind, 6
2024-12-20 20:14:08 -06:00
PJBot
9a4f9561e6 Automatic changelog update 2024-12-20 22:35:50 +00:00
pocl v
3a917bcb56 Diona chirping & Nymph vocals (#32511)
* Adds chirping to adult diona

* Added vocals for diona nymph

* Nymphs now have a speechsound
2024-12-20 23:34:44 +01:00
PJBot
50cc90fb41 Automatic changelog update 2024-12-20 22:16:46 +00:00
lzk
919fdc0798 Add description of tool qualities to entity (#32436)
* Add description of tool qualities to entity

* LMAO I FORGOT FUCKING FTL FILE

* minor cleanup

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-20 23:15:40 +01:00
PJBot
bbceffac0e Automatic changelog update 2024-12-20 21:39:33 +00:00
AverageNotDoingAnythingEnjoyer
e4974cba25 Nanotrasen, Syndicate factions are now hostile to Dragons and Carps (#32515)
* Weh

Weh

* Now hostiles too!

Added Dragon to hostile factions for Hostiles

* Nah

Better not do this, I think
2024-12-20 22:38:27 +01:00
PJBot
a89d254425 Automatic changelog update 2024-12-20 21:28:04 +00:00
beck-thompson
a0a405768a Add clearer defib cooldowns! (#31251)
* First commit

* Fix silly test

* Swiched stuff up

* Update Content.Shared/Medical/DefibrillatorComponent.cs

* remove unneeded visuals

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-20 22:26:56 +01:00
PJBot
0e850ab370 Automatic changelog update 2024-12-20 20:36:01 +00:00
CaptainMaru
5a07413ef8 All hostile turret (#33970)
* All hostile turret

* Other factions are now hostile against "all hostile" too
2024-12-20 23:34:53 +03:00
Errant
1419b8868e combine licence files for StationEvents audio (#33972)
* merge licence files

* actual commit

* whoops
2024-12-20 21:51:03 +03:00
PJBot
f19377d6cb Automatic changelog update 2024-12-20 16:18:20 +00:00
VideoKompany
4c0a1348bd Fix communication console menu (#33655)
fix Communication console
2024-12-20 10:17:13 -06:00
PJBot
f4fd64756f Automatic changelog update 2024-12-20 14:37:03 +00:00
Piras314
34b906640f Remove Clearly Nuclear on Author's Request (#33971)
Revert "New Nukie Song (#25765)"

This reverts commit 806c0d162f.
2024-12-20 15:35:54 +01:00
metalgearsloth
a2912e3922 Add MovementSound (#31313)
Mainly useful for medicalborg so you can get a looping sound and not footsteps playing over and over.

Didn't actually update medborg because footsteps need updating.

Not needed for AI.
2024-12-20 14:51:17 +03:00
IProduceWidgets
864c2257b0 add man-o-war shuttle (#32105)
manowar
2024-12-20 14:36:23 +03:00
chromiumboy
39600f9516 Minor fixes for the holopad (#33969)
Initial commit
2024-12-20 13:51:00 +03:00
github-actions[bot]
7f2907a93a Update Credits (#33865)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-12-19 22:51:28 +01:00
August Sun
0462993153 Fixes/removes borg spawnpoint from Oasis Engineering, added one to Robotics (#33960)
removed borg spawnpoint from engineering, added one to robotics

Co-authored-by: august-sun <45527070+august.sun@users.noreply.github.com>
2024-12-19 13:02:35 -07:00
ArtisticRoomba
ee72cdacdc Update Fland for holopads (#33962)
* update fland for holopads

* fix duplicate holopad name
2024-12-19 12:55:41 -07:00
TytosB
fe69ef63f0 Loopstation hotfix (#33958)
Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com>
2024-12-19 20:26:14 +01:00
PJBot
ae5c1f5995 Automatic changelog update 2024-12-19 17:22:37 +00:00
Plykiya
7f6d55a1b6 Fix: Update armor crate description (#33414)
Update armor crate
2024-12-19 18:21:27 +01:00
chromiumboy
209c1769ee Tweaks for the holopad (#33928)
* Initial commit

* AIs get a warning when trying to answer long distance calls

* Better handling of ending telephone calls

* Fixed issue with duplicated holopad window when an AI answers a summons

* Changed how ranges are handled, added the bluespace holopad

* Bug fixes

* More bug fixes

* More bug fixes

* Update Resources/Prototypes/Entities/Structures/Machines/holopad.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Structures/Machines/holopad.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-19 18:20:20 +01:00
LevitatingTree
25980d8888 Remove plushie_lizard_mirrored.png (#33855)
* Remove plushie_lizard_mirrored.png

* Remove from meta.json

* Replace mirrored state from yml

---------

Co-authored-by: LevitatingTree <None>
2024-12-19 17:44:48 +01:00
PJBot
efa76be390 Automatic changelog update 2024-12-19 11:32:19 +00:00
Centronias
128721ee4e Logic Gate Compatibility with Non-Logic Signals bugfix (#33792)
:)
2024-12-19 12:31:13 +01:00
SpaceLizard
ef45c16667 Food Container Size Increase (#33842)
* Stuff

* hehe

* moar.
2024-12-19 13:15:48 +03:00
PJBot
2581c24bfe Automatic changelog update 2024-12-19 09:39:31 +00:00
TytosB
043510fb51 New mid pop station: Loop (#33697)
* many changes

* contentingregrationtests

* serialized invalid removed

* blank

* "Changes and fixes as suggested"

* blank

* blank

* added desk bells

* engi rework rework rework

* added gate to content integration

* tweaks

* aaa

* bbb

* added holopads

* ccc

* Update default.yml

---------

Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com>
2024-12-19 02:38:22 -07:00
ArtisticRoomba
66ea113eda Omega Power Rebalance (#33956)
* fix packed power

* Revert "fix packed power"

This reverts commit 4f44d0673e0a597bea39c594f5b7ace3069433ea.

* fic the entire thing again
2024-12-18 22:13:01 -07:00
ArtisticRoomba
c1b229aea5 Packed Power Rebalance + Gas Sensors Adjustments (#33955)
* fix packed power

* fix that

* fix that as well

* even more fixes

* fix power, again
2024-12-18 20:48:14 -07:00
ArtisticRoomba
28fa7cedc7 Meta Power Rebalance + Gas Pipe Sensors, Holopads (#33949)
power fixes, sensors, dim lights
2024-12-18 18:05:06 -07:00
Southbridge
943be3e75c Amber Statio - Localized Holopads and Balance Updates (#33948)
* Added loc versions of holopads to Amber, and made some adjustments given Acorn's feedback

* fixed the name of the gameroom

* Fixed it in the map file
2024-12-18 17:52:46 -07:00
Spanky
e7d5ab67ec Omega Update (Localized Holopads) (#33946)
* Omega Update (Localized Holopads)

Replaced all holopads with localized versions and a couple tiny misc

* Remove engi protolathe

* Forgot to rename engi fax whoops
2024-12-18 17:52:35 -07:00
PJBot
e70a3b8a21 Automatic changelog update 2024-12-19 00:47:43 +00:00
ArtisticRoomba
9de569d973 Show battery level for selected devices in Power Monitoring Console (#33854)
* Use class instead of out variables

* Show battery level in power monitoring console

* Better color contrast for battery level + localized string

* Add visualization to battery percentage

* Reverts random ChatSystem.cs whitespace change

* Address review

* Show BatteryLevel stats in child view when selecting devices

---------

Co-authored-by: Crotalus <crotalus@users.noreply.github.com>
2024-12-19 01:46:36 +01:00
Winkarst
f7bf694707 Comment LogTypes (#33497)
* Comment LogTypes

* Uncomment unused types

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
2024-12-19 01:18:04 +01:00
PJBot
383ecdd70f Automatic changelog update 2024-12-19 00:13:07 +00:00
Hannah Giovanna Dawson
c33d3350bd [Christmas] Y'all want a Smite Cranberry? (#33922)
* Add a festive lemon-lime soda variant: cranberry!

* Gave lemon-lime a brand name

* Make the CrateFoodSoftdrinksLarge slightly larger to accomodate the extra drinks.

* Extend the Christmas anomaly with extra jolliness

* Minor spelling mistake. Jollyness will not be denied.

* Removed redundant delay from meta file
2024-12-19 01:11:59 +01:00
Spanky
8f36d7d1c8 Reach/Cargo Update (Holopads & Atmos) (#33943)
* Reach/Cargo Update

Adds holopads and new atmos tech to Reach, and replaces cargo shuttle/ATS holopads with localized versions.

* Fix Invalid

invalidinvalidinvalidinvalidinvalidinvalid
2024-12-18 16:29:21 -07:00
ScarKy0
fa6de41ae9 Localized holopads + atmos network for Oasis (#33941)
Oasis stuff
2024-12-18 16:10:53 -07:00
Spanky
6f42ebf206 Packed Update (Holopads & Engi Stuff) (#33940)
Packed Holopad & Engi Update

Added holopads, atmos network monitor and sensors, advanced SMES, and revamped TEG setup.
2024-12-18 15:42:01 -07:00
ScarKy0
18de5ea986 Localized holopads for Bagel (#33934)
* Stuff

* Requested changes
2024-12-18 14:45:12 -07:00
ArtisticRoomba
52117fdc13 Marathon Power Rebalance + Gas Pipe Sensors, Holopads (#33938)
* fix marathon power

* add holopads

* add requested changes
2024-12-18 14:28:46 -07:00
ScarKy0
8a0edad886 Localized holopads for Cog (#33937)
* coggers

* Requested changes
2024-12-18 13:54:09 -07:00
PJBot
4fe69f2383 Automatic changelog update 2024-12-18 16:33:03 +00:00
ArtisticRoomba
345adcd5d0 New Drazil plushie (inverse lizard plushie) (#33776)
* Hew

* properly attribute hew.ogg

* add to maints locker plushie pool with low chance, clear up grammar

* shhhh nobody saw that linter failure

* adds localization support for Weh and Hew emotes

* fix capitalization error present since circa 2/25/2024

* resolve conflicts, fix sprite, add reversed inhands

* clear up cursed formatting
2024-12-18 17:31:55 +01:00
Ed
18fe8b9df0 Sprite Movement working with AI movement (#33494)
* FINALLY

* Update animals.yml
2024-12-18 17:15:34 +01:00
PJBot
b649517a17 Automatic changelog update 2024-12-18 15:14:46 +00:00
RedBookcase
c1558f689f Mercenary gear contraband tweaks. (#33647)
* Mercenary gear contraband tweaks.

* Fixed Mercenary Combat Gloves to have basic Combat Gloves as a parent again.

* Update Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml

---------

Co-authored-by: RedBookcase <Usualmoves@gmail.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-18 16:13:40 +01:00
PJBot
97a2e0deef Automatic changelog update 2024-12-18 15:06:22 +00:00
SlamBamActionman
659bc8f2de Replace Cellular Slime mob damage with Caustic (#33104)
Cellular gone
2024-12-18 16:05:15 +01:00
Nim
868699a219 More beer, wine and ale (#686)
* more beer

* ru

* comoss fix update, loc change to eng

* Update dwarf.yml

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
2024-12-18 17:37:06 +03:00
PJBot
d01839a990 Automatic changelog update 2024-12-18 14:28:05 +00:00
MilenVolf
8359541706 Fix hugging buckled mobs instead of unbuckling (#33635)
* Check buckle.BuckledTo value before hugging interaction

* Make InteractHandEvent to be used by BuckleSystem before InteractionPopupSystem instead of after
2024-12-18 15:26:58 +01:00
PJBot
337ef6c5aa Automatic changelog update 2024-12-18 13:16:13 +00:00
slarticodefast
e7294bdf4f Only disable panicbunker for admins with AdminFlags.Admin (#33879)
* Only disable panicbunker for admins with AdminFlags.Admin

* nicer curly braces
2024-12-18 14:15:04 +01:00
Centronias
6b99493e80 Reduce network burden of the hunger system (#32986)
* reduce network burden of the hunger system

* explicit start + last updated

* remove auto reformat changes to otherwise untouched code

add clamp helper

* imagine making breaking changes, documenting them, and then not thinking to check the yaml

* comments

* Remove unused net manager in hunger system
Remove lastAuthoritativeHungerValue from prototypes
2024-12-18 14:06:02 +01:00
ScarKy0
87f39af1cf Holopad prototypes for mapping (#33931)
* Init

* fix

* Atmosn't

* ID fixes

* locale
2024-12-18 12:38:00 +01:00
PJBot
94594debf3 Automatic changelog update 2024-12-18 11:27:28 +00:00
lzk
6c925d2c82 Make safes craftable (#32694)
* Made the Armory Gun Safe craftable with 10 steel, 10 plasteel, and 5 LV cables.

* Changed gun safe price to 335, to match the cost of its material components. Changed gun safe to start with no accesses when constructed.

* adress the review

* yeah

* wrah

* test fail is not real

---------

Co-authored-by: Ty Ashley <42426760+TyAshley@users.noreply.github.com>
2024-12-18 12:26:19 +01:00
ArtisticRoomba
1c0db473bc Fland Power Rebalance + Gas Pipe Sensors (#33933)
fix fland power
2024-12-18 04:09:50 -07:00
ArtisticRoomba
9f0a8aac7d Cog Power Rebalance + Holopads, Gas Pipe Sensors (#33930)
* fix cog power

* double fix cog power

* trial 3

* fourth go

* i stopped counting
2024-12-18 02:52:21 -07:00
Spanky
50fddd0804 Cargo Shuttle/ATS Update (#33927)
Update Cargo Shuttle/ATS

Adds holopads to the cargo shuttle and ATS. Also replaces the blast door buttons on the cargo shuttle with locked variants.
2024-12-18 01:37:56 -07:00
ArtisticRoomba
42f7279f52 Box Power Rebalance + Holopads, Gas Pipe Sensors (#33929)
* fix power

* Rebalance power, add holopads, add pipenet sensors

* recolor that one pipe I missed + remove invalids

* resave map, if this fails tests one more time, no more cake
2024-12-18 01:17:48 -07:00
Spanky
8b0b822207 Omega Update (Holopads & Engi Stuff) (#33926)
Omega Update

Add holopads, atmospheric network monitors & sensors, and advanced SMES's.
2024-12-17 22:55:09 -07:00
ArtisticRoomba
91b85be1a4 Bagel Power Rebalance + Gas Pipe Sensors (#33925)
* Balances bagel power

* Adds gas pipe sensors

* remove invalids :)
2024-12-17 21:45:50 -07:00
Southbridge
122e307694 Amber Station - Added Holopads, Atmos Monitoring, and Advanced SMESes (#33923)
* Added holopads and atmos network monitoring.

* Added the advanced SMESes to the station and evac shuttle

* Removed an accidentally mapped vox air alarm

* Fixed invalids in the escape shuttle
2024-12-17 21:44:29 -07:00
PJBot
ecc2edea6d Automatic changelog update 2024-12-18 00:13:41 +00:00
slarticodefast
908e476643 Fix admins not being able to health scan slimes (#33884) 2024-12-18 01:12:35 +01:00
Tiniest Shark
aaec1e684e Ground Light Post Crafting Description Fix (#33920)
Updates ground light post's crafting description
2024-12-18 01:03:45 +01:00
PJBot
5863cfc78a Automatic changelog update 2024-12-18 00:00:00 +00:00
ArtisticRoomba
e7330ece9c Adds Advanced SMES, an SMES with higher capacity for mapping (#33757)
* Adds Advanced SMES machine and board to autolathe roundstart

* Make Advanced SMES T2 Advanced Powercells research, reduce cost, remove from random spawner, add sprites by augustsun

* fix attribution formatting

* Update smes.yml to address review

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>

* add new sprites and change naming scheme, testing something

* address review, tested it a bit more, works ingame

---------

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
2024-12-18 00:58:53 +01:00
PJBot
27cb17f865 Automatic changelog update 2024-12-17 23:57:11 +00:00
Golinth
a9cf54aca8 Fix AME power generation (#32825)
* Change AME power generation

* Fix negative power, change formula slightly
2024-12-18 00:56:02 +01:00
slarticodefast
984b29082d Update PR size labeler line counts (#33915)
new numbers
2024-12-18 00:40:49 +01:00
ScarKy0
a55d26eb8b Holopads + Atmos Network Console for Bagel (#33921)
Holopads!
2024-12-17 16:17:37 -07:00
Ed
8fbaffe2e7 Gate map: Holopads added (#33918)
Update gate.yml
2024-12-17 14:37:19 -07:00
Myra
77a4cda8bc Master merge: Fix horrible lag in Zombies mode (#33818) (#33917) 2024-12-17 20:19:31 +00:00
psykana
59e955a559 Fix horrible lag in Zombies mode (#33818) 2024-12-17 21:16:05 +01:00
Saphire
3fe576b4c9 Merge main and stable back together 2024-12-18 01:59:46 +06:00
Myra
fb6e85e87e Test can now run on stable prs (#33914)
Make tests also run on stable and staging
2024-12-17 20:40:57 +01:00
PJBot
616ddc1776 Automatic changelog update 2024-12-17 19:19:23 +00:00
chromiumboy
7780b867ac Holopads (#32711)
* Initial resources commit

* Initial code commit

* Added additional resources

* Continuing to build holopad and telephone systems

* Added hologram shader

* Added hologram system and entity

* Holo calls now have a hologram of the user appear on them

* Initial implementation of holopads transmitting nearby chatter

* Added support for linking across multiple telephones/holopads/entities

* Fixed a bunch of bugs

* Tried simplifying holopad entity dependence, added support for mid-call user switching

* Replaced PVS expansion with manually networked sprite states

* Adjusted volume of ring tone

* Added machine board

* Minor features and tweaks

* Resolving merge conflict

* Recommit audio attributions

* Telephone chat adjustments

* Added support for AI interactions with holopads

* Building the holopad UI

* Holopad UI finished

* Further UI tweaks

* Station AI can hear local chatter when being projected from a holopad

* Minor bug fixes

* Added wire panels to holopads

* Basic broadcasting

* Start of emergency broadcasting code

* Fixing issues with broadcasting

* More work on emergency broadcasting

* Updated holopad visuals

* Added cooldown text to emergency broadcast and control lock out screen

* Code clean up

* Fixed issue with timing

* Broadcasting now requires command access

* Fixed some bugs

* Added multiple holopad prototypes with different ranges

* The AI no longer requires power to interact with holopads

* Fixed some additional issues

* Addressing more issues

* Added emote support for holograms

* Changed the broadcast lockout durations to their proper values

* Added AI vision wire to holopads

* Bug fixes

* AI vision and interaction wires can be added to the same wire panel

* Fixed error

* More bug fixes

* Fixed test fail

* Embellished the emergency call lock out window

* Holopads play borg sounds when speaking

* Borg and AI names are listed as the caller ID on the holopad

* Borg chassis can now be seen on holopad holograms

* Holopad returns to a machine frame when badly damaged

* Clarified some text

* Fix merge conflict

* Fixed merge conflict

* Fixing merge conflict

* Fixing merge conflict

* Fixing merge conflict

* Offset menu on open

* AI can alt click on holopads to activate the projector

* Bug fixes for intellicard interactions

* Fixed speech issue with intellicards

* The UI automatically opens for the AI when it alt-clicks on the holopad

* Simplified shader math

* Telephones will auto hang up 60 seconds after the last person on a call stops speaking

* Added better support for AI requests when multiple AI cores are on the station

* The call controls pop up for the AI when they accept a summons from a holopad

* Compatibility mode fix for the hologram shader

* Further shader fixes for compatibility mode

* File clean up

* More cleaning up

* Removed access requirements from quantum holopads so they can used by nukies

* The title of the holopad window now reflects the name of the device

* Linked telephones will lose their connection if both move out of range of each other
2024-12-17 20:18:15 +01:00
Errant
bbf5369f14 Core - remove vox box (#33911)
remove Core vox box
2024-12-17 20:08:22 +01:00
Errant
332f870304 Oasis - remove vox box (#33912)
remove oasis vox box
2024-12-17 20:07:27 +01:00
slarticodefast
0fc2cca10c HOTFIX: Add [MRP] tag to the hostname for Salamander (#33909) 2024-12-17 14:37:53 +01:00
PJBot
ab8447956c Automatic changelog update 2024-12-17 13:36:36 +00:00
Tiniest Shark
32164c2ab8 Anomaly Scanner In-hand Sprites (#33427)
* Adds in-hand sprites to the Anomaly Scanner.

* Revert "Adds in-hand sprites to the Anomaly Scanner."

This reverts commit 257efd032a15d6459043f47106bd537abfe18fad.

im very stupid and need to undo my dumb commit.

* okay actually making sure these are committed this time like a smart boi

* Better version of the sprites based off of /tg station's health analyzer.

* Updated copyright to include link to sprite

* Updated copyright license and commit link

* Update Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/meta.json

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

* Update Resources/Textures/Objects/Specific/Research/anomalyscanner.rsi/meta.json

Aeshus adjusted indentation to better match original file.

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

---------

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>
2024-12-17 14:35:23 +01:00
PJBot
0d31b8c37a Automatic changelog update 2024-12-17 11:57:55 +00:00
Patrik Caes-Sayrs
8f2d16aabf Zombies keep their anomalies on zombification (#33867)
* Zombies keep their anomalies on zombification

* Refactor anombies to isolate anomalies and zombies

InnerBodyAnomalies now send an event when the host dies.
Zombies cancels this event if the host is turning into a zombie.

* Anomazombies: deprecate CancellableEntityEventArgs

CancellableEntityEventArgs is deprecated. Use structs
with bool Cancelled instead.
2024-12-17 14:56:47 +03:00
PJBot
67e5cc2104 Automatic changelog update 2024-12-17 10:07:40 +00:00
Ed
a77fcdec76 Gate map (#32032)
* import

* remove perma asteroid

* remove cyrillic

* ok

* Remove Chromite island, Move AI, add cameras

* remove mapped garbage

* add station anchors

* admeme teleporter

* remove wapr points, add nav beacons

* telecomm, camera servers, some atmos fix

* crew server

* remove white plating, fix MANY pipestacking

* playtest bugs fixing

* big update

* bunch minor fixes

* Update gate.yml

* out of rotation
2024-12-17 13:06:33 +03:00
Southbridge
d90f6ce086 Amber station updates (#33899)
* Fixed various issued identified during playtests.

* Fixed a firelock stuck closed

* Added more cameras and moved others

* Fixed an issue with disposals

* Modified the map a bit after watching some matches and listening to feedback

* Reworked sec some more. Moved perma out into its own separate ship (another design from Frontier) Also performed various improvements to the station.

* Added final touches, ready to PR

* Added some more loot rooms throughout the map

* Changed up some areas in maints that I didn't like

* Removed footprints outside detective's room and wrenched down the logic gates in the ship building airlock

* I totally didn't forget to add the lights
2024-12-16 23:43:55 -07:00
PJBot
038ba39b97 Automatic changelog update 2024-12-17 03:54:23 +00:00
chromiumboy
27e59d35fb Atmospheric network monitor (#32294)
* Updated to latest master version

* Added gas pipe analyzer

* Completed prototype

* Playing with UI display

* Refinement of the main UI

* Renamed gas pipe analyzer to gas pipe sensor

* Added focus network highlighting and map icons for gas pipe sensors

* Added construction graph for gas pipe sensor

* Improved efficiency of atmos pipe and focus pipe network data storage

* Added gas pipe sensor variants

* Fixed gas pipe sensor nav map icon not highlighting on focus

* Rendered pipe lines now get merged together

* Set up appearance handling for the gas pipe sensor, but setting the layers is bugged

* Gas pipe sensor lights turn off when the device is unpowered

* Renamed console

* The gas pipe sensor is now a pipe. Redistributed components between it and its assembly

* AtmosMonitors can now optionally monitor their internal pipe network instead of the surrounding atmosphere

* Massive code clean up

* Added delta states to handle pipe net updates, fixed entity deletion handling

* Nav map blip data has been replaced with prototypes

* Nav map blip fixes

* Nav map colors are now set by the console component

* Made the nav map more responsive to changes in focus

* Updated nav map icons

* Reverted unnecessary namespace changes

* Code tidy up

* Updated sprites and construction graph for gas pipe sensor

* Updated localization files

* Misc bug fixes

* Added missing comment

* Fixed issue with the circuit board for the monitor

* Embellished the background of the console network entries

* Updated console to account for PR #32273

* Removed gas pipe sensor

* Fixing merge conflict

* Update

* Addressing reviews part 1

* Addressing review part 2

* Addressing reviews part 3

* Removed unnecessary references

* Side panel values will be grayed out if there is no gas present in the pipe network

* Declaring colors at the start of some files

* Added a colored stripe to the side of the atmos network entries

* Fixed an issue with pipe sensor blip coloration

* Fixed delay that occurs when toggling gas sensors on/off
2024-12-17 04:53:17 +01:00
PJBot
f4765260cb Automatic changelog update 2024-12-16 19:24:38 +00:00
Ed
36c676741f Christmas anomaly (#33889)
* santa anomaly

* Update anomaly.yml

* injection

* Update anomaly.yml

* Update Resources/Locale/en-US/anomaly/inner_anomaly.ftl

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>

* Update Resources/Textures/Structures/Specific/Anomalies/Cores/santa_core.rsi/meta.json

Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>

* Update Resources/Textures/Structures/Specific/Anomalies/santa_anom.rsi/meta.json

Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>

---------

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
2024-12-16 22:23:31 +03:00
Ed
af7e552d3c Flora clean up (#33839)
* first migrate

* clean up prototypes

* Update polymorph.yml

* Update flora.yml

* and this one

* and this one x2

* and this one x3

* Update migration.yml
2024-12-16 20:20:36 +01:00
PJBot
9eda08cd12 Automatic changelog update 2024-12-16 18:53:16 +00:00
beck-thompson
74e9576e66 Figures can now be activated remotely (#32769)
* First commit

* I'm silly

* weh

* will this work?

* Better design

* Fixes!

* rider :(

* L rider
2024-12-16 19:52:09 +01:00
PJBot
001b0edc7e Automatic changelog update 2024-12-16 17:54:45 +00:00
goet
db69ae67fe Spaceshroom grilling (#31872)
* make spaceshroom cookable on grill

* remove microwave recipe
2024-12-16 18:53:38 +01:00
Intoxicating-Innocence
2ccd471388 Chem master UI (#33328)
* chemmaster buffer has colors now

* I have saved chemists everywhere

* implimented panelcontainers instead of labels, slight visual rework

* added UI changes to input buffer

* fixed some unsightly indentation on brackets and removed redundant minheight specification from verticalstretch elements

* Formatting and code cleanup

* pills still not rendering correctly

* more tinkering, entities finally display correctly

* entities display correctly, pill fields default to max now

* fixed stripes

* fixed excess pillCount bug

* removed cache, fixed tab swapping

---------

Co-authored-by: Saphire <lattice@saphi.re>
2024-12-16 18:17:06 +01:00
PJBot
74f873a9f7 Automatic changelog update 2024-12-16 16:28:47 +00:00
Vexerot
17e3ef32b7 Add Explosion Resistance to SecBelts (#33253)
Added explosion resistance to secbelt
2024-12-16 17:27:40 +01:00
PJBot
c35505c6b4 Automatic changelog update 2024-12-16 15:34:39 +00:00
SlamBamActionman
95328dab68 Add Holy damage (#32755)
* Initial commit

* hoili moili

* now to add sherlock and doctor who

* funny stick

* Oops it was meant to be called metaphysical

* Attribution

* Even BETTER attribution
2024-12-16 16:33:32 +01:00
PJBot
046dde7717 Automatic changelog update 2024-12-16 15:26:13 +00:00
dragonryan06
1e80dd2891 Add the Zombie, a new cocktail (#32802) 2024-12-16 16:25:06 +01:00
PJBot
782a2978f0 Automatic changelog update 2024-12-16 14:20:21 +00:00
deathride58
d8afcdcdf0 Makes admins not count towards the playercount cap (#33424)
* Makes admins not count towards the playercount cap

* Update Content.Shared/CCVar/CCVars.Admin.cs (thx Aeshus

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

* Actually fixes whitespace on the comments
Thanks VScode very good IDE

---------

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>
2024-12-16 17:19:15 +03:00
PJBot
1368092d43 Automatic changelog update 2024-12-16 14:15:57 +00:00
KieueCaprie
881e4d3432 Add an in-hand sprite for the lizard plushie (#32583)
* add hold sprites for lizard plushie

* make the lizard plushie sprites slightly chonkier for those who are not wearing winter clothes.

* me when i hit the noise button and pretend it's shading.

* lizard plushie is not legally-distinct green dinosaur with a long tongue™ (front sprite tongue has been shortened)

* update meta.json
2024-12-16 17:14:51 +03:00
PJBot
2a6800f354 Automatic changelog update 2024-12-16 14:10:28 +00:00
Preston Smith
01c1d8f824 Prevent pulling when teleporting (#33252)
* No more teleporting pulling

* pulled dash

* Update Content.Shared/Ninja/Systems/DashAbilitySystem.cs

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Content.Server/Implants/SubdermalImplantSystem.cs

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-16 17:09:17 +03:00
PJBot
852b3e9bb6 Automatic changelog update 2024-12-16 12:54:28 +00:00
Baa
1f42413416 Fix udder wooly reagent creation V2 (#32905)
* Changed comments to be more clear and uniform.
EggLayer uses NextGrowth instead of frame accumulation.
Egglayer uses much less energy to make eggs, and lay time is randomized for player and AI chicken.

* UdderComponent ReagentId can be changed now
UdderSystem and WoolySystem use SharedSolutionContainerSystem now

* Entities with udders can be examined to see a rough hunger level
udders and wooly stop reagent generation/extra nutrient usage once the solution container is full

* Moved stuff to Shared
AutoPausedField now

* Cleanup moving stuff to Shared

* Oops. Make UdderSystem sealed instead of abstract.

* Switch PopupEntity for PopupClient

* Didn't mean to delete Access

* new() instead of default! prototype
revert egglayer balance change
NextGrowth += timespan   in egglayer

* forgot [Datafield] for NextGrowth

* forgot NetworkedComponent again...

* Renaming Shared Animal to Shared Animals to match Server
Hopefully also resolve merge conflicts.

* Fix incorrect filename

* Update with requested changes
Put UdderSystem dependencies in alphabetical order.
Initialise NextGrowth for Udder and Wooly components on MapInitEvent.
Clean-up EggLayerSystem a little.
Re-write OnExamine function for UdderSystem, improving clarity.
Add full stops to end of udder examine locales.
And more :)

* Add some additional descriptions for cow hunger levels.

* Add Udder and Wooly quantity to AutoNetworkedField

* Account for less than starving threshold.

---------

Co-authored-by: sirionaut <sirionaut@gmail.com>
Co-authored-by: Sirionaut <148076704+Sirionaut@users.noreply.github.com>
Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
2024-12-16 13:53:21 +01:00
PJBot
d5323332a6 Automatic changelog update 2024-12-16 12:34:40 +00:00
Tayrtahn
cf738857fe Add a test to check that lathe recipes are possible (#33868)
* Add a test to check that all lathes accept the materials for all their recipesy

* Add check for storage limit

* Track total recipe material volume

* Check dynamic and emag recipes too

* Move AllLatheRecipesValidTest from ResearchTest to LatheTest

* Extremely minor modernization
2024-12-16 13:34:02 +01:00
beck-thompson
196782774b Add generator scrap (Plasma / uranium scrap) (#32198)
* First commit

* Forgot the shading!

* tweaked  values

* sprite update

* Radiation
2024-12-16 13:33:34 +01:00
metalgearsloth
386e431ea7 LightOnCollide entityquery (#33886) 2024-12-16 13:24:00 +01:00
deltanedas
2635888b6a add SpawnTableOnUse (#32620)
* add SpawnTableOnUse

* make BaseEmitSound more flexible and remove sound from spawntable

* add log

* :trollface:

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-12-16 15:23:14 +03:00
ActiveMammmoth
cd23805750 Wizard Mind Swap Spell (#33416)
* working mind swap spell

* Removing unncessary spacing

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

* Changing mind swap speech

Co-authored-by: keronshb <54602815+keronshb@users.noreply.github.com>

* All requested changes in review

* Stores owned by mind instead of body

* Requested changes, traitor uplink fixed

* Revert "Requested changes, traitor uplink fixed"

This reverts commit 2ceac6733d6a28890f60d2ccef3dafa160a702fd.

* Revert "Stores owned by mind instead of body"

This reverts commit dfb72ab70ed66db50312617f2dce02d0a4e4dfce.

* Separate target and performer stun duration

---------

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>
Co-authored-by: keronshb <54602815+keronshb@users.noreply.github.com>
2024-12-16 15:12:45 +03:00
PJBot
612f8bedab Automatic changelog update 2024-12-16 12:09:14 +00:00
Plykiya
a4d6f09a4f Cluster grenade refactor and contra markings (#31108)
* Cluster grenade refactor

* oopsies on the name

* Solve client-side errors

* reviews addressed

* filling scattering grenades is now predicted

* reviews addressed
2024-12-16 13:08:07 +01:00
TGRCDev
1266b05b02 Bug fixes for Store UIs with multiple currencies (#33565)
Fixed stores with multiple currencies having bad formatting and non-functional withdraw screens
2024-12-16 14:57:11 +03:00
PJBot
51a45ae640 Automatic changelog update 2024-12-16 11:54:25 +00:00
PJBot
e0a1db6e45 Automatic changelog update 2024-12-16 11:53:18 +00:00
psykana
5e8db16660 Zombies can see Initial Infected (#33665)
* Zombies can see Initial Infected

* Update zombie character info text
2024-12-16 14:53:13 +03:00
Litraxx
46d288cc39 Rename Dungeon Master Laws to not run into copyright problems (#33678)
* Rename Dungeon Master Laws to not run into copyright problems

* Revert direct map changes

* Added renaming of DungeonMasterCircuitBoard to migration.yml

* Remove whitespace changes to oasis.yml

---------

Co-authored-by: Litrax <email@emal.com>
2024-12-16 14:52:03 +03:00
Nim
a248c176ae Crane barrel (#672)
* crane barrel

* fix

* sprite resize, file rename

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2024-12-16 11:43:29 +03:00
Ed
862df73ff2 Demiplane modifiers groups & tiers (#678)
* data setup

* demiplanes modficators combine refactor

* generationProb

* demiplane tiers setup

* migration, and t2 loots

* t2 balance tweaks

* retags

* weather modifiers group

* maplight modifiers

* more passed checks

* wanderer buy positions localization fix

* fixes
2024-12-16 00:38:29 +03:00
Tayrtahn
5958801182 Separate RGlass recipe for autolathe and ore processor (#33876) 2024-12-15 22:02:32 +01:00
A.Ne.
57a795261f mithril and lucens modular parts (#682)
Co-authored-by: Ed <edwardxperia2000@gmail.com>
2024-12-15 22:40:05 +03:00
Ed
e102b5011e Merge remote-tracking branch 'origin/map-upate' 2024-12-15 22:17:29 +03:00
Viator-MV
35c45e70f6 Christmas map (#681)
* Update comoss.yml

* Update comoss_d.yml
2024-12-15 22:11:38 +03:00
A.Ne.
f655f74b03 mithril and lucens (#660)
* mithril and manarium

* Rename manarium to Lucens

* pointlight to tree

* lucens tile

* Update trees.yml

* logs sprite

* Update trees.yml

* delete acacia tiles, recolor lucen example

* tiles new palette

* Update ores.yml

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>

* tiles update

* Update tiles.ftl

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
2024-12-15 12:53:31 +03:00
PJBot
102d4fbc95 Automatic changelog update 2024-12-14 16:04:27 +00:00
Nim
df7b9d1e04 Other colour of the binary channel (#33841)
* radio

* color 2

* console-announcement

* 5ed7aa
2024-12-14 17:03:18 +01:00
Southbridge
7d82d2d5da Amber station updates (#33845)
* Fixed various issued identified during playtests.

* Fixed a firelock stuck closed

* Added more cameras and moved others

* Fixed an issue with disposals

* Modified the map a bit after watching some matches and listening to feedback

* Reworked sec some more. Moved perma out into its own separate ship (another design from Frontier) Also performed various improvements to the station.

* Added final touches, ready to PR
2024-12-14 16:59:43 +01:00
Errant
a3fc690236 Cherry-pick to stable: Amber Station - Playtest Fixes (#33773) (#33811)
Amber Station - Playtest Fixes (#33773)

* Fixed various issued identified during playtests.

* Fixed a firelock stuck closed

* Added more cameras and moved others

* Fixed an issue with disposals

Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com>
2024-12-14 16:40:21 +01:00
Ed
58269bb65e Snowballs (#677)
* snowballs

* biome update

* fixes
2024-12-14 14:57:15 +03:00
PJBot
744b105fc6 Automatic changelog update 2024-12-13 23:01:52 +00:00
godisdeadLOL
06071a5d8a Secret stash wrench anchoring fix (#31779)
* secret stash wrench fix

* fix

* cleanup

---------

Co-authored-by: YourUsername <you@example.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-14 00:00:45 +01:00
Ed
d7d0977eb6 New year preparation (#674)
* garland

* presents filter

* vladimirs weather

* snowed tilebrick
2024-12-14 01:01:36 +03:00
Ed
4cea96f6eb Garland (#673)
* garland

* presents filter
2024-12-13 22:20:00 +03:00
Ed
e30c5848c5 Update crates.yml 2024-12-13 17:55:54 +03:00
Ed
c9d2b8fb2b remove footprints (#670) 2024-12-13 17:33:42 +03:00
PJBot
2c00abbcae Automatic changelog update 2024-12-13 14:25:41 +00:00
Southbridge
7eb714d38f Monospace Support for Rich Text (#33830)
* Initial Commit

* Moved all this to SS14 on it's own

* Added prototype validation
2024-12-13 15:24:34 +01:00
Ed
e1f67be2a8 Snowdrifts (#669)
* snowdrifts

* Update fire.png

* alerts sprite optimize

* Update wooden.png

* stone wall fix
2024-12-13 16:59:37 +03:00
PJBot
e704f4e9a8 Automatic changelog update 2024-12-13 13:55:04 +00:00
LevitatingTree
b46f487503 Add meat tag to Five Alarm Burger (#33848)
* Add meat tag to Five Alarm Burger

* Revert "Add meat tag to Five Alarm Burger"

This reverts commit e483b5effe63a8cbdcce81eeddc622f5555ae240.

* Re-add tag, but in notepad

* Move tag down to follow hierarchy

---------

Co-authored-by: LevitatingTree <None>
2024-12-13 14:53:56 +01:00
Ed
3f8757dec9 Update migration.yml 2024-12-13 15:06:10 +03:00
PJBot
9329fcf32e Automatic changelog update 2024-12-13 03:11:29 +00:00
lzk
115b3e0519 Increase war ops evac time (#33628) 2024-12-12 21:10:20 -06:00
Ed
eb76a9ef6a Ed 12 12 2024 bugfixes (#668)
* fix #665

* fix #664

* fix #661

* fix #666
2024-12-12 23:00:16 +03:00
Ed
93a49ca398 Snowy (#659)
* snow tiles

* snow trees (2\6)

* +1 tree

* third snow layer, and simple snow biome
2024-12-12 21:51:03 +03:00
onesch
9d7846ed72 Safari hat In-hand Sprites (#33464)
* adds in-hand sprites to the safari hat.

* Update copyright wording

* visual fix

* Resprite in-hand sprites.

* linting meta.json
2024-12-12 18:09:43 +01:00
lzk
18322ec76f fix ghost command error string (#33838) 2024-12-12 11:18:53 -05:00
PJBot
b959a64f2c Automatic changelog update 2024-12-12 14:25:41 +00:00
Winkarst
48f62da2dc Update APE guidebook to contain Sigma particles, Transformation and colors for effects (#33558)
* Update APE guidebook

* Lang error

* Update Resources/ServerInfo/Guidebook/Science/APE.xml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/ServerInfo/Guidebook/Science/APE.xml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/ServerInfo/Guidebook/Science/APE.xml

Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>

* Update Resources/ServerInfo/Guidebook/Science/APE.xml

Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>
2024-12-12 15:24:34 +01:00
A.Ne.
2b3cc9e868 key rings fix (#620)
* key rings fix

* Update SharedCP14LockKeySystem.cs
2024-12-12 13:12:58 +03:00
onesch
842bbeb85f Warden headdresses In-hand Sprites (#33521)
* Adds in-hand sprites to the warden beret.

* Adds in-hand sprites to the warden cap.

* resprite in-hand sprites to the warden cap.
2024-12-12 02:44:48 +01:00
Ed
c42b77d0c9 Merge pull request #658 from crystallpunk-14/ed-11-12-2024-upstream
Upstream sync
2024-12-11 21:18:17 +03:00
Ed
6c8b0a07f3 yep 2024-12-11 21:17:43 +03:00
PJBot
67d444feb0 Automatic changelog update 2024-12-11 16:22:11 +00:00
BramvanZijp
ce9fc82382 Rework the HoS's Energy Shotgun (Varying energy consumption depending on fire-mode + re-adds a toned down self recharge.) (#32104)
* Rebalance HoS's Energy Shotgun

* SLIGHTLY Up the max charge so the gun properly recharges all of its charges, which matters a lot more with the self charge cooldown system.

* Prevent recharge cooldown if 0 power is used.

* Makes the clientside HUD actually update to reflect the changes in firecost and thus max/current charges.

* Properly fix that recharging to just under full issue instead of applying a budget fix to only the eshotgun.

* Clean up the client ammo UI fix.

* Update the self recharger component to comply with maintainer request.

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Remove code that was made redundant by a hotfix from another PR.

* Make the recharge pause on EMP, document things where needed, clean up code as per maintainer request, add a note to make the code better when power is moved to shared.

* Fix another internal issue

* Code cleanup + fix the rapid recharge verb to remove pause.

* cleanup

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2024-12-11 17:21:04 +01:00
PJBot
5ba868af79 Automatic changelog update 2024-12-11 15:59:10 +00:00
metalgearsloth
1a8e469c58 Fix battery self-recharge mispredicts (#33384) 2024-12-11 16:58:02 +01:00
Velcroboy
976cae9c78 Names camera routers (#33496)
Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2024-12-11 16:02:15 +01:00
PJBot
fc738b6690 Automatic changelog update 2024-12-11 14:31:38 +00:00
slarticodefast
c28f4fdc7f Fix greytide virus hitting other maps (#33806)
fix greytide virus hitting other maps
2024-12-11 15:30:29 +01:00
TGRCDev
89522e7144 Made anchor visuals generic (#33810)
Added a generic anchor visuals enum
2024-12-11 14:50:20 +01:00
Ed
af918c1253 Update audio_music.yml 2024-12-11 14:53:49 +03:00
Ed
be15a4097c Update cp14-ignoredPrototypes.yml 2024-12-11 14:49:44 +03:00
Ed
cd736e4fd4 Merge remote-tracking branch 'upstream/stable' into ed-11-12-2024-upstream
# Conflicts:
#	Content.IntegrationTests/Tests/PostMapInitTest.cs
#	Content.Shared/Lock/LockSystem.cs
#	Resources/Maps/oasis.yml
#	Resources/Prototypes/Maps/Pools/default.yml
#	Resources/Prototypes/audio.yml
2024-12-11 14:49:02 +03:00
Ed
576bbe91d0 Roofs (#657)
* simple roo system

* tweaks

* roof sprite update

* transparent roof

* wooden roof sprite

* remove weather: false from all tiles

* stone roof + roofs crafting

* final shtrix, maps update

* fuck

* fix checks

* reagent auto vaporize tweaks

* Update base.yml
2024-12-11 14:44:16 +03:00
Ed
e4b60b31c0 Ed 10 12 2024 aah (#656)
* fix ghost zlevel moving

* stairways autorotation

* ladders sprite update

* slow space swimming

* fix wrong wood spawn

* deadly ocean

* Update zLevels.yml
2024-12-10 21:24:06 +03:00
PJBot
7b681b66ae Automatic changelog update 2024-12-10 13:46:28 +00:00
metalgearsloth
2b487baea0 Fix blank newline on empty examine groups (#33813)
Construction always grants a blank newline even if it not currently constructing.
2024-12-10 14:45:20 +01:00
slarticodefast
7ed32f2c7d Merge into master: Derelict icon hotfix (#33768) (#33802) 2024-12-10 11:34:40 +01:00
PJBot
ee10fc246f Automatic changelog update 2024-12-10 10:01:27 +00:00
ArtisticRoomba
0e4728b6d4 Fix: SMES now has wirepanels visuals (#33808)
SMES now has wirepanels visuals
2024-12-10 11:00:17 +01:00
Ed
99786342fb Comoss sewers (zlevels added) (#655)
* comoss zlevel sewers

* Update biome_template_caves.yml

* Update GhostSystem.cs

* Update GhostSystem.cs
2024-12-10 00:43:30 +03:00
ArtisticRoomba
b1fca73f91 Meta station TEG power fixes + misc stuff (#33791)
* Fix Meta TEG power issues, give singulo more scaffold, give AI two cams in singulo containment like other stations

* remove serialized invalids because it happens to the best of us

* properly setup cameras, label substation and atmos APC while I'm here
2024-12-09 14:13:21 -07:00
PJBot
dd96f77faa Automatic changelog update 2024-12-09 17:14:04 +00:00
joshepvodka
9cb46d9343 Bar related tweaks (#33505)
* does everything

* beer flavor revert and linter fix

* Update Resources/Locale/en-US/flavors/flavor-profiles.ftl

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

* fix misspelling

* fix yet another misspelling

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>

* english has weird spellings huh

* im starting to feel ashamed of myself

* this is shameful

---------

Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com>
2024-12-09 18:12:57 +01:00
PJBot
35b1c04494 Automatic changelog update 2024-12-09 16:11:20 +00:00
ScarKy0
60bf48ccce You can now pet the AI core. (#33788)
Pettable AI core
2024-12-09 17:10:13 +01:00
ScarKy0
3844352fee Derelict icon hotfix (#33768)
whoops
2024-12-09 13:56:25 +01:00
slarticodefast
8bb4c82890 add "Changes: Audio" label to labeler (#33790)
add audio label to labeler
2024-12-09 11:56:30 +01:00
PJBot
a7957ddf65 Automatic changelog update 2024-12-09 08:55:30 +00:00
deathride58
5ab8e467a5 Adds an introductory message to the user-facing ahelp chat window (#33348)
* Adds an introductory message to the user-facing ahelp chat window

* Update Resources/Locale/en-US/administration/bwoink.ftl

* Update Resources/Locale/en-US/administration/bwoink.ftl

---------

Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>
2024-12-09 09:54:23 +01:00
dylanstrategie
38c35d8315 Major Marathon atmospherics rework (#33688)
* Major Marathon atmospherics rework

* More atmos changes

---------

Co-authored-by: dylanstrategie <188926747+dylanstrategie@users.noreply.github.com~>
2024-12-08 23:21:04 -07:00
sleepyyapril
7fd89806e2 Fix Disposals Ejections (#33468)
* Fix disposals.

* Rename properly

---------

Co-authored-by: sleepyyapril <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>
2024-12-08 22:08:07 -06:00
PJBot
1510e892f0 Automatic changelog update 2024-12-09 03:52:59 +00:00
Plykiya
8f2b19e103 Popup when being pulled shows who is pulling you (#33612)
* Popup when being pulled

* Update Content.Shared/Movement/Pulling/Systems/PullingSystem.cs

Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com>

* Update Resources/Locale/en-US/movement/pulling.ftl

Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com>

---------

Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com>
2024-12-08 21:51:53 -06:00
PJBot
a7e1adf395 Automatic changelog update 2024-12-09 03:42:17 +00:00
Errant
d57e731635 Signal timer duration limit (#33781)
* max duration

* comment
2024-12-08 21:41:11 -06:00
PJBot
670f1a8e28 Automatic changelog update 2024-12-08 23:21:10 +00:00
slarticodefast
ede8a1d377 Fix gas pipe leaking when unanchoring or breaking them (#33774)
* fix gas pipe unanchoring

* remove unneeded update

* revert popup change
2024-12-09 00:20:04 +01:00
PJBot
c4556fcbfe Automatic changelog update 2024-12-08 22:51:22 +00:00
ArtisticRoomba
34bfc59b18 Fix detective Vox spawning with their chosen outer clothing on the floor, force detective to have a selected outerclothing like all other sec roles (#33765)
fix detective vox spawning with their outer clothing on the floor
2024-12-08 23:50:14 +01:00
PJBot
98ad7a872f Automatic changelog update 2024-12-08 22:38:41 +00:00
Pieter-Jan Briers
f9da25881d Singularity equipment can now be activated with E interact (#33762)
These were coded to only listen to InteractHand, which doesn't follow our interaction model properly.
2024-12-08 23:37:32 +01:00
Errant
0c4dd9d1b9 Revert "Simplify separated screen top menu (#33047)" (Stable -> Master) (#33785) 2024-12-08 22:14:34 +01:00
Vasilis The Pikachu
8472603b76 Revert "Simplify separated screen top menu (#33047)"
This reverts commit f27fa1ed30.
2024-12-08 21:36:48 +01:00
Southbridge
73d5129644 Amber Station - Playtest Fixes (#33773)
* Fixed various issued identified during playtests.

* Fixed a firelock stuck closed

* Added more cameras and moved others

* Fixed an issue with disposals
2024-12-07 23:31:51 -07:00
PJBot
4661e9ef86 Automatic changelog update 2024-12-08 01:47:48 +00:00
Pieter-Jan Briers
299b13f21b Give silicons proper lobby/character editor previews (#33763)
* Give silicons proper lobby/character editor previews

No more naked dummies, properly show a borg/AI sprite now.

This means taking the JobEntity into account when spawning the dummy. For AIs I had to add a "JobPreviewEntity" field because they'd look like a posibrain otherwise. AI therefore uses a custom dummy entity I defined.

Also I had to add some margins to the UI, because otherwise the 32x32 sprite of the AI would look bad.

* Update Content.Shared/Roles/JobPrototype.cs

* Update Content.Client/Lobby/LobbyUIController.cs

* Update Resources/Prototypes/Entities/Mobs/Player/silicon.yml

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-08 02:46:41 +01:00
github-actions[bot]
3d53e748fa Update Credits (#33772)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-12-08 01:57:20 +01:00
Myra
337952dcb4 Codeowners cleanup (#33297) 2024-12-08 01:01:57 +01:00
Emisse
c85642d920 let bagel be played at max pop (#33769) 2024-12-07 14:24:16 -07:00
SpaceManiac
20be8298b7 Organize the Sandbox Panel window (#33684)
* Organize Sandbox Panel

* Map Editing -> Editing

* Unset ToggleMode on Suicide button. Can hardly un-suicide, no?

* Remove 'Link machines' button that has done nothing for 3 years

* Remember Sandbox window's position instead of forcing to center

* Shows Spawns -> Show Spawns

* Remove SandboxSystem.MachineLinking
2024-12-07 19:13:56 +01:00
Emisse
7f5c3cf751 infiltrator update (#33759) 2024-12-07 01:36:03 -07:00
Southbridge
cf73cd5ddc Box Station - Now more festive! (#33751)
Added more holiday decorations
2024-12-06 23:53:36 -07:00
PJBot
1a96a2bcc8 Automatic changelog update 2024-12-07 05:59:31 +00:00
Piras314
0d45dfada9 Christmas Nuke Song (#33752)
* 圣诞歌曲

* Update Resources/Audio/StationEvents/attributions.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-06 23:58:23 -06:00
PJBot
44daf85566 Automatic changelog update 2024-12-07 03:41:00 +00:00
metalgearsloth
9365e3a99b Predicted gas pumps (#33717)
* Predicted gas pumps

I wanted to try out atmos and first thing I found.

* a

* Remove details range
2024-12-07 14:39:52 +11:00
Winkarst
4beb1016cc Make unknown shuttle events trigger an announcement (#33450)
* Make unknown shuttle events trigger an announcement

* Call base at the end

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
2024-12-06 22:39:35 +01:00
deltanedas
3300ff2a06 clean up random lathe recipes (#31525)
Co-authored-by: deltanedas <@deltanedas:kde.org>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-06 16:45:01 +01:00
MilenVolf
b66fd98514 Localize ai dataset names (#33608)
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-06 16:38:00 +01:00
K-Dynamic
e244472546 Samurai dogi is now major contraband (#33699) 2024-12-06 16:36:26 +01:00
0tito
de19418126 Add Sprite changes to Logic Gates to show the input/output state (#33277) 2024-12-06 16:35:48 +01:00
beck
6add781c4a Added several variables to make ClumsyComponent more modular for developers. (#33715)
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-06 16:31:31 +01:00
PJBot
d6d95f1a7a Automatic changelog update 2024-12-06 10:16:30 +00:00
Ed
7d410d6094 Fix debris chunks loot spawning (#33747)
Update DungeonJob.PostGenBiome.cs
2024-12-06 11:15:23 +01:00
Errant
2d6e52b21c vox guidebook update poison regen (#33739)
* vox guidebook regen update

* damage number

* skreee
2024-12-06 09:43:11 +01:00
Southbridge
623a35b3fe Amber Station - Added Evac Shuttle (#33743)
* Added evac shuttle and fixed various issues brought up during playtests

* Updated Amber with playtest feedback, removed waste loop and firelocks from evac shuttle
2024-12-06 01:39:25 -07:00
PJBot
94090f7403 Automatic changelog update 2024-12-06 06:23:45 +00:00
ScarKy0
274c3ab0b9 Derelict Borg Revival (#33433)
* Derelictn'tn't Borg!

* Clean *sparkles*

* Removed "S: Awaiting Changes"
2024-12-06 00:22:38 -06:00
PJBot
38c8ffb9b5 Automatic changelog update 2024-12-06 05:28:59 +00:00
Winkarst
52a886947f Add a maintenance panel to bar signs (#33467)
* Add a maintenance panel to bar signs

* Update Resources/Locale/en-US/wires/wire-names.ftl

* AI interactions

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-05 23:27:52 -06:00
MilenVolf
d6ba7598bd Fix name duplications (#33740)
* Fix name duplication

* Apply requested changes
2024-12-05 23:19:27 -06:00
Velcroboy
207c849e2d Adds Station Anchor Beacon (#33711)
Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2024-12-05 22:56:34 -06:00
PJBot
cd1177d9ba Automatic changelog update 2024-12-06 04:53:08 +00:00
IProduceWidgets
3e0b93d071 fix a station event weighting bug (#33584)
* fractional weights dont work in StationEvents

* force-int

* sure why not, we can keep floats I guess.
2024-12-05 22:52:02 -06:00
PJBot
0e6ec2e1af Automatic changelog update 2024-12-05 21:40:46 +00:00
IProduceWidgets
8f3973b2eb set n2 survival box sprite layers (#33733) 2024-12-05 22:39:39 +01:00
PJBot
97ece026d5 Automatic changelog update 2024-12-05 21:18:37 +00:00
Pieter-Jan Briers
dc8b859916 Give vox health regen for poison below 20 damage (#33722) 2024-12-05 22:17:27 +01:00
Winkarst
ce672acf91 Fix meteor's ArithmeticException (#33556)
Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
2024-12-05 13:20:27 +01:00
Leon Friedrich
6f51aa4b15 More device configurator serialization fixes (#33664)
More device configurator invalid entity serialization fixes
2024-12-05 09:36:49 +01:00
Spessmann
59bce41390 Cog vox box removal (#33730)
removed vox box ggggggggggggg
2024-12-04 20:01:56 -07:00
Southbridge
bcf2b9afeb Box Station - Removed Vox Box (#33729)
* Removed vox box and removed nearby fuel tank as well

* made all dirt decals consistent
2024-12-04 19:54:59 -07:00
Emisse
90c8776a60 bagel update (#33726)
* bagel update

* remove invalid

* remove invalid
2024-12-04 19:54:45 -07:00
Southbridge
da68ae94c1 Amber Station - Removed Vox Box (#33725)
Removed Vox Box
2024-12-04 17:02:36 -07:00
PJBot
fbfcccbe16 Automatic changelog update 2024-12-04 16:51:01 +00:00
keronshb
82528dce37 Adds Store on Collide and Wand of the Locker (#33710)
* Adds wand of locker and locker projectile

* Adds IsOpen method to check if storage is open

* Adds store on collide

* Adds Store On Collide to Wizard Locker

* Adds Lock API

* Adds locking support

* Adds resist override and custom visual layers

* Fixes decursed states, adds comment for a future visualizer

* adds locker wand visuals and descriptions

* shrinks locker radius, moves TODO for throw support

* Adds whitelist and moves storage and lock logic into their own methods

* Adds support to disable store on collide after the first open. Fixes prediction issues with disabling.

* Adds wand of locker to the grimoire

* Adds wizard access prototype

* Adds Wizard to universal access

* Moves Lock on collide to on collide method

* Comments

* Changes layer order

* Fixes prediction issues when locking.

* Adds Wiz access to universal ID
2024-12-04 17:49:54 +01:00
Hreno
152cf3388b Add cooldown to buttons in borg's laws UI (#31490) 2024-12-04 21:16:41 +11:00
Tap
2e26ca786d Fix for towels not having a cooldown for cleaning (#33700)
Added a delay to cleaning with the towel
2024-12-04 21:14:59 +11:00
PJBot
fc8f7fb0ba Automatic changelog update 2024-12-04 10:14:29 +00:00
Pieter-Jan Briers
c10a72be39 Fix layout on wires UI (#33714)
Layout would break for machines with >6 lights because the column count was hardcoded. Uncap the UI width and fix the rows count instead.

Lights with less than 4 characters of text weren't aligned right, now they are.
2024-12-04 21:13:22 +11:00
PJBot
7ffd8012f6 Automatic changelog update 2024-12-04 02:43:25 +00:00
Partmedia
cf202e805d Fix sinks and toilets not draining (#33691)
* Fix AutoDrain

Per the system comments, AutoDrain is designed to automatically move
puddles into the drain (like a floor drain). Drains without AutoDrain
are still supposed to gradually empty the buffer, but not remove puddles
(like sinks and toilets).

However, a logic error in the original implementation causes drains with
AutoDrain set to false to simply not work. Hence sinks never emptied.

* Update documentation
2024-12-04 03:42:16 +01:00
Southbridge
87182635b6 Amber Improvements (#33707)
* Various changes (see PR)

* variantized, fixedgridatmos, tiledwalls
2024-12-03 16:59:16 -07:00
Southbridge
2c2a435dbd Amber Station Seasonal Update (#33698)
Made some modifications requested by reviewers prior to and after map merge, also added holiday decorations!
2024-12-02 21:58:02 -07:00
PJBot
bfd005a37f Automatic changelog update 2024-12-03 03:00:54 +00:00
CheddaCheez
e50c98c618 Add missing nacho recipes (#33637)
* Nacho recipes, nutrition, and trash

In meal_recipes.yml: Add recipes for Nachos, Cheesy Nachos, and Cuban Nachos.

In meals.yml: Add a solutions container to regular nachos so it lines up with the others, and add a small plate as trash to each one.

* Volumes, nutritional tweaks, and flavor

In meals.yml: Lowered maxVol on nachos to leave 5 units of space. Nachos nutriment and vitamin lowered for costing so little. A cheese wedge is 3.75 nutriment, so cheesy having 4 more total nutritional value lines up nicely to me.

Cuban nachos had too little volume to fit its reagents in the first place, so increased maxVol by 10. Chili peppers are 4 nutri / 4 vitamin and ketchup has a touch of tomato, so bumped to 8 and 5. Capsaicin lowered partly to make it an even 20u. Ketchup dilutes I guess. Also they don't have cheese so I changed the flavor profile to tomato instead.

In meal_recipes.yml: Cuban Nachos recipe tweaked to require one less pepper. Given above numbers, this fits the nutritional value imo.
2024-12-02 20:59:47 -06:00
Luiz Costa
029b0374e9 Juiceable slimeballs (#33660)
adds extractable component to slimeball prototype
2024-12-02 20:51:00 -06:00
Velcroboy
c1491e91b8 Adds a morgue locked maints airlock (#33693)
Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2024-12-02 20:46:55 -06:00
SpaceRox1244
2e31eb32cb Makes kukri not use combat knife's storage sprite (#33661) 2024-12-02 20:41:42 -06:00
PJBot
f0829a6652 Automatic changelog update 2024-12-03 02:25:45 +00:00
Southbridge
e4e84aea74 New Low-Mid Pop Station - Amber Station (#33441)
* Initial Commit with two departments done

* Checkpointing work

* Added most of service and science

* Started work on medbay

* Modified TEG setup and set up atmos pipes for engineering

* Re-added medbay, added chapel and janitorial, started routing disposals and generally the final layout of the map is coming together

* Plenty of additions, too many to list in a commit message

* Major update

* Nearly done with the map, just have to do decals and emergency lights

* Added all decals, only thing missing is department signs

* Toned back the dirt decals a bunch, added hallway signs and other decorations

* Finishing touches on the map before testing.

* Fixed invalids

* Renamed the station to Amber, and made a couple adjustments

* Completely redid cargo, added maints around sec

* Added Amber to the map post init integration test

* Many small updates addressing issues.

* Ran a script to update all the camera names, also ran fixgridatmos, fixrotations, tilewalls, and variantize

* Started addressing some of the issues brough up by Emisse and others

* Addressed all issues mentioned by reviewers. Added mail system.

* Wrapped up meeting all the issues raised by reviewers, also did a bunch of testing and resolved issues found during those tests

* Addressed additional requested changes, and nabbed some ship designs from Frontier. Redesigned south east maints and surrounding meteor nets based off of those designs

* Making a couple more requested changes

* Reduced the amount of Nitrogen Closets, made several small adjustments. Ready for review again!

* Removed invalids!

* web edit lmao

---------

Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com>
2024-12-02 19:24:37 -07:00
SpaceManiac
b800d98260 Fix lobby countdown not showing hours (#33685) 2024-12-02 13:29:44 -08:00
PJBot
cc804bf316 Automatic changelog update 2024-12-02 19:45:08 +00:00
JIPDawg
638a1dc489 Fixed ghost role rules for some syndicate familiars (#32457)
* fix ghost role rules for some syndicate familiars

* change from monkey rules to Team Antag rules.

* Resolve reviews + Fix rules for LoneOp and Xenos

* ghostrole rules

---------

Co-authored-by: JIPDawg <JIPDawg93@gmail.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
2024-12-02 20:43:59 +01:00
dylanstrategie
7f966ab9b1 Touching up Bagel Security Brig (#33680)
* Touching up Bagel Security Brig

* Added a few missing door names

* Last door name I promise

* Address feedback

* Forgot to delete old shutter button

---------

Co-authored-by: dylanstrategie <188926747+dylanstrategie@users.noreply.github.com~>
2024-12-02 04:29:45 -07:00
PJBot
560fd8dd77 Automatic changelog update 2024-12-01 22:10:41 +00:00
MilenVolf
b3841e8414 Fix BuckleSystem always marking InteractHandEvent as Handled (#33602)
* Add check before marking event as handled

* Update Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Cleanup

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-12-01 23:09:34 +01:00
MilenVolf
d4067bcaab Fix wrong system usage (#33679)
Fix wrong system using
2024-12-01 11:34:18 -08:00
PJBot
237324e268 Automatic changelog update 2024-12-01 06:31:13 +00:00
IProduceWidgets
bf312f2306 Update Snowasis (#33364)
* Update Snowasis

* Appease test gods

* Woops had the leftward animation backwards. Fixed.

* add santa suits and envelopes to chapel

* It looks worse unscaled but whatever.

* fix ghost role

* examines
2024-11-30 23:30:01 -07:00
MilenVolf
5fdf03c216 Replace obsolete GetTilesIntersecting methods (#32455)
* Remove usage of obsolete GetTilesIntersecting round 1

* Oop wrong uids

* Remove usage of obsolete GetLocalTilesIntersecting round 2

* Remove usage of obsolete GetLocalTilesIntersecting final round

* weh

* Fix using `SharedMapSystem` in `StencilOverlay`
2024-12-01 12:56:47 +11:00
Nikolai Korolev
2d405c9652 Fix formatting IDE0055 warnings in VS Code (#33669) 2024-12-01 12:51:26 +11:00
github-actions[bot]
3984f0aa0a Update Credits (#33670)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-12-01 12:51:12 +11:00
PJBot
a46323d9f9 Automatic changelog update 2024-11-30 20:12:50 +00:00
Token
061b1b8adb Fix makeghostroleraffle command where 4 arguments (#31836)
Fix makeghostroleraffle command with 4 arguments
2024-11-30 21:11:44 +01:00
PJBot
44ef60a642 Automatic changelog update 2024-11-30 19:32:46 +00:00
Preston Smith
efb35d7953 Require Wield To Activate Double-bladed ESword (#32869)
* Add MeleeRequiresWield component

* Prevent world activation
2024-11-30 20:31:40 +01:00
PJBot
720fccf3f3 Automatic changelog update 2024-11-30 17:26:15 +00:00
Winkarst
ab36b15080 Fix borgs not getting names on roundstart (#33578)
* Fix borgs not getting names on roundstart

* Glory to the NT

* Allow riggable to take in multiple reagents

* Revert

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
2024-11-30 18:25:09 +01:00
PJBot
766389a66b Automatic changelog update 2024-11-30 16:24:33 +00:00
Plykiya
fb76cd952e Fix for inspecting entities in the stripping window (#33644)
Handle it
2024-11-30 17:23:26 +01:00
PJBot
3d984603f1 Automatic changelog update 2024-11-30 16:15:45 +00:00
Plykiya
450bf813b8 Fix for inspecting entities in hand (#33642)
Actually inspect entity in hands
2024-11-30 17:14:39 +01:00
PJBot
973f42b3b2 Automatic changelog update 2024-11-30 16:00:03 +00:00
Plykiya
021c9832ef Fix for handcuffing someone more than once (#33646)
* Fix for over-cuffing someone

* comment
2024-11-30 16:58:56 +01:00
PJBot
86791583f9 Automatic changelog update 2024-11-30 06:24:58 +00:00
compilatron
08db47cb28 Cog/Marathon: Airlock fixes (#33621)
* Fixes the TEG airlock on marathon

* Fixes the atmos external airlock on cog
2024-11-29 23:23:50 -07:00
lunarcomets
b45c9d5129 fix PermanentBlindnessComponent to be not so permanent (#33292)
* adjust min blindness back to 0 when PermanentBlindnessComponent is removed

* mapinit changes

* remove OnRemove, move changes to OnShutdown

* goodbye event

* dependency removal

* final adjustment

---------

Co-authored-by: lunarcomets <luanrcomets2@gmail,com>
2024-11-30 13:56:52 +11:00
PJBot
e9ef00f475 Automatic changelog update 2024-11-30 02:55:44 +00:00
VideoKompany
54a9dce68d add locale to Shuttle Console Map tab (#33651)
fixed
2024-11-30 13:54:37 +11:00
PJBot
17a224c86a Automatic changelog update 2024-11-30 02:49:12 +00:00
Gansu
9236e9e5b9 Fix for arrivals deleting nuke (#33659)
Adds FTLSmashImmune to nuke prototype to stop it from arrival smashing
Adds a comment in FasterThanLight to indicate where the FTLSmashImmuneComponent is checked

Co-authored-by: aa5g21 <aa5g21@soton.ac.uk>
2024-11-30 13:48:04 +11:00
MilenVolf
6c86d7b32b Cleanup some Client atmos systems (#33634)
* Cleanup `ScrubberControl.xaml.cs`

* Minor cleanups

* Another pile of minor cleanups

* Apply requested changes

* Rename "which" into "bound". Add whitespace after "if"
2024-11-30 02:33:29 +01:00
PJBot
f99331aa00 Automatic changelog update 2024-11-29 12:52:21 +00:00
MossyGreySlope
87d6b0b79b Rename nitrogen internals crate (#33545)
* rename nitrogen internals crate

* nitrogen internals crate description

* migrate CrateNitrogenInternals ID
2024-11-29 13:51:15 +01:00
PJBot
bbdadd7144 Automatic changelog update 2024-11-29 09:47:31 +00:00
DrSmugleaf
3ad227a904 Add admin log for ghost warping (#33636) 2024-11-29 10:46:24 +01:00
Myra
422d1a9d32 Remove grasshopper from the panic bunker message (#33638)
Can be retargetted to stable if preferred, which will then be a hotfix
2024-11-29 20:27:14 +11:00
PJBot
2e340578ff Automatic changelog update 2024-11-29 08:15:22 +00:00
Alice "Arimah" Heurlin
360f6982f4 Display GPS coordinates on their own line (#33625) 2024-11-29 11:14:14 +03:00
Alpha-Two
93bdd813c4 Fix gender, maybe (#33631)
Co-authored-by: Alpha-Two <alpha2.5232@gmail.com>
2024-11-29 08:54:46 +01:00
Myra
b53c8ea60e Approval labeler fix electric boogaloo (#33633)
Nik told me to not name this "nya"
2024-11-28 21:54:01 +01:00
Nikolai Korolev
4a21ed87db Update Content.PatreonParser to use net8.0 TargetFramework (#33559)
Update Content.PatreonParse to use net8.0 targetframework
2024-11-28 20:13:26 +01:00
PJBot
6463e7e08e Automatic changelog update 2024-11-28 13:42:10 +00:00
beck-thompson
a790955b76 Light verb is now predicted (#33622)
Fix
2024-11-29 00:41:01 +11:00
SpaceRox1244
f6813e39c7 Makes knives fly straight when thrown (#33615)
Gives knives a thrown angle
2024-11-28 16:09:47 +03:00
SpaceManiac
a206acc220 Fix swapped uniform printer east/west sprites (#33442)
Fix uniform printer sprites rotating the wrong way
2024-11-28 21:38:33 +11:00
Mifia
de613e45f8 Fix gauze eyepatch flying pixel (#33564)
boo
2024-11-28 21:34:43 +11:00
AlexUm
ac65c5a55d Fix version for electril_grill meta.json (#33611)
fix

fixing the version thing in meta json for electril grill textures

Co-authored-by: Arthur Kustenko <arthur.kustenko@learnet.se>
2024-11-28 21:30:13 +11:00
ScarKy0
9704ed7a00 Added Oppenhopper poster to the game. (#33588)
* o7

* -

* oppenhopper v2

* Update Resources/Prototypes/Entities/Structures/Wallmounts/Signs/posters.yml

* Update Resources/Prototypes/Entities/Structures/Wallmounts/Signs/posters.yml

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-11-28 11:08:43 +01:00
Flareguy
56fd7cbb6f Removes burnt tiles (#33422)
remove burnt tiles
2024-11-28 09:49:41 +03:00
Myra
1bc65624c8 Merge stable into master: Hotfix the randomly occurring DeleteAllThenGhost test failures (#33593) 2024-11-27 09:05:31 +00:00
PJBot
1b6c9e866b Automatic changelog update 2024-11-27 05:56:21 +00:00
slarticodefast
8ea388b309 Fix windoor and high security door not showing electrocution HUD (#33551) 2024-11-27 16:55:14 +11:00
PJBot
6187675c27 Automatic changelog update 2024-11-27 05:33:46 +00:00
slarticodefast
c861c56a69 Fix space ambient music (#33594) 2024-11-27 16:32:39 +11:00
Errant
eb9540364e Hotfix the randomly occurring DeleteAllThenGhost test failures (#33582)
* clear mindrole on component shutdown

* let it go
2024-11-27 00:56:35 +01:00
dylanstrategie
ab7221efad Added two N2 lockers to Reach (#33409)
Co-authored-by: dylanstrategie <188926747+dylanstrategie@users.noreply.github.com~>
2024-11-26 13:04:34 -07:00
PJBot
dfc3562bfc Automatic changelog update 2024-11-26 13:51:29 +00:00
Winkarst
41d2cf166d Make shuttle airlocks not snapcardinals (#33557)
* Make shuttle airlocks not snapcardinals

* Update Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-11-27 00:51:13 +11:00
slarticodefast
470c869ce2 Greytide Virus station event (#33547)
* proof of concept

* full implementation

* I commited a crime

* t

* min players increase
2024-11-27 00:50:20 +11:00
Intoxicating-Innocence
d5225d1f46 Ghost role drop-down alignment (#33397)
* dropdown shares margin width with children

* removed dependency that rider added for some reason

* reduced vertical margin from 8 to 2
2024-11-26 09:28:31 +01:00
PJBot
a69fc39fc0 Automatic changelog update 2024-11-26 01:00:41 +00:00
metalgearsloth
f27fa1ed30 Simplify separated screen top menu (#33047) 2024-11-26 01:59:34 +01:00
slarticodefast
e9eca826d8 minor AI cleanup (#33555)
* minor cleanup

* to
2024-11-26 09:39:04 +11:00
Vasilis
f0e9de8489 "Borgimorph" Release 2024-11-22 (#33544) 2024-11-25 15:25:04 +00:00
Flareguy
b8c8f7d0f8 Adds more diona names (#33066)
* adds more diona names

* more stuff

* AHHHHHHHHHHHHHHHHHHHHHHH

* further additions

* removes depression + adds comment

* fixes + remove some weird stuff + more stuff

* remove haste
2024-11-25 14:51:41 +01:00
PJBot
b8466d8321 Automatic changelog update 2024-11-25 12:36:20 +00:00
Niels Huylebroeck
49724a9b9d Turn off PointLights on VendingMachines when broken or off. (#33513)
The light itself should already turn off due to `LitOnPowered`
component, but the broken state of a VendingMachine did not.

Fixes  #33382
2024-11-25 13:35:14 +01:00
PJBot
ae576abe1f Automatic changelog update 2024-11-25 12:25:04 +00:00
Minemoder5000
45cf4ec340 Shark plushies now goes rawr on hit. (#33540)
Shark goes rawr more
2024-11-25 13:23:57 +01:00
Nikolai Korolev
ea7f5433ac Fix RA0003 warning for ChatBox (#33531) 2024-11-25 22:53:12 +11:00
Ben
32f48d974f removed obsolete netmessage creator (#33542)
removed opsolete netmessage createor
2024-11-25 22:39:10 +11:00
Errant
14103e7a86 Hotfix babyproof arrivals terminal and arrivals shuttle (#33538) 2024-11-25 12:12:11 +01:00
PJBot
da9b2e6a10 Automatic changelog update 2024-11-25 07:21:39 +00:00
Schrödinger
f53e3ec3c1 [BUGFIX] "Ghost" in the lobby lets you see the whole chat (#33529)
* fix bug, in ghost command lobby

* fix

* Fix build
2024-11-25 10:20:31 +03:00
IProduceWidgets
9a898bb98e babyproof arrivals shuttle (#33284)
* babyproof arrivals shuttle

* always powered lights

* uncuttable cables from terminal PR.

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-11-25 07:59:37 +01:00
IProduceWidgets
86a3d1636f baby proof the terminal (#33281)
* baby proof the terminal

* Make a couple exceptions for items that you might take with you.

* alwayspoweredlights

* Uncuttable cables since cablecomp is a snowflake construction system

* chairs and vendors

* rerun heisentests

* rerun tests again
2024-11-25 07:59:01 +01:00
PJBot
ed2cd23309 Automatic changelog update 2024-11-25 04:28:02 +00:00
slarticodefast
3c6c5ab6c9 fix airlocks inconsistently auto-closing after unbolting (#33524)
fix door auto close timer
2024-11-25 15:26:54 +11:00
kosticia
d642ee7707 Delete HOS headset from warden's locker (#33234)
* add headset

* Add icons

* Meta change

* fix

* Revert + delete headset from locker
2024-11-25 01:46:33 +01:00
mubururu_
cae49ae0d2 various material & ore inhands (#33342)
* begin

* bones + pyrotten + goliath hide inhands

* Update Resources/Prototypes/Entities/Objects/Materials/materials.yml

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/Textures/Objects/Materials/materials.rsi/meta.json

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/Textures/Objects/Materials/materials.rsi/meta.json

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* Update Resources/Textures/Objects/Materials/materials.rsi/meta.json

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>

* pyrottOn

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-11-24 17:24:13 +01:00
PJBot
91b9d4a7f0 Automatic changelog update 2024-11-24 08:50:37 +00:00
deltanedas
e436a50c36 fix exped caves generation (#32890)
Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-11-24 09:49:31 +01:00
PJBot
84df2b857e Automatic changelog update 2024-11-24 08:12:54 +00:00
MilenVolf
aa80a88cc4 Allow shuttles on planets to make FTL jump (#33507)
This check conflicts with an attempt to FTL from the planet before expedition ends
2024-11-24 11:11:47 +03:00
PJBot
2229a6a04b Automatic changelog update 2024-11-24 04:21:08 +00:00
Winkarst
f706170ee1 Draw muzzle flash below mobs (#33465)
* Draw muzzle flash below mobs

* Better naming

---------

Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
2024-11-24 15:20:00 +11:00
github-actions[bot]
ef89d5cc21 Update Credits (#33503)
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
2024-11-24 12:56:18 +11:00
PJBot
e958c0c9b0 Automatic changelog update 2024-11-23 16:54:04 +00:00
metalgearsloth
11dbf50ed6 Add delay to AutoOrient (#33479)
It functions identically to how V1 of orientation worked and it's incredibly annoying.
2024-11-23 17:52:58 +01:00
PJBot
8522ffe8ce Automatic changelog update 2024-11-23 15:15:19 +00:00
IProduceWidgets
fab9993a3b babyproof arrivals shuttle (#33284)
* babyproof arrivals shuttle

* always powered lights

* uncuttable cables from terminal PR.

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
2024-11-23 16:14:13 +01:00
PJBot
4cecf99e65 Automatic changelog update 2024-11-23 11:42:43 +00:00
goet
855547a2d4 Ensure wires can always be cut (#32447)
ensure wires are always cut
2024-11-23 12:41:37 +01:00
PJBot
45af6a13fc Automatic changelog update 2024-11-23 11:21:05 +00:00
metalgearsloth
11dae2ff93 Don't show drag-drop outline if climbing (#33477)
It won't actually do anything.
2024-11-23 12:19:59 +01:00
PJBot
bde85858a3 Automatic changelog update 2024-11-23 09:32:14 +00:00
metalgearsloth
c3786a56dc Fix door animations mispredicting if closing is interrupted (#33481)
* Fix door animations mispredicting if closing is interrupted

On master it will flicker states a little bit partially due to it not being predicted.

Instead we'll just set it straight back to opening (no animation is ever played anyway).

* no log
2024-11-23 10:31:07 +01:00
eoineoineoin
bdf4a46edf Minor improvements & fixes to Shuttle Console UI (#31623)
* Fix grids and docks being culled from display prematurely

* Fix inconsistent disabling of "Undock" buttons

* Add a radar icon to indicate where the controlling console is

* Tidy up math

Remove lots of sketchy transforms-of-transforms, which should have been
as single matrix multiply. Assign proper names to matrices. Remove some
redundant calculations.

* Feedback
2024-11-23 17:55:09 +11:00
MetalSage
a42bacd3a9 Fix startingGear storage (#33394)
* fix starting gear storage

* removal of unused

---------

Co-authored-by: MetalSage <metalsage.official@gmail.com>
2024-11-23 17:54:35 +11:00
PJBot
1e93e12330 Automatic changelog update 2024-11-23 06:42:34 +00:00
Winkarst
0a587c9ccc Disable submit admin note button on switch to note (#33456)
Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co>
2024-11-23 17:41:28 +11:00
PJBot
7feafcbe95 Automatic changelog update 2024-11-23 06:38:21 +00:00
metalgearsloth
5409815be9 Allow AI and observers to see electrified doors (#33466) 2024-11-23 17:37:14 +11:00
PJBot
d8ecf12fca Automatic changelog update 2024-11-23 02:54:55 +00:00
metalgearsloth
616907009d Fix salvage vendor inventory (#33437) 2024-11-23 13:53:47 +11:00
PJBot
6bc205484f Automatic changelog update 2024-11-22 22:51:50 +00:00
IProduceWidgets
a28adf4ae4 baby proof the terminal (#33281)
* baby proof the terminal

* Make a couple exceptions for items that you might take with you.

* alwayspoweredlights

* Uncuttable cables since cablecomp is a snowflake construction system

* chairs and vendors

* rerun heisentests

* rerun tests again
2024-11-22 23:50:41 +01:00
slarticodefast
de516905f0 another rename 2024-11-22 23:39:05 +01:00
slarticodefast
306277afe0 rename 2024-11-22 23:05:36 +01:00
slarticodefast
08bfb43feb cleanup 2024-11-22 23:02:59 +01:00
slarticodefast
5a9a2d463b Merge branch 'master' into powerhud 2024-11-22 19:38:55 +01:00
slarticodefast
3758715bdc electrification hud 2024-11-22 00:43:02 +01:00
MissKay1994
c02a027cf1 Update salvage.yml 2024-11-20 18:06:19 -05:00
MissKay1994
e96e80bc95 Update salvage.yml 2024-11-20 18:05:01 -05:00
MissKay1994
f23b6522b2 Update cargo_vending.yml 2024-11-20 04:44:33 -05:00
MissKay1994
693e5f1fad Update salvage.yml 2024-11-20 03:40:54 -05:00
2103 changed files with 785288 additions and 117942 deletions

37
.github/CODEOWNERS vendored
View File

@@ -2,49 +2,30 @@
# Sorting by path instead of by who added it one day :(
# this isn't how codeowners rules work pls read the first comment instead of trying to force a sorting order
/Resources/ConfigPresets/WizardsDen/ @Chief-Engineer
# Moony's Gargantuan List Of Things She Cares About, or MGLOTSCA for short.
# You need to add your name to these entries, not make a new one, if you care about them.
/Content.*/Toolshed/ @moonheart08
**/Toolshed/** @moonheart08
*Command.cs @moonheart08
/Content.*/Administration/ @moonheart08 @DrSmugleaf @Chief-Engineer
/Content.*/Station/ @moonheart08
/Content.*/Maps/ @moonheart08
/Content.*/GameTicking/ @moonheart08 @EmoGarbage404
/Resources/ServerInfo/ @moonheart08 @Chief-Engineer
/Resources/ServerInfo/Guidebook/ @moonheart08 @EmoGarbage404
/Resources/ServerInfo/Guidebook/ServerRules/ @Chief-Engineer
/Resources/engineCommandPerms.yml @moonheart08 @Chief-Engineer
/Resources/clientCommandPerms.yml @moonheart08 @Chief-Engineer
/Resources/ConfigPresets/WizardsDen/ @nikthechampiongr @crazybrain23
/Content.*/Administration/ @DrSmugleaf @nikthechampiongr @crazybrain23
/Resources/ServerInfo/ @nikthechampiongr @crazybrain23
/Resources/ServerInfo/Guidebook/ServerRules/ @nikthechampiongr @crazybrain23
/Resources/Prototypes/Maps/** @Emisse
/Resources/Prototypes/Body/ @DrSmugleaf # suffering
/Resources/Prototypes/Entities/Mobs/Player/ @DrSmugleaf
/Resources/Prototypes/Entities/Mobs/Species/ @DrSmugleaf
/Resources/Prototypes/Guidebook/rules.yml @Chief-Engineer
/Resources/Prototypes/Guidebook/rules.yml @nikthechampiongr @crazybrain23
/Content.*/Body/ @DrSmugleaf
/Content.YAMLLinter @DrSmugleaf
/Content.Shared/Damage/ @DrSmugleaf
/Content.*/Anomaly/ @EmoGarbage404 @TheShuEd
/Content.*/Lathe/ @EmoGarbage404
/Content.*/Materials/ @EmoGarbage404
/Content.*/Mech/ @EmoGarbage404
/Content.*/Research/ @EmoGarbage404
/Content.*/Stack/ @EmoGarbage404
/Content.*/Xenoarchaeology/ @EmoGarbage404
/Content.*/Zombies/ @EmoGarbage404
/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml @EmoGarbage404 @TheShuEd
/Resources/Prototypes/Research/ @EmoGarbage404
/Content.*/Anomaly/ @TheShuEd
/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml @TheShuEd
/Content.*/Forensics/ @ficcialfaint
# SKREEEE
/Content.*.Database/ @PJB3005 @DrSmugleaf
/Content.Shared.Database/Log*.cs @PJB3005 @DrSmugleaf @Chief-Engineer
/Content.Shared.Database/Log*.cs @PJB3005 @DrSmugleaf @nikthechampiongr @crazybrain23
/Pow3r/ @PJB3005
/Content.Server/Power/Pow3r/ @PJB3005
@@ -52,7 +33,7 @@
/Content.*/Atmos/ @Partmedia
/Content.*/Botany/ @Partmedia
#Jezi
# Jezi
/Content.*/Medical @Jezithyr
/Content.*/Body @Jezithyr

4
.github/labeler.yml vendored
View File

@@ -16,6 +16,10 @@
- changed-files:
- any-glob-to-any-file: '**/*.swsl'
"Changes: Audio":
- changed-files:
- any-glob-to-any-file: '**/*.ogg'
"Changes: No C#":
- changed-files:
# Equiv to any-glob-to-all as long as this has one matcher. If ALL changed files are not C# files, then apply label.

View File

@@ -2,11 +2,11 @@
on:
push:
branches: [ master, staging, trying ]
branches: [ master, staging, stable ]
merge_group:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]
branches: [ master ]
branches: [ master, staging, stable ]
jobs:
build:

View File

@@ -2,11 +2,11 @@ name: Build & Test Debug
on:
push:
branches: [ master, staging, trying ]
branches: [ master, staging, stable ]
merge_group:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]
branches: [ master ]
branches: [ master, staging, stable ]
jobs:
build:

View File

@@ -16,7 +16,7 @@ jobs:
with:
username: ${{ github.actor }}
team: "content-maintainers,junior-maintainers"
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
GITHUB_TOKEN: ${{ secrets.LABELER_PAT }}
- if: ${{ steps.checkUserMember.outputs.isTeamMember == 'true' }}
uses: actions-ecosystem/action-add-labels@v1
with:

View File

@@ -14,7 +14,7 @@ jobs:
{
"0": "XS",
"10": "S",
"30": "M",
"100": "L",
"1000": "XL"
"100": "M",
"1000": "L",
"5000": "XL"
}

View File

@@ -2,7 +2,7 @@
on:
push:
branches: [ master, staging, trying ]
branches: [ master, staging, stable ]
paths:
- '**.cs'
- '**.csproj'
@@ -16,7 +16,7 @@ on:
merge_group:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]
branches: [ master ]
branches: [ master, staging, stable ]
paths:
- '**.cs'
- '**.csproj'

View File

@@ -1,7 +1,7 @@
name: RGA schema validator
on:
push:
branches: [ master, staging, trying ]
branches: [ master, staging, stable ]
merge_group:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]

View File

@@ -2,7 +2,7 @@ name: RSI Validator
on:
push:
branches: [ staging, trying ]
branches: [ master, staging, stable ]
merge_group:
pull_request:
paths:

View File

@@ -1,7 +1,7 @@
name: Map file schema validator
on:
push:
branches: [ master, staging, trying ]
branches: [ master, staging, stable ]
merge_group:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]

View File

@@ -2,7 +2,7 @@ name: YAML Linter
on:
push:
branches: [ master, staging, trying ]
branches: [ master, staging, stable ]
merge_group:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]

View File

@@ -258,13 +258,13 @@ namespace Content.Client.Actions
public void LinkAllActions(ActionsComponent? actions = null)
{
if (_playerManager.LocalEntity is not { } user ||
!Resolve(user, ref actions, false))
{
return;
}
if (_playerManager.LocalEntity is not { } user ||
!Resolve(user, ref actions, false))
{
return;
}
LinkActions?.Invoke(actions);
LinkActions?.Invoke(actions);
}
public override void Shutdown()

View File

@@ -159,6 +159,7 @@ public sealed partial class NoteEdit : FancyWindow
SecretCheckBox.Pressed = false;
SeverityOption.Disabled = false;
PermanentCheckBox.Pressed = true;
SubmitButton.Disabled = true;
UpdatePermanentCheckboxFields();
break;
case (int) NoteType.Message: // Message: these are shown to the player when they log on

View File

@@ -1,8 +1,4 @@
using Robust.Shared.GameObjects;
namespace Content.Client.Atmos.Components;
[RegisterComponent]
public sealed partial class PipeColorVisualsComponent : Component
{
}
public sealed partial class PipeColorVisualsComponent : Component;

View File

@@ -1,6 +1,5 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Orientation="Vertical" HorizontalExpand ="True" Margin="0 0 0 3">
@@ -62,7 +61,7 @@
</PanelContainer>
</BoxContainer>
<!-- If the alarm is inactive, this is label is diplayed instead -->
<!-- If the alarm is inactive, this is label is displayed instead -->
<Label Name="NoDataLabel" Text="{Loc 'atmos-alerts-window-no-data-available'}" HorizontalAlignment="Center" Margin="0 15" FontColorOverride="#a9a9a9" ReservesSpace="False" Visible="False"></Label>
<!-- Silencing progress bar -->

View File

@@ -31,19 +31,6 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
[AtmosAlarmType.Danger] = "atmos-alerts-window-danger-state",
};
private Dictionary<Gas, string> _gasShorthands = new Dictionary<Gas, string>()
{
[Gas.Ammonia] = "NH₃",
[Gas.CarbonDioxide] = "CO₂",
[Gas.Frezon] = "F",
[Gas.Nitrogen] = "N₂",
[Gas.NitrousOxide] = "N₂O",
[Gas.Oxygen] = "O₂",
[Gas.Plasma] = "P",
[Gas.Tritium] = "T",
[Gas.WaterVapor] = "H₂O",
};
public AtmosAlarmEntryContainer(NetEntity uid, EntityCoordinates? coordinates)
{
RobustXamlLoader.Load(this);
@@ -136,8 +123,9 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
GasGridContainer.RemoveAllChildren();
var gasData = focusData.Value.GasData.Where(g => g.Key != Gas.Oxygen);
var keyValuePairs = gasData.ToList();
if (gasData.Count() == 0)
if (keyValuePairs.Count == 0)
{
// No other gases
var gasLabel = new Label()
@@ -158,17 +146,14 @@ public sealed partial class AtmosAlarmEntryContainer : BoxContainer
else
{
// Add an entry for each gas
foreach ((var gas, (var mol, var percent, var alert)) in gasData)
foreach ((var gas, (var mol, var percent, var alert)) in keyValuePairs)
{
var gasPercent = (FixedPoint2)0f;
gasPercent = percent * 100f;
if (!_gasShorthands.TryGetValue(gas, out var gasShorthand))
gasShorthand = "X";
FixedPoint2 gasPercent = percent * 100f;
var gasAbbreviation = Atmospherics.GasAbbreviations.GetValueOrDefault(gas, Loc.GetString("gas-unknown-abbreviation"));
var gasLabel = new Label()
{
Text = Loc.GetString("atmos-alerts-window-other-gases-value", ("shorthand", gasShorthand), ("value", gasPercent)),
Text = Loc.GetString("atmos-alerts-window-other-gases-value", ("shorthand", gasAbbreviation), ("value", gasPercent)),
FontOverride = normalFont,
FontColorOverride = GetAlarmStateColor(alert),
HorizontalAlignment = HAlignment.Center,

View File

@@ -14,8 +14,6 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
_menu = new AtmosAlertsComputerWindow(this, Owner);
_menu.OpenCentered();
_menu.OnClose += Close;
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -24,9 +22,6 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
var castState = (AtmosAlertsComputerBoundInterfaceState) state;
if (castState == null)
return;
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
_menu?.UpdateUI(xform?.Coordinates, castState.AirAlarms, castState.FireAlarms, castState.FocusData);
}

View File

@@ -1,7 +1,6 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.Pinpointer.UI"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Title="{Loc 'atmos-alerts-window-title'}"
Resizable="False"
SetSize="1120 750"

View File

@@ -0,0 +1,40 @@
using Content.Shared.Atmos.Components;
namespace Content.Client.Atmos.Consoles;
public sealed class AtmosMonitoringConsoleBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private AtmosMonitoringConsoleWindow? _menu;
public AtmosMonitoringConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { }
protected override void Open()
{
base.Open();
_menu = new AtmosMonitoringConsoleWindow(this, Owner);
_menu.OpenCentered();
_menu.OnClose += Close;
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (state is not AtmosMonitoringConsoleBoundInterfaceState castState)
return;
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
_menu?.UpdateUI(xform?.Coordinates, castState.AtmosNetworks);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}

View File

@@ -0,0 +1,295 @@
using Content.Client.Pinpointer.UI;
using Content.Shared.Atmos.Components;
using Content.Shared.Pinpointer;
using Robust.Client.Graphics;
using Robust.Shared.Collections;
using Robust.Shared.Map.Components;
using System.Linq;
using System.Numerics;
namespace Content.Client.Atmos.Consoles;
public sealed partial class AtmosMonitoringConsoleNavMapControl : NavMapControl
{
[Dependency] private readonly IEntityManager _entManager = default!;
public bool ShowPipeNetwork = true;
public int? FocusNetId = null;
private const int ChunkSize = 4;
private readonly Color _basePipeNetColor = Color.LightGray;
private readonly Color _unfocusedPipeNetColor = Color.DimGray;
private List<AtmosMonitoringConsoleLine> _atmosPipeNetwork = new();
private Dictionary<Color, Color> _sRGBLookUp = new Dictionary<Color, Color>();
// Look up tables for merging continuous lines. Indexed by line color
private Dictionary<Color, Dictionary<Vector2i, Vector2i>> _horizLines = new();
private Dictionary<Color, Dictionary<Vector2i, Vector2i>> _horizLinesReversed = new();
private Dictionary<Color, Dictionary<Vector2i, Vector2i>> _vertLines = new();
private Dictionary<Color, Dictionary<Vector2i, Vector2i>> _vertLinesReversed = new();
public AtmosMonitoringConsoleNavMapControl() : base()
{
PostWallDrawingAction += DrawAllPipeNetworks;
}
protected override void UpdateNavMap()
{
base.UpdateNavMap();
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(Owner, out var console))
return;
if (!_entManager.TryGetComponent<MapGridComponent>(MapUid, out var grid))
return;
_atmosPipeNetwork = GetDecodedAtmosPipeChunks(console.AtmosPipeChunks, grid);
}
private void DrawAllPipeNetworks(DrawingHandleScreen handle)
{
if (!ShowPipeNetwork)
return;
// Draw networks
if (_atmosPipeNetwork != null && _atmosPipeNetwork.Any())
DrawPipeNetwork(handle, _atmosPipeNetwork);
}
private void DrawPipeNetwork(DrawingHandleScreen handle, List<AtmosMonitoringConsoleLine> atmosPipeNetwork)
{
var offset = GetOffset();
offset = offset with { Y = -offset.Y };
if (WorldRange / WorldMaxRange > 0.5f)
{
var pipeNetworks = new Dictionary<Color, ValueList<Vector2>>();
foreach (var chunkedLine in atmosPipeNetwork)
{
var start = ScalePosition(chunkedLine.Origin - offset);
var end = ScalePosition(chunkedLine.Terminus - offset);
if (!pipeNetworks.TryGetValue(chunkedLine.Color, out var subNetwork))
subNetwork = new ValueList<Vector2>();
subNetwork.Add(start);
subNetwork.Add(end);
pipeNetworks[chunkedLine.Color] = subNetwork;
}
foreach ((var color, var subNetwork) in pipeNetworks)
{
if (subNetwork.Count > 0)
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, subNetwork.Span, color);
}
}
else
{
var pipeVertexUVs = new Dictionary<Color, ValueList<Vector2>>();
foreach (var chunkedLine in atmosPipeNetwork)
{
var leftTop = ScalePosition(new Vector2
(Math.Min(chunkedLine.Origin.X, chunkedLine.Terminus.X) - 0.1f,
Math.Min(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) - 0.1f)
- offset);
var rightTop = ScalePosition(new Vector2
(Math.Max(chunkedLine.Origin.X, chunkedLine.Terminus.X) + 0.1f,
Math.Min(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) - 0.1f)
- offset);
var leftBottom = ScalePosition(new Vector2
(Math.Min(chunkedLine.Origin.X, chunkedLine.Terminus.X) - 0.1f,
Math.Max(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) + 0.1f)
- offset);
var rightBottom = ScalePosition(new Vector2
(Math.Max(chunkedLine.Origin.X, chunkedLine.Terminus.X) + 0.1f,
Math.Max(chunkedLine.Origin.Y, chunkedLine.Terminus.Y) + 0.1f)
- offset);
if (!pipeVertexUVs.TryGetValue(chunkedLine.Color, out var pipeVertexUV))
pipeVertexUV = new ValueList<Vector2>();
pipeVertexUV.Add(leftBottom);
pipeVertexUV.Add(leftTop);
pipeVertexUV.Add(rightBottom);
pipeVertexUV.Add(leftTop);
pipeVertexUV.Add(rightBottom);
pipeVertexUV.Add(rightTop);
pipeVertexUVs[chunkedLine.Color] = pipeVertexUV;
}
foreach ((var color, var pipeVertexUV) in pipeVertexUVs)
{
if (pipeVertexUV.Count > 0)
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleList, pipeVertexUV.Span, color);
}
}
}
private List<AtmosMonitoringConsoleLine> GetDecodedAtmosPipeChunks(Dictionary<Vector2i, AtmosPipeChunk>? chunks, MapGridComponent? grid)
{
var decodedOutput = new List<AtmosMonitoringConsoleLine>();
if (chunks == null || grid == null)
return decodedOutput;
// Clear stale look up table values
_horizLines.Clear();
_horizLinesReversed.Clear();
_vertLines.Clear();
_vertLinesReversed.Clear();
// Generate masks
var northMask = (ulong)1 << 0;
var southMask = (ulong)1 << 1;
var westMask = (ulong)1 << 2;
var eastMask = (ulong)1 << 3;
foreach ((var chunkOrigin, var chunk) in chunks)
{
var list = new List<AtmosMonitoringConsoleLine>();
foreach (var ((netId, hexColor), atmosPipeData) in chunk.AtmosPipeData)
{
// Determine the correct coloration for the pipe
var color = Color.FromHex(hexColor) * _basePipeNetColor;
if (FocusNetId != null && FocusNetId != netId)
color *= _unfocusedPipeNetColor;
// Get the associated line look up tables
if (!_horizLines.TryGetValue(color, out var horizLines))
{
horizLines = new();
_horizLines[color] = horizLines;
}
if (!_horizLinesReversed.TryGetValue(color, out var horizLinesReversed))
{
horizLinesReversed = new();
_horizLinesReversed[color] = horizLinesReversed;
}
if (!_vertLines.TryGetValue(color, out var vertLines))
{
vertLines = new();
_vertLines[color] = vertLines;
}
if (!_vertLinesReversed.TryGetValue(color, out var vertLinesReversed))
{
vertLinesReversed = new();
_vertLinesReversed[color] = vertLinesReversed;
}
// Loop over the chunk
for (var tileIdx = 0; tileIdx < ChunkSize * ChunkSize; tileIdx++)
{
if (atmosPipeData == 0)
continue;
var mask = (ulong)SharedNavMapSystem.AllDirMask << tileIdx * SharedNavMapSystem.Directions;
if ((atmosPipeData & mask) == 0)
continue;
var relativeTile = GetTileFromIndex(tileIdx);
var tile = (chunk.Origin * ChunkSize + relativeTile) * grid.TileSize;
tile = tile with { Y = -tile.Y };
// Calculate the draw point offsets
var vertLineOrigin = (atmosPipeData & northMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 1f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
var vertLineTerminus = (atmosPipeData & southMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
var horizLineOrigin = (atmosPipeData & eastMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
new Vector2(grid.TileSize * 1f, -grid.TileSize * 0.5f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
var horizLineTerminus = (atmosPipeData & westMask << tileIdx * SharedNavMapSystem.Directions) > 0 ?
new Vector2(grid.TileSize * 0f, -grid.TileSize * 0.5f) : new Vector2(grid.TileSize * 0.5f, -grid.TileSize * 0.5f);
// Since we can have pipe lines that have a length of a half tile,
// double the vectors and convert to vector2i so we can merge them
AddOrUpdateNavMapLine(ConvertVector2ToVector2i(tile + horizLineOrigin, 2), ConvertVector2ToVector2i(tile + horizLineTerminus, 2), horizLines, horizLinesReversed);
AddOrUpdateNavMapLine(ConvertVector2ToVector2i(tile + vertLineOrigin, 2), ConvertVector2ToVector2i(tile + vertLineTerminus, 2), vertLines, vertLinesReversed);
}
}
}
// Scale the vector2is back down and convert to vector2
foreach (var (color, horizLines) in _horizLines)
{
// Get the corresponding sRBG color
var sRGB = GetsRGBColor(color);
foreach (var (origin, terminal) in horizLines)
decodedOutput.Add(new AtmosMonitoringConsoleLine
(ConvertVector2iToVector2(origin, 0.5f), ConvertVector2iToVector2(terminal, 0.5f), sRGB));
}
foreach (var (color, vertLines) in _vertLines)
{
// Get the corresponding sRBG color
var sRGB = GetsRGBColor(color);
foreach (var (origin, terminal) in vertLines)
decodedOutput.Add(new AtmosMonitoringConsoleLine
(ConvertVector2iToVector2(origin, 0.5f), ConvertVector2iToVector2(terminal, 0.5f), sRGB));
}
return decodedOutput;
}
private Vector2 ConvertVector2iToVector2(Vector2i vector, float scale = 1f)
{
return new Vector2(vector.X * scale, vector.Y * scale);
}
private Vector2i ConvertVector2ToVector2i(Vector2 vector, float scale = 1f)
{
return new Vector2i((int)MathF.Round(vector.X * scale), (int)MathF.Round(vector.Y * scale));
}
private Vector2i GetTileFromIndex(int index)
{
var x = index / ChunkSize;
var y = index % ChunkSize;
return new Vector2i(x, y);
}
private Color GetsRGBColor(Color color)
{
if (!_sRGBLookUp.TryGetValue(color, out var sRGB))
{
sRGB = Color.ToSrgb(color);
_sRGBLookUp[color] = sRGB;
}
return sRGB;
}
}
public struct AtmosMonitoringConsoleLine
{
public readonly Vector2 Origin;
public readonly Vector2 Terminus;
public readonly Color Color;
public AtmosMonitoringConsoleLine(Vector2 origin, Vector2 terminus, Color color)
{
Origin = origin;
Terminus = terminus;
Color = color;
}
}

View File

@@ -0,0 +1,69 @@
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Consoles;
using Robust.Shared.GameStates;
namespace Content.Client.Atmos.Consoles;
public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleSystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AtmosMonitoringConsoleComponent, ComponentHandleState>(OnHandleState);
}
private void OnHandleState(EntityUid uid, AtmosMonitoringConsoleComponent component, ref ComponentHandleState args)
{
Dictionary<Vector2i, Dictionary<(int, string), ulong>> modifiedChunks;
Dictionary<NetEntity, AtmosDeviceNavMapData> atmosDevices;
switch (args.Current)
{
case AtmosMonitoringConsoleDeltaState delta:
{
modifiedChunks = delta.ModifiedChunks;
atmosDevices = delta.AtmosDevices;
foreach (var index in component.AtmosPipeChunks.Keys)
{
if (!delta.AllChunks!.Contains(index))
component.AtmosPipeChunks.Remove(index);
}
break;
}
case AtmosMonitoringConsoleState state:
{
modifiedChunks = state.Chunks;
atmosDevices = state.AtmosDevices;
foreach (var index in component.AtmosPipeChunks.Keys)
{
if (!state.Chunks.ContainsKey(index))
component.AtmosPipeChunks.Remove(index);
}
break;
}
default:
return;
}
foreach (var (origin, chunk) in modifiedChunks)
{
var newChunk = new AtmosPipeChunk(origin);
newChunk.AtmosPipeData = new Dictionary<(int, string), ulong>(chunk);
component.AtmosPipeChunks[origin] = newChunk;
}
component.AtmosDevices.Clear();
foreach (var (nuid, atmosDevice) in atmosDevices)
{
component.AtmosDevices[nuid] = atmosDevice;
}
}
}

View File

@@ -0,0 +1,99 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.Atmos.Consoles"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Title="{Loc 'atmos-monitoring-window-title'}"
Resizable="False"
SetSize="1120 750"
MinSize="1120 750">
<BoxContainer Orientation="Vertical">
<!-- Main display -->
<BoxContainer Orientation="Horizontal" VerticalExpand="True" HorizontalExpand="True">
<!-- Nav map -->
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<ui:AtmosMonitoringConsoleNavMapControl Name="NavMap" Margin="5 5" VerticalExpand="True" HorizontalExpand="True">
<!-- System warning -->
<PanelContainer Name="SystemWarningPanel"
HorizontalAlignment="Center"
VerticalAlignment="Top"
HorizontalExpand="True"
Margin="0 48 0 0"
Visible="False">
<RichTextLabel Name="SystemWarningLabel" Margin="12 8 12 8"/>
</PanelContainer>
</ui:AtmosMonitoringConsoleNavMapControl>
<!-- Nav map legend -->
<BoxContainer Orientation="Horizontal" Margin="0 10 0 10">
<TextureRect Stretch="KeepAspectCentered"
TexturePath="/Textures/Interface/NavMap/beveled_square.png"
Modulate="#a9a9a9"
SetSize="16 16"
Margin="20 0 5 0"/>
<Label Text="{Loc 'atmos-monitoring-window-label-gas-opening'}"/>
<TextureRect Stretch="KeepAspectCentered"
TexturePath="/Textures/Interface/NavMap/beveled_circle.png"
SetSize="16 16"
Modulate="#a9a9a9"
Margin="20 0 5 0"/>
<Label Text="{Loc 'atmos-monitoring-window-label-gas-scrubber'}"/>
<TextureRect Stretch="KeepAspectCentered"
TexturePath="/Textures/Interface/NavMap/beveled_arrow_east.png"
SetSize="16 16"
Modulate="#a9a9a9"
Margin="20 0 5 0"/>
<Label Text="{Loc 'atmos-monitoring-window-label-gas-flow-regulator'}"/>
<TextureRect Stretch="KeepAspectCentered"
TexturePath="/Textures/Interface/NavMap/beveled_hexagon.png"
SetSize="16 16"
Modulate="#a9a9a9"
Margin="20 0 5 0"/>
<Label Text="{Loc 'atmos-monitoring-window-label-thermoregulator'}"/>
</BoxContainer>
</BoxContainer>
<!-- Atmosphere status -->
<BoxContainer Orientation="Vertical" VerticalExpand="True" SetWidth="440" Margin="0 0 10 10">
<!-- Station name -->
<controls:StripeBack>
<PanelContainer>
<RichTextLabel Name="StationName" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 5 0 3"/>
</PanelContainer>
</controls:StripeBack>
<!-- Alarm status (entries added by C# code) -->
<TabContainer Name="MasterTabContainer" VerticalExpand="True" HorizontalExpand="True" Margin="0 10 0 0">
<ScrollContainer HorizontalExpand="True" Margin="8, 8, 8, 8">
<BoxContainer Name="AtmosNetworksTable" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" Margin="0 0 0 10"/>
</ScrollContainer>
</TabContainer>
<!-- Overlay toggles -->
<BoxContainer Orientation="Vertical" Margin="0 10 0 0">
<Label Text="{Loc 'atmos-monitoring-window-toggle-overlays'}" Margin="0 0 0 5"/>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<CheckBox Name="ShowPipeNetwork" Text="{Loc 'atmos-monitoring-window-show-pipe-network'}" Pressed="True" HorizontalExpand="True"/>
<CheckBox Name="ShowGasPipeSensors" Text="{Loc 'atmos-monitoring-window-show-gas-pipe-sensors'}" Pressed="False" HorizontalExpand="True"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</BoxContainer>
<!-- Footer -->
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'atmos-monitoring-window-flavor-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'atmos-monitoring-window-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,455 @@
using Content.Client.Pinpointer.UI;
using Content.Client.UserInterface.Controls;
using Content.Shared.Atmos.Components;
using Content.Shared.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace Content.Client.Atmos.Consoles;
[GenerateTypedNameReferences]
public sealed partial class AtmosMonitoringConsoleWindow : FancyWindow
{
private readonly IEntityManager _entManager;
private readonly IPrototypeManager _protoManager;
private readonly SpriteSystem _spriteSystem;
private EntityUid? _owner;
private NetEntity? _focusEntity;
private int? _focusNetId;
private bool _autoScrollActive = false;
private readonly Color _unfocusedDeviceColor = Color.DimGray;
private ProtoId<NavMapBlipPrototype> _navMapConsoleProtoId = "NavMapConsole";
private ProtoId<NavMapBlipPrototype> _gasPipeSensorProtoId = "GasPipeSensor";
public AtmosMonitoringConsoleWindow(AtmosMonitoringConsoleBoundUserInterface userInterface, EntityUid? owner)
{
RobustXamlLoader.Load(this);
_entManager = IoCManager.Resolve<IEntityManager>();
_protoManager = IoCManager.Resolve<IPrototypeManager>();
_spriteSystem = _entManager.System<SpriteSystem>();
// Pass the owner to nav map
_owner = owner;
NavMap.Owner = _owner;
// Set nav map grid uid
var stationName = Loc.GetString("atmos-monitoring-window-unknown-location");
EntityCoordinates? consoleCoords = null;
if (_entManager.TryGetComponent<TransformComponent>(owner, out var xform))
{
consoleCoords = xform.Coordinates;
NavMap.MapUid = xform.GridUid;
// Assign station name
if (_entManager.TryGetComponent<MetaDataComponent>(xform.GridUid, out var stationMetaData))
stationName = stationMetaData.EntityName;
var msg = new FormattedMessage();
msg.TryAddMarkup(Loc.GetString("atmos-monitoring-window-station-name", ("stationName", stationName)), out _);
StationName.SetMessage(msg);
}
else
{
StationName.SetMessage(stationName);
NavMap.Visible = false;
}
// Set trackable entity selected action
NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap;
// Update nav map
NavMap.ForceNavMapUpdate();
// Set tab container headers
MasterTabContainer.SetTabTitle(0, Loc.GetString("atmos-monitoring-window-tab-networks"));
// Set UI toggles
ShowPipeNetwork.OnToggled += _ => OnShowPipeNetworkToggled();
ShowGasPipeSensors.OnToggled += _ => OnShowGasPipeSensors();
// Set nav map colors
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner, out var console))
return;
NavMap.TileColor = console.NavMapTileColor;
NavMap.WallColor = console.NavMapWallColor;
// Initalize
UpdateUI(consoleCoords, Array.Empty<AtmosMonitoringConsoleEntry>());
}
#region Toggle handling
private void OnShowPipeNetworkToggled()
{
if (_owner == null)
return;
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner.Value, out var console))
return;
NavMap.ShowPipeNetwork = ShowPipeNetwork.Pressed;
foreach (var (netEnt, device) in console.AtmosDevices)
{
if (device.NavMapBlip == _gasPipeSensorProtoId)
continue;
if (ShowPipeNetwork.Pressed)
AddTrackedEntityToNavMap(device);
else
NavMap.TrackedEntities.Remove(netEnt);
}
}
private void OnShowGasPipeSensors()
{
if (_owner == null)
return;
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner.Value, out var console))
return;
foreach (var (netEnt, device) in console.AtmosDevices)
{
if (device.NavMapBlip != _gasPipeSensorProtoId)
continue;
if (ShowGasPipeSensors.Pressed)
AddTrackedEntityToNavMap(device, true);
else
NavMap.TrackedEntities.Remove(netEnt);
}
}
#endregion
public void UpdateUI
(EntityCoordinates? consoleCoords,
AtmosMonitoringConsoleEntry[] atmosNetworks)
{
if (_owner == null)
return;
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner.Value, out var console))
return;
// Reset nav map values
NavMap.TrackedCoordinates.Clear();
NavMap.TrackedEntities.Clear();
if (_focusEntity != null && !console.AtmosDevices.Any(x => x.Key == _focusEntity))
ClearFocus();
// Add tracked entities to the nav map
UpdateNavMapBlips();
// Show the monitor location
var consoleNetEnt = _entManager.GetNetEntity(_owner);
if (consoleCoords != null && consoleNetEnt != null)
{
var proto = _protoManager.Index(_navMapConsoleProtoId);
if (proto.TexturePaths != null && proto.TexturePaths.Length != 0)
{
var texture = _spriteSystem.Frame0(new SpriteSpecifier.Texture(proto.TexturePaths[0]));
var blip = new NavMapBlip(consoleCoords.Value, texture, proto.Color, proto.Blinks, proto.Selectable);
NavMap.TrackedEntities[consoleNetEnt.Value] = blip;
}
}
// Update the nav map
NavMap.ForceNavMapUpdate();
// Clear excess children from the tables
while (AtmosNetworksTable.ChildCount > atmosNetworks.Length)
AtmosNetworksTable.RemoveChild(AtmosNetworksTable.GetChild(AtmosNetworksTable.ChildCount - 1));
// Update all entries in each table
for (int index = 0; index < atmosNetworks.Length; index++)
{
var entry = atmosNetworks.ElementAt(index);
UpdateUIEntry(entry, index, AtmosNetworksTable, console);
}
}
private void UpdateNavMapBlips()
{
if (_owner == null || !_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner.Value, out var console))
return;
if (NavMap.Visible)
{
foreach (var (netEnt, device) in console.AtmosDevices)
{
// Update the focus network ID, incase it has changed
if (_focusEntity == netEnt)
{
_focusNetId = device.NetId;
NavMap.FocusNetId = _focusNetId;
}
var isSensor = device.NavMapBlip == _gasPipeSensorProtoId;
// Skip network devices if the toggled is off
if (!ShowPipeNetwork.Pressed && !isSensor)
continue;
// Skip gas pipe sensors if the toggle is off
if (!ShowGasPipeSensors.Pressed && isSensor)
continue;
AddTrackedEntityToNavMap(device, isSensor);
}
}
}
private void AddTrackedEntityToNavMap(AtmosDeviceNavMapData metaData, bool isSensor = false)
{
var proto = _protoManager.Index(metaData.NavMapBlip);
if (proto.TexturePaths == null || proto.TexturePaths.Length == 0)
return;
var idx = Math.Clamp((int)metaData.Direction / 2, 0, proto.TexturePaths.Length - 1);
var texture = proto.TexturePaths.Length > 0 ? proto.TexturePaths[idx] : proto.TexturePaths[0];
var color = isSensor ? proto.Color : proto.Color * metaData.PipeColor;
if (_focusNetId != null && metaData.NetId != _focusNetId)
color *= _unfocusedDeviceColor;
var blinks = proto.Blinks || _focusEntity == metaData.NetEntity;
var coords = _entManager.GetCoordinates(metaData.NetCoordinates);
var blip = new NavMapBlip(coords, _spriteSystem.Frame0(new SpriteSpecifier.Texture(texture)), color, blinks, proto.Selectable, proto.Scale);
NavMap.TrackedEntities[metaData.NetEntity] = blip;
}
private void UpdateUIEntry(AtmosMonitoringConsoleEntry data, int index, Control table, AtmosMonitoringConsoleComponent console)
{
// Make new UI entry if required
if (index >= table.ChildCount)
{
var newEntryContainer = new AtmosMonitoringEntryContainer(data);
// On click
newEntryContainer.FocusButton.OnButtonUp += args =>
{
if (_focusEntity == newEntryContainer.Data.NetEntity)
{
ClearFocus();
}
else
{
SetFocus(newEntryContainer.Data.NetEntity, newEntryContainer.Data.NetId);
var coords = _entManager.GetCoordinates(newEntryContainer.Data.Coordinates);
NavMap.CenterToCoordinates(coords);
}
// Update affected UI elements across all tables
UpdateConsoleTable(console, AtmosNetworksTable, _focusEntity);
};
// Add the entry to the current table
table.AddChild(newEntryContainer);
}
// Update values and UI elements
var tableChild = table.GetChild(index);
if (tableChild is not AtmosMonitoringEntryContainer)
{
table.RemoveChild(tableChild);
UpdateUIEntry(data, index, table, console);
return;
}
var entryContainer = (AtmosMonitoringEntryContainer)tableChild;
entryContainer.UpdateEntry(data, data.NetEntity == _focusEntity);
}
private void UpdateConsoleTable(AtmosMonitoringConsoleComponent console, Control table, NetEntity? currTrackedEntity)
{
foreach (var tableChild in table.Children)
{
if (tableChild is not AtmosAlarmEntryContainer)
continue;
var entryContainer = (AtmosAlarmEntryContainer)tableChild;
if (entryContainer.NetEntity != currTrackedEntity)
entryContainer.RemoveAsFocus();
else if (entryContainer.NetEntity == currTrackedEntity)
entryContainer.SetAsFocus();
}
}
private void SetTrackedEntityFromNavMap(NetEntity? focusEntity)
{
if (focusEntity == null)
return;
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner, out var console))
return;
foreach (var (netEnt, device) in console.AtmosDevices)
{
if (netEnt != focusEntity)
continue;
if (device.NavMapBlip != _gasPipeSensorProtoId)
return;
// Set new focus
SetFocus(focusEntity.Value, device.NetId);
// Get the scroll position of the selected entity on the selected button the UI
ActivateAutoScrollToFocus();
break;
}
}
protected override void FrameUpdate(FrameEventArgs args)
{
AutoScrollToFocus();
}
private void ActivateAutoScrollToFocus()
{
_autoScrollActive = true;
}
private void AutoScrollToFocus()
{
if (!_autoScrollActive)
return;
var scroll = AtmosNetworksTable.Parent as ScrollContainer;
if (scroll == null)
return;
if (!TryGetVerticalScrollbar(scroll, out var vScrollbar))
return;
if (!TryGetNextScrollPosition(out float? nextScrollPosition))
return;
vScrollbar.ValueTarget = nextScrollPosition.Value;
if (MathHelper.CloseToPercent(vScrollbar.Value, vScrollbar.ValueTarget))
_autoScrollActive = false;
}
private bool TryGetVerticalScrollbar(ScrollContainer scroll, [NotNullWhen(true)] out VScrollBar? vScrollBar)
{
vScrollBar = null;
foreach (var control in scroll.Children)
{
if (control is not VScrollBar)
continue;
vScrollBar = (VScrollBar)control;
return true;
}
return false;
}
private bool TryGetNextScrollPosition([NotNullWhen(true)] out float? nextScrollPosition)
{
nextScrollPosition = null;
var scroll = AtmosNetworksTable.Parent as ScrollContainer;
if (scroll == null)
return false;
var container = scroll.Children.ElementAt(0) as BoxContainer;
if (container == null || container.Children.Count() == 0)
return false;
// Exit if the heights of the children haven't been initialized yet
if (!container.Children.Any(x => x.Height > 0))
return false;
nextScrollPosition = 0;
foreach (var control in container.Children)
{
if (control is not AtmosMonitoringEntryContainer)
continue;
var entry = (AtmosMonitoringEntryContainer)control;
if (entry.Data.NetEntity == _focusEntity)
return true;
nextScrollPosition += control.Height;
}
// Failed to find control
nextScrollPosition = null;
return false;
}
private void SetFocus(NetEntity focusEntity, int focusNetId)
{
_focusEntity = focusEntity;
_focusNetId = focusNetId;
NavMap.FocusNetId = focusNetId;
OnFocusChanged();
}
private void ClearFocus()
{
_focusEntity = null;
_focusNetId = null;
NavMap.FocusNetId = null;
OnFocusChanged();
}
private void OnFocusChanged()
{
UpdateNavMapBlips();
NavMap.ForceNavMapUpdate();
if (!_entManager.TryGetComponent<AtmosMonitoringConsoleComponent>(_owner, out var console))
return;
for (int index = 0; index < AtmosNetworksTable.ChildCount; index++)
{
var entry = (AtmosMonitoringEntryContainer)AtmosNetworksTable.GetChild(index);
if (entry == null)
continue;
UpdateUIEntry(entry.Data, index, AtmosNetworksTable, console);
}
}
}

View File

@@ -0,0 +1,74 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Orientation="Vertical" HorizontalExpand ="True" Margin="0 0 0 3">
<!-- Network selection button -->
<Button Name="FocusButton" HorizontalExpand="True" VerticalExpand="True" Margin="0 0 6 8" StyleClasses="OpenLeft" Access="Public">
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Horizontal" SetHeight="32">
<PanelContainer Name="NetworkColorStripe" HorizontalAlignment="Left" SetWidth="8" VerticalExpand="True" Margin="-8 -2 0 0">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#d7d7d7"/>
</PanelContainer.PanelOverride>
</PanelContainer>
<Label Name="NetworkNameLabel" Text="???" HorizontalExpand="True" HorizontalAlignment="Center"/>
</BoxContainer>
<!-- Panel that appears on selecting the device -->
<PanelContainer HorizontalExpand="True" Margin="-8 0 -14 -4" Access="Public">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#25252a"/>
</PanelContainer.PanelOverride>
<BoxContainer Name="MainDataContainer" HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<Control>
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<BoxContainer HorizontalExpand="True" Orientation="Horizontal">
<Label Name="TemperatureHeaderLabel" Text="{Loc 'atmos-alerts-window-temperature-label'}" HorizontalAlignment="Center" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="0 2 0 0" SetHeight="24"></Label>
<Label Name="PressureHeaderLabel" Text="{Loc 'atmos-alerts-window-pressure-label'}" HorizontalAlignment="Center" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="0 2 0 0" SetHeight="24"></Label>
<Label Name="TotalMolHeaderLabel" Text="{Loc 'atmos-alerts-window-total-mol-label'}" HorizontalAlignment="Center" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="0 2 0 0" SetHeight="24"></Label>
</BoxContainer>
<PanelContainer HorizontalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#202023"/>
</PanelContainer.PanelOverride>
<BoxContainer HorizontalExpand="True" Orientation="Horizontal">
<Label Name="TemperatureLabel" Text="???" HorizontalAlignment="Center" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="0 2 0 0" SetHeight="24"></Label>
<Label Name="PressureLabel" Text="???" HorizontalAlignment="Center" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="0 2 0 0" SetHeight="24"></Label>
<Label Name="TotalMolLabel" Text="???" HorizontalAlignment="Center" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="0 2 0 0" SetHeight="24"></Label>
</BoxContainer>
</PanelContainer>
<BoxContainer HorizontalExpand="True" Orientation="Horizontal" Margin="8 0">
<TextureRect Name="ArrowTexture" VerticalAlignment="Center" SetSize="12 12" Stretch="KeepAspectCentered" Margin="3 0" TexturePath="/Textures/Interface/Nano/triangle_right.png"></TextureRect>
<Label Name="GasesHeaderLabel" Text="{Loc 'atmos-monitoring-window-label-gases'}" HorizontalAlignment="Left" HorizontalExpand="True" FontColorOverride="#a9a9a9" Margin="4 0 0 0" SetHeight="24"></Label>
</BoxContainer>
</BoxContainer>
</Control>
<!-- Atmosphere status -->
<Control Name="FocusContainer" ReservesSpace="False" Visible="False">
<!-- Main container for displaying atmospheric data -->
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<PanelContainer HorizontalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#202023"/>
</PanelContainer.PanelOverride>
<!-- Gas entries added via C# code -->
<GridContainer Name="GasGridContainer" HorizontalExpand="True" Columns = "4"></GridContainer>
</PanelContainer>
</BoxContainer>
</Control>
</BoxContainer>
<!-- If the alarm is inactive, this is label is displayed instead -->
<Label Name="NoDataLabel" Text="{Loc 'atmos-alerts-window-no-data-available'}" HorizontalAlignment="Center" Margin="0 15" FontColorOverride="#a9a9a9" ReservesSpace="False" Visible="False"></Label>
</PanelContainer>
</BoxContainer>
</Button>
</BoxContainer>

View File

@@ -0,0 +1,166 @@
using Content.Client.Stylesheets;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Temperature;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using System.Linq;
namespace Content.Client.Atmos.Consoles;
[GenerateTypedNameReferences]
public sealed partial class AtmosMonitoringEntryContainer : BoxContainer
{
public AtmosMonitoringConsoleEntry Data;
private readonly IEntityManager _entManager;
private readonly IResourceCache _cache;
public AtmosMonitoringEntryContainer(AtmosMonitoringConsoleEntry data)
{
RobustXamlLoader.Load(this);
_entManager = IoCManager.Resolve<IEntityManager>();
_cache = IoCManager.Resolve<IResourceCache>();
Data = data;
// Modulate colored stripe
NetworkColorStripe.Modulate = data.Color;
// Load fonts
var headerFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Bold.ttf"), 11);
var normalFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSansDisplay/NotoSansDisplay-Regular.ttf"), 11);
// Set fonts
TemperatureHeaderLabel.FontOverride = headerFont;
PressureHeaderLabel.FontOverride = headerFont;
TotalMolHeaderLabel.FontOverride = headerFont;
GasesHeaderLabel.FontOverride = headerFont;
TemperatureLabel.FontOverride = normalFont;
PressureLabel.FontOverride = normalFont;
TotalMolLabel.FontOverride = normalFont;
NoDataLabel.FontOverride = headerFont;
}
public void UpdateEntry(AtmosMonitoringConsoleEntry updatedData, bool isFocus)
{
// Load fonts
var normalFont = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSansDisplay/NotoSansDisplay-Regular.ttf"), 11);
// Update name and values
if (!string.IsNullOrEmpty(updatedData.Address))
NetworkNameLabel.Text = Loc.GetString("atmos-alerts-window-alarm-label", ("name", updatedData.EntityName), ("address", updatedData.Address));
else
NetworkNameLabel.Text = Loc.GetString(updatedData.EntityName);
Data = updatedData;
// Modulate colored stripe
NetworkColorStripe.Modulate = Data.Color;
// Focus updates
if (isFocus)
SetAsFocus();
else
RemoveAsFocus();
// Check if powered
if (!updatedData.IsPowered)
{
MainDataContainer.Visible = false;
NoDataLabel.Visible = true;
return;
}
// Set container visibility
MainDataContainer.Visible = true;
NoDataLabel.Visible = false;
// Update temperature
var isNotVacuum = updatedData.TotalMolData > 1e-6f;
var tempK = (FixedPoint2)updatedData.TemperatureData;
var tempC = (FixedPoint2)TemperatureHelpers.KelvinToCelsius(tempK.Float());
TemperatureLabel.Text = isNotVacuum ?
Loc.GetString("atmos-alerts-window-temperature-value", ("valueInC", tempC), ("valueInK", tempK)) :
Loc.GetString("atmos-alerts-window-invalid-value");
TemperatureLabel.FontColorOverride = isNotVacuum ? Color.DarkGray : StyleNano.DisabledFore;
// Update pressure
PressureLabel.Text = Loc.GetString("atmos-alerts-window-pressure-value", ("value", (FixedPoint2)updatedData.PressureData));
PressureLabel.FontColorOverride = isNotVacuum ? Color.DarkGray : StyleNano.DisabledFore;
// Update total mol
TotalMolLabel.Text = Loc.GetString("atmos-alerts-window-total-mol-value", ("value", (FixedPoint2)updatedData.TotalMolData));
TotalMolLabel.FontColorOverride = isNotVacuum ? Color.DarkGray : StyleNano.DisabledFore;
// Update other present gases
GasGridContainer.RemoveAllChildren();
if (updatedData.GasData.Count() == 0)
{
// No gases
var gasLabel = new Label()
{
Text = Loc.GetString("atmos-alerts-window-other-gases-value-nil"),
FontOverride = normalFont,
FontColorOverride = StyleNano.DisabledFore,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
HorizontalExpand = true,
Margin = new Thickness(0, 2, 0, 0),
SetHeight = 24f,
};
GasGridContainer.AddChild(gasLabel);
}
else
{
// Add an entry for each gas
foreach (var (gas, percent) in updatedData.GasData)
{
var gasPercent = (FixedPoint2)0f;
gasPercent = percent * 100f;
var gasAbbreviation = Atmospherics.GasAbbreviations.GetValueOrDefault(gas, Loc.GetString("gas-unknown-abbreviation"));
var gasLabel = new Label()
{
Text = Loc.GetString("atmos-alerts-window-other-gases-value", ("shorthand", gasAbbreviation), ("value", gasPercent)),
FontOverride = normalFont,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
HorizontalExpand = true,
Margin = new Thickness(0, 2, 0, 0),
SetHeight = 24f,
};
GasGridContainer.AddChild(gasLabel);
}
}
}
public void SetAsFocus()
{
FocusButton.AddStyleClass(StyleNano.StyleClassButtonColorGreen);
ArrowTexture.TexturePath = "/Textures/Interface/Nano/inverted_triangle.svg.png";
FocusContainer.Visible = true;
}
public void RemoveAsFocus()
{
FocusButton.RemoveStyleClass(StyleNano.StyleClassButtonColorGreen);
ArrowTexture.TexturePath = "/Textures/Interface/Nano/triangle_right.png";
FocusContainer.Visible = false;
}
}

View File

@@ -4,8 +4,6 @@ using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
namespace Content.Client.Atmos.EntitySystems;
@@ -19,7 +17,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<PipeAppearanceComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: new[] { typeof(SubFloorHideSystem) });
SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: [typeof(SubFloorHideSystem)]);
}
private void OnInit(EntityUid uid, PipeAppearanceComponent component, ComponentInit args)
@@ -84,7 +82,8 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
layer.Visible &= visible;
if (!visible) continue;
if (!visible)
continue;
layer.Color = color;
}

View File

@@ -0,0 +1,23 @@
using Content.Client.Atmos.UI;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping.Binary.Components;
namespace Content.Client.Atmos.EntitySystems;
public sealed class GasPressurePumpSystem : SharedGasPressurePumpSystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasPressurePumpComponent, AfterAutoHandleStateEvent>(OnPumpUpdate);
}
private void OnPumpUpdate(Entity<GasPressurePumpComponent> ent, ref AfterAutoHandleStateEvent args)
{
if (UserInterfaceSystem.TryGetOpenUi<GasPressurePumpBoundUserInterface>(ent.Owner, GasPressurePumpUiKey.Key, out var bui))
{
bui.Update();
}
}
}

View File

@@ -1,12 +1,7 @@
using System.Collections.Generic;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Power;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Client.Atmos.Monitor;
@@ -27,7 +22,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var visLayer in component.HideOnDepowered)
{
if (args.Sprite.LayerMapTryGet(visLayer, out int powerVisibilityLayer))
if (args.Sprite.LayerMapTryGet(visLayer, out var powerVisibilityLayer))
args.Sprite.LayerSetVisible(powerVisibilityLayer, powered);
}
}
@@ -36,7 +31,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var (setLayer, powerState) in component.SetOnDepowered)
{
if (args.Sprite.LayerMapTryGet(setLayer, out int setStateLayer))
if (args.Sprite.LayerMapTryGet(setLayer, out var setStateLayer))
args.Sprite.LayerSetState(setStateLayer, new RSI.StateId(powerState));
}
}

View File

@@ -1,11 +1,7 @@
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
namespace Content.Client.Atmos.Monitor.UI;
@@ -78,6 +74,7 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface
{
base.Dispose(disposing);
if (disposing) _window?.Dispose();
if (disposing)
_window?.Dispose();
}
}

View File

@@ -8,7 +8,6 @@ using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Temperature;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
@@ -59,7 +58,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
AirAlarmMode.Fill => "air-alarm-ui-mode-fill",
AirAlarmMode.Panic => "air-alarm-ui-mode-panic",
AirAlarmMode.None => "air-alarm-ui-mode-none",
_ => "error"
_ => "error",
};
_modes.AddItem(Loc.GetString(text));
}
@@ -70,7 +69,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
AirAlarmModeChanged!.Invoke((AirAlarmMode) args.Id);
};
_autoMode.OnToggled += args =>
_autoMode.OnToggled += _ =>
{
AutoModeChanged!.Invoke(_autoMode.Pressed);
};
@@ -176,22 +175,18 @@ public sealed partial class AirAlarmWindow : FancyWindow
public static Color ColorForThreshold(float amount, AtmosAlarmThreshold threshold)
{
threshold.CheckThreshold(amount, out AtmosAlarmType curAlarm);
threshold.CheckThreshold(amount, out var curAlarm);
return ColorForAlarm(curAlarm);
}
public static Color ColorForAlarm(AtmosAlarmType curAlarm)
{
if(curAlarm == AtmosAlarmType.Danger)
return curAlarm switch
{
return StyleNano.DangerousRedFore;
}
else if(curAlarm == AtmosAlarmType.Warning)
{
return StyleNano.ConcerningOrangeFore;
}
return StyleNano.GoodGreenFore;
AtmosAlarmType.Danger => StyleNano.DangerousRedFore,
AtmosAlarmType.Warning => StyleNano.ConcerningOrangeFore,
_ => StyleNano.GoodGreenFore,
};
}

View File

@@ -1,12 +1,8 @@
using System;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
namespace Content.Client.Atmos.Monitor.UI.Widgets;
@@ -25,7 +21,7 @@ public sealed partial class PumpControl : BoxContainer
private OptionButton _pressureCheck => CPressureCheck;
private FloatSpinBox _externalBound => CExternalBound;
private FloatSpinBox _internalBound => CInternalBound;
private Button _copySettings => CCopySettings;
private Button _copySettings => CCopySettings;
public PumpControl(GasVentPumpData data, string address)
{
@@ -86,7 +82,7 @@ public sealed partial class PumpControl : BoxContainer
_data.PressureChecks = (VentPressureBound) args.Id;
PumpDataChanged?.Invoke(_address, _data);
};
_copySettings.OnPressed += _ =>
{
PumpDataCopied?.Invoke(_data);

View File

@@ -1,15 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
namespace Content.Client.Atmos.Monitor.UI.Widgets;
@@ -27,7 +21,7 @@ public sealed partial class ScrubberControl : BoxContainer
private OptionButton _pumpDirection => CPumpDirection;
private FloatSpinBox _volumeRate => CVolumeRate;
private CheckBox _wideNet => CWideNet;
private Button _copySettings => CCopySettings;
private Button _copySettings => CCopySettings;
private GridContainer _gases => CGasContainer;
private Dictionary<Gas, Button> _gasControls = new();
@@ -77,7 +71,7 @@ public sealed partial class ScrubberControl : BoxContainer
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
ScrubberDataChanged?.Invoke(_address, _data);
};
_copySettings.OnPressed += _ =>
{
ScrubberDataCopied?.Invoke(_data);

View File

@@ -43,7 +43,8 @@ public sealed partial class SensorInfo : BoxContainer
var label = new RichTextLabel();
var fractionGas = amount / data.TotalMoles;
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator", ("gas", $"{gas}"),
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
("gas", $"{gas}"),
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
("amount", $"{amount:0.####}"),
("percentage", $"{(100 * fractionGas):0.##}")));
@@ -53,9 +54,9 @@ public sealed partial class SensorInfo : BoxContainer
var threshold = data.GasThresholds[gas];
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title", ("gas", $"{gas}")), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
gasThresholdControl.ThresholdDataChanged += (type, threshold, arg3) =>
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
{
OnThresholdUpdate!(_address, type, threshold, arg3);
OnThresholdUpdate!(_address, type, alarmThreshold, arg3);
};
_gasThresholds.Add(gas, gasThresholdControl);
@@ -64,7 +65,8 @@ public sealed partial class SensorInfo : BoxContainer
_pressureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-pressure-title"), data.PressureThreshold, AtmosMonitorThresholdType.Pressure);
PressureThresholdContainer.AddChild(_pressureThreshold);
_temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"), data.TemperatureThreshold,
_temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"),
data.TemperatureThreshold,
AtmosMonitorThresholdType.Temperature);
TemperatureThresholdContainer.AddChild(_temperatureThreshold);
@@ -103,7 +105,8 @@ public sealed partial class SensorInfo : BoxContainer
}
var fractionGas = amount / data.TotalMoles;
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator", ("gas", $"{gas}"),
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
("gas", $"{gas}"),
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
("amount", $"{amount:0.####}"),
("percentage", $"{(100 * fractionGas):0.##}")));

View File

@@ -1,7 +1,4 @@
using Content.Client.Message;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Temperature;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

View File

@@ -1,12 +1,8 @@
using System;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
// holy FUCK
// this technically works because some of this you can *not* do in XAML but holy FUCK
@@ -115,29 +111,38 @@ public sealed partial class ThresholdControl : BoxContainer
_enabled.Pressed = !_threshold.Ignore;
}
private String LabelForBound(string boundType) //<todo.eoin Replace this with enums
private string LabelForBound(string boundType) //<todo.eoin Replace this with enums
{
return Loc.GetString($"air-alarm-ui-thresholds-{boundType}");
}
public void UpdateThresholdData(AtmosAlarmThreshold threshold, float currentAmount)
{
threshold.CheckThreshold(currentAmount, out AtmosAlarmType alarm, out AtmosMonitorThresholdBound which);
threshold.CheckThreshold(currentAmount, out var alarm, out var bound);
var upperDangerState = AtmosAlarmType.Normal;
var lowerDangerState = AtmosAlarmType.Normal;
var upperWarningState = AtmosAlarmType.Normal;
var lowerWarningState = AtmosAlarmType.Normal;
if(alarm == AtmosAlarmType.Danger)
switch (alarm)
{
if(which == AtmosMonitorThresholdBound.Upper) upperDangerState = alarm;
else lowerDangerState = alarm;
}
else if(alarm == AtmosAlarmType.Warning)
{
if(which == AtmosMonitorThresholdBound.Upper) upperWarningState = alarm;
else lowerWarningState = alarm;
case AtmosAlarmType.Danger:
{
if (bound == AtmosMonitorThresholdBound.Upper)
upperDangerState = alarm;
else
lowerDangerState = alarm;
break;
}
case AtmosAlarmType.Warning:
{
if (bound == AtmosMonitorThresholdBound.Upper)
upperWarningState = alarm;
else
lowerWarningState = alarm;
break;
}
}
_upperBoundControl.SetValue(threshold.UpperBound.Value);

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using System.Linq;
using System.Numerics;
using Content.Client.Atmos.EntitySystems;
@@ -101,14 +102,9 @@ public sealed class AtmosDebugOverlay : Overlay
else
{
// Red-Green-Blue interpolation
if (interp < 0.5f)
{
res = Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2);
}
else
{
res = Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
}
res = interp < 0.5f
? Color.InterpolateBetween(Color.Red, Color.LimeGreen, interp * 2)
: Color.InterpolateBetween(Color.LimeGreen, Color.Blue, (interp - 0.5f) * 2);
}
res = res.WithAlpha(0.75f);
@@ -181,7 +177,10 @@ public sealed class AtmosDebugOverlay : Overlay
handle.DrawCircle(tileCentre, 0.05f, Color.Black);
}
private void CheckAndShowBlockDir(AtmosDebugOverlayData data, DrawingHandleWorld handle, AtmosDirection dir,
private void CheckAndShowBlockDir(
AtmosDebugOverlayData data,
DrawingHandleWorld handle,
AtmosDirection dir,
Vector2 tileCentre)
{
if (!data.BlockDirection.HasFlag(dir))
@@ -243,7 +242,7 @@ public sealed class AtmosDebugOverlay : Overlay
var moles = data.Moles == null
? "No Air"
: data.Moles.Sum().ToString();
: data.Moles.Sum().ToString(CultureInfo.InvariantCulture);
handle.DrawString(_font, pos, $"Moles: {moles}");
pos += offset;
@@ -263,7 +262,12 @@ public sealed class AtmosDebugOverlay : Overlay
private void GetGrids(MapId mapId, Box2Rotated box)
{
_grids.Clear();
_mapManager.FindGridsIntersecting(mapId, box, ref _grids, (EntityUid uid, MapGridComponent grid,
_mapManager.FindGridsIntersecting(
mapId,
box,
ref _grids,
(EntityUid uid,
MapGridComponent grid,
ref List<(Entity<MapGridComponent>, DebugMessage)> state) =>
{
if (_system.TileData.TryGetValue(uid, out var data))

View File

@@ -1,65 +1,63 @@
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Localizations;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Atmos.UI
namespace Content.Client.Atmos.UI;
/// <summary>
/// Initializes a <see cref="GasPressurePumpWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public sealed class GasPressurePumpBoundUserInterface : BoundUserInterface
{
/// <summary>
/// Initializes a <see cref="GasPressurePumpWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public sealed class GasPressurePumpBoundUserInterface : BoundUserInterface
[ViewVariables]
private const float MaxPressure = Atmospherics.MaxOutputPressure;
[ViewVariables]
private GasPressurePumpWindow? _window;
public GasPressurePumpBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
[ViewVariables]
private const float MaxPressure = Atmospherics.MaxOutputPressure;
}
[ViewVariables]
private GasPressurePumpWindow? _window;
protected override void Open()
{
base.Open();
public GasPressurePumpBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
_window = this.CreateWindow<GasPressurePumpWindow>();
protected override void Open()
{
base.Open();
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
_window.PumpOutputPressureChanged += OnPumpOutputPressurePressed;
Update();
}
_window = this.CreateWindow<GasPressurePumpWindow>();
public void Update()
{
if (_window == null)
return;
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
_window.PumpOutputPressureChanged += OnPumpOutputPressurePressed;
}
_window.Title = Identity.Name(Owner, EntMan);
private void OnToggleStatusButtonPressed()
{
if (_window is null) return;
SendMessage(new GasPressurePumpToggleStatusMessage(_window.PumpStatus));
}
if (!EntMan.TryGetComponent(Owner, out GasPressurePumpComponent? pump))
return;
private void OnPumpOutputPressurePressed(string value)
{
var pressure = UserInputParser.TryFloat(value, out var parsed) ? parsed : 0f;
if (pressure > MaxPressure) pressure = MaxPressure;
_window.SetPumpStatus(pump.Enabled);
_window.MaxPressure = pump.MaxTargetPressure;
_window.SetOutputPressure(pump.TargetPressure);
}
SendMessage(new GasPressurePumpChangeOutputPressureMessage(pressure));
}
private void OnToggleStatusButtonPressed()
{
if (_window is null) return;
SendPredictedMessage(new GasPressurePumpToggleStatusMessage(_window.PumpStatus));
}
/// <summary>
/// Update the UI state based on server-sent info
/// </summary>
/// <param name="state"></param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_window == null || state is not GasPressurePumpBoundUserInterfaceState cast)
return;
_window.Title = (cast.PumpLabel);
_window.SetPumpStatus(cast.Enabled);
_window.SetOutputPressure(cast.OutputPressure);
}
private void OnPumpOutputPressurePressed(float value)
{
SendPredictedMessage(new GasPressurePumpChangeOutputPressureMessage(value));
}
}

View File

@@ -1,22 +1,18 @@
<DefaultWindow xmlns="https://spacestation14.io"
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
MinSize="200 120" Title="Pressure Pump">
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
SetSize="340 110" MinSize="340 110" Title="Pressure Pump">
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Label Text="{Loc comp-gas-pump-ui-pump-status}"/>
<Control MinSize="5 0" />
<Label Text="{Loc comp-gas-pump-ui-pump-status}" Margin="0 0 5 0"/>
<Button Name="ToggleStatusButton"/>
<Control HorizontalExpand="True"/>
<Button HorizontalAlignment="Right" Name="SetOutputPressureButton" Text="{Loc comp-gas-pump-ui-pump-set-rate}" Disabled="True" Margin="0 0 5 0"/>
<Button Name="SetMaxPressureButton" Text="{Loc comp-gas-pump-ui-pump-set-max}" />
</BoxContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Label Text="{Loc comp-gas-pump-ui-pump-output-pressure}"/>
<Control MinSize="5 0" />
<LineEdit Name="PumpPressureOutputInput" MinSize="70 0" />
<Control MinSize="5 0" />
<Button Name="SetMaxPressureButton" Text="{Loc comp-gas-pump-ui-pump-set-max}" />
<Control MinSize="5 0" />
<Control HorizontalExpand="True" />
<Button Name="SetOutputPressureButton" Text="{Loc comp-gas-pump-ui-pump-set-rate}" HorizontalAlignment="Right" Disabled="True"/>
<FloatSpinBox HorizontalExpand="True" Name="PumpPressureOutputInput" MinSize="70 0" />
</BoxContainer>
</BoxContainer>
</DefaultWindow>
</controls:FancyWindow>

View File

@@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Content.Client.Atmos.EntitySystems;
using Content.Client.UserInterface.Controls;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
namespace Content.Client.Atmos.UI
{
@@ -16,12 +10,25 @@ namespace Content.Client.Atmos.UI
/// Client-side UI used to control a gas pressure pump.
/// </summary>
[GenerateTypedNameReferences]
public sealed partial class GasPressurePumpWindow : DefaultWindow
public sealed partial class GasPressurePumpWindow : FancyWindow
{
public bool PumpStatus = true;
public event Action? ToggleStatusButtonPressed;
public event Action<string>? PumpOutputPressureChanged;
public event Action<float>? PumpOutputPressureChanged;
public float MaxPressure
{
get => _maxPressure;
set
{
_maxPressure = value;
PumpPressureOutputInput.Value = MathF.Min(value, PumpPressureOutputInput.Value);
}
}
private float _maxPressure = Atmospherics.MaxOutputPressure;
public GasPressurePumpWindow()
{
@@ -30,23 +37,25 @@ namespace Content.Client.Atmos.UI
ToggleStatusButton.OnPressed += _ => SetPumpStatus(!PumpStatus);
ToggleStatusButton.OnPressed += _ => ToggleStatusButtonPressed?.Invoke();
PumpPressureOutputInput.OnTextChanged += _ => SetOutputPressureButton.Disabled = false;
PumpPressureOutputInput.OnValueChanged += _ => SetOutputPressureButton.Disabled = false;
SetOutputPressureButton.OnPressed += _ =>
{
PumpOutputPressureChanged?.Invoke(PumpPressureOutputInput.Text ??= "");
PumpPressureOutputInput.Value = Math.Clamp(PumpPressureOutputInput.Value, 0f, _maxPressure);
PumpOutputPressureChanged?.Invoke(PumpPressureOutputInput.Value);
SetOutputPressureButton.Disabled = true;
};
SetMaxPressureButton.OnPressed += _ =>
{
PumpPressureOutputInput.Text = Atmospherics.MaxOutputPressure.ToString(CultureInfo.CurrentCulture);
PumpPressureOutputInput.Value = _maxPressure;
SetOutputPressureButton.Disabled = false;
};
}
public void SetOutputPressure(float pressure)
{
PumpPressureOutputInput.Text = pressure.ToString(CultureInfo.CurrentCulture);
PumpPressureOutputInput.Value = pressure;
}
public void SetPumpStatus(bool enabled)

View File

@@ -2,6 +2,7 @@ using System.Numerics;
using Content.Client.Chat.Managers;
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Speech;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
@@ -141,7 +142,12 @@ namespace Content.Client.Chat.UI
Modulate = Color.White;
}
var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -EntityVerticalOffset;
var baseOffset = 0f;
if (_entityManager.TryGetComponent<SpeechComponent>(_senderEntity, out var speech))
baseOffset = speech.SpeechBubbleOffset;
var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -(EntityVerticalOffset + baseOffset);
var worldPos = _transformSystem.GetWorldPosition(xform) + offset;
var lowerCenter = _eyeManager.WorldToScreen(worldPos) / UIScale;

View File

@@ -12,6 +12,7 @@ using Robust.Shared.Utility;
using System.Linq;
using System.Numerics;
using Content.Shared.FixedPoint;
using Robust.Client.Graphics;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Chemistry.UI
@@ -90,10 +91,40 @@ namespace Content.Client.Chemistry.UI
private ReagentButton MakeReagentButton(string text, ChemMasterReagentAmount amount, ReagentId id, bool isBuffer, string styleClass)
{
var button = new ReagentButton(text, amount, id, isBuffer, styleClass);
button.OnPressed += args
=> OnReagentButtonPressed?.Invoke(args, button);
return button;
var reagentTransferButton = new ReagentButton(text, amount, id, isBuffer, styleClass);
reagentTransferButton.OnPressed += args
=> OnReagentButtonPressed?.Invoke(args, reagentTransferButton);
return reagentTransferButton;
}
/// <summary>
/// Conditionally generates a set of reagent buttons based on the supplied boolean argument.
/// This was moved outside of BuildReagentRow to facilitate conditional logic, stops indentation depth getting out of hand as well.
/// </summary>
private List<ReagentButton> CreateReagentTransferButtons(ReagentId reagent, bool isBuffer, bool addReagentButtons)
{
if (!addReagentButtons)
return new List<ReagentButton>(); // Return an empty list if reagentTransferButton creation is disabled.
var buttonConfigs = new (string text, ChemMasterReagentAmount amount, string styleClass)[]
{
("1", ChemMasterReagentAmount.U1, StyleBase.ButtonOpenBoth),
("5", ChemMasterReagentAmount.U5, StyleBase.ButtonOpenBoth),
("10", ChemMasterReagentAmount.U10, StyleBase.ButtonOpenBoth),
("25", ChemMasterReagentAmount.U25, StyleBase.ButtonOpenBoth),
("50", ChemMasterReagentAmount.U50, StyleBase.ButtonOpenBoth),
("100", ChemMasterReagentAmount.U100, StyleBase.ButtonOpenBoth),
(Loc.GetString("chem-master-window-buffer-all-amount"), ChemMasterReagentAmount.All, StyleBase.ButtonOpenLeft),
};
var buttons = new List<ReagentButton>();
foreach (var (text, amount, styleClass) in buttonConfigs)
{
var reagentTransferButton = MakeReagentButton(text, amount, reagent, isBuffer, styleClass);
buttons.Add(reagentTransferButton);
}
return buttons;
}
/// <summary>
@@ -102,25 +133,36 @@ namespace Content.Client.Chemistry.UI
/// <param name="state">State data sent by the server.</param>
public void UpdateState(BoundUserInterfaceState state)
{
var castState = (ChemMasterBoundUserInterfaceState) state;
var castState = (ChemMasterBoundUserInterfaceState)state;
if (castState.UpdateLabel)
LabelLine = GenerateLabel(castState);
// Ensure the Panel Info is updated, including UI elements for Buffer Volume, Output Container and so on
UpdatePanelInfo(castState);
var output = castState.OutputContainerInfo;
BufferCurrentVolume.Text = $" {castState.BufferCurrentVolume?.Int() ?? 0}u";
InputEjectButton.Disabled = castState.InputContainerInfo is null;
OutputEjectButton.Disabled = output is null;
CreateBottleButton.Disabled = output?.Reagents == null;
CreatePillButton.Disabled = output?.Entities == null;
OutputEjectButton.Disabled = castState.OutputContainerInfo is null;
CreateBottleButton.Disabled = castState.OutputContainerInfo?.Reagents == null;
CreatePillButton.Disabled = castState.OutputContainerInfo?.Entities == null;
UpdateDosageFields(castState);
}
//assign default values for pill and bottle fields.
private void UpdateDosageFields(ChemMasterBoundUserInterfaceState castState)
{
var output = castState.OutputContainerInfo;
var remainingCapacity = output is null ? 0 : (output.MaxVolume - output.CurrentVolume).Int();
var holdsReagents = output?.Reagents != null;
var pillNumberMax = holdsReagents ? 0 : remainingCapacity;
var bottleAmountMax = holdsReagents ? remainingCapacity : 0;
var bufferVolume = castState.BufferCurrentVolume?.Int() ?? 0;
PillDosage.Value = (int)Math.Min(bufferVolume, castState.PillDosageLimit);
PillTypeButtons[castState.SelectedPillType].Pressed = true;
PillNumber.IsValid = x => x >= 0 && x <= pillNumberMax;
PillDosage.IsValid = x => x > 0 && x <= castState.PillDosageLimit;
@@ -130,8 +172,19 @@ namespace Content.Client.Chemistry.UI
PillNumber.Value = pillNumberMax;
if (BottleDosage.Value > bottleAmountMax)
BottleDosage.Value = bottleAmountMax;
}
// Avoid division by zero
if (PillDosage.Value > 0)
{
PillNumber.Value = Math.Min(bufferVolume / PillDosage.Value, pillNumberMax);
}
else
{
PillNumber.Value = 0;
}
BottleDosage.Value = Math.Min(bottleAmountMax, bufferVolume);
}
/// <summary>
/// Generate a product label based on reagents in the buffer.
/// </summary>
@@ -178,46 +231,23 @@ namespace Content.Client.Chemistry.UI
var bufferVol = new Label
{
Text = $"{state.BufferCurrentVolume}u",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
};
bufferHBox.AddChild(bufferVol);
// initialises rowCount to allow for striped rows
var rowCount = 0;
foreach (var (reagent, quantity) in state.BufferReagents)
{
// Try to get the prototype for the given reagent. This gives us its name.
_prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto);
var reagentId = reagent;
_prototypeManager.TryIndex(reagentId.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
if (proto != null)
{
BufferInfo.Children.Add(new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label {Text = $"{name}: "},
new Label
{
Text = $"{quantity}u",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
},
// Padding
new Control {HorizontalExpand = true},
MakeReagentButton("1", ChemMasterReagentAmount.U1, reagent, true, StyleBase.ButtonOpenRight),
MakeReagentButton("5", ChemMasterReagentAmount.U5, reagent, true, StyleBase.ButtonOpenBoth),
MakeReagentButton("10", ChemMasterReagentAmount.U10, reagent, true, StyleBase.ButtonOpenBoth),
MakeReagentButton("25", ChemMasterReagentAmount.U25, reagent, true, StyleBase.ButtonOpenBoth),
MakeReagentButton("50", ChemMasterReagentAmount.U50, reagent, true, StyleBase.ButtonOpenBoth),
MakeReagentButton("100", ChemMasterReagentAmount.U100, reagent, true, StyleBase.ButtonOpenBoth),
MakeReagentButton(Loc.GetString("chem-master-window-buffer-all-amount"), ChemMasterReagentAmount.All, reagent, true, StyleBase.ButtonOpenLeft),
}
});
}
var reagentColor = proto?.SubstanceColor ?? default(Color);
BufferInfo.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagentId, quantity, true, true));
}
}
private void BuildContainerUI(Control control, ContainerInfo? info, bool addReagentButtons)
{
control.Children.Clear();
@@ -228,104 +258,111 @@ namespace Content.Client.Chemistry.UI
{
Text = Loc.GetString("chem-master-window-no-container-loaded-text")
});
return;
}
else
// Name of the container and its fill status (Ex: 44/100u)
control.Children.Add(new BoxContainer
{
// Name of the container and its fill status (Ex: 44/100u)
control.Children.Add(new BoxContainer
Orientation = LayoutOrientation.Horizontal,
Children =
{
Orientation = LayoutOrientation.Horizontal,
Children =
new Label { Text = $"{info.DisplayName}: " },
new Label
{
new Label {Text = $"{info.DisplayName}: "},
new Label
{
Text = $"{info.CurrentVolume}/{info.MaxVolume}",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
}
Text = $"{info.CurrentVolume}/{info.MaxVolume}",
StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
}
});
IEnumerable<(string Name, ReagentId Id, FixedPoint2 Quantity)> contents;
if (info.Entities != null)
{
contents = info.Entities.Select(x => (x.Id, default(ReagentId), x.Quantity));
}
else if (info.Reagents != null)
});
// Initialises rowCount to allow for striped rows
var rowCount = 0;
// Handle entities if they are not null
if (info.Entities != null)
{
foreach (var (id, quantity) in info.Entities.Select(x => (x.Id, x.Quantity)))
{
contents = info.Reagents.Select(x =>
{
_prototypeManager.TryIndex(x.Reagent.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName
?? Loc.GetString("chem-master-window-unknown-reagent-text");
return (name, Id: x.Reagent, x.Quantity);
})
.OrderBy(r => r.Item1);
control.Children.Add(BuildReagentRow(default(Color), rowCount++, id, default(ReagentId), quantity, false, addReagentButtons));
}
else
}
// Handle reagents if they are not null
if (info.Reagents != null)
{
foreach (var reagent in info.Reagents)
{
return;
_prototypeManager.TryIndex(reagent.Reagent.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
var reagentColor = proto?.SubstanceColor ?? default(Color);
control.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagent.Reagent, reagent.Quantity, false, addReagentButtons));
}
foreach (var (name, id, quantity) in contents)
{
var inner = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label { Text = $"{name}: " },
new Label
{
Text = $"{quantity}u",
StyleClasses = { StyleNano.StyleClassLabelSecondaryColor },
}
}
};
if (addReagentButtons)
{
var cs = inner.Children;
// Padding
cs.Add(new Control { HorizontalExpand = true });
cs.Add(MakeReagentButton(
"1", ChemMasterReagentAmount.U1, id, false, StyleBase.ButtonOpenRight));
cs.Add(MakeReagentButton(
"5", ChemMasterReagentAmount.U5, id, false, StyleBase.ButtonOpenBoth));
cs.Add(MakeReagentButton(
"10", ChemMasterReagentAmount.U10, id, false, StyleBase.ButtonOpenBoth));
cs.Add(MakeReagentButton(
"25", ChemMasterReagentAmount.U25, id, false, StyleBase.ButtonOpenBoth));
cs.Add(MakeReagentButton(
"50", ChemMasterReagentAmount.U50, id, false, StyleBase.ButtonOpenBoth));
cs.Add(MakeReagentButton(
"100", ChemMasterReagentAmount.U100, id, false, StyleBase.ButtonOpenBoth));
cs.Add(MakeReagentButton(
Loc.GetString("chem-master-window-buffer-all-amount"),
ChemMasterReagentAmount.All, id, false, StyleBase.ButtonOpenLeft));
}
control.Children.Add(inner);
}
}
}
public String LabelLine
/// <summary>
/// Take reagent/entity data and present rows, labels, and buttons appropriately. todo sprites?
/// </summary>
private Control BuildReagentRow(Color reagentColor, int rowCount, string name, ReagentId reagent, FixedPoint2 quantity, bool isBuffer, bool addReagentButtons)
{
get
//Colors rows and sets fallback for reagentcolor to the same as background, this will hide colorPanel for entities hopefully
var rowColor1 = Color.FromHex("#1B1B1E");
var rowColor2 = Color.FromHex("#202025");
var currentRowColor = (rowCount % 2 == 1) ? rowColor1 : rowColor2;
if ((reagentColor == default(Color))|(!addReagentButtons))
{
return LabelLineEdit.Text;
reagentColor = currentRowColor;
}
set
//this calls the separated button builder, and stores the return to render after labels
var reagentButtonConstructors = CreateReagentTransferButtons(reagent, isBuffer, addReagentButtons);
// Create the row layout with the color panel
var rowContainer = new BoxContainer
{
LabelLineEdit.Text = value;
Orientation = LayoutOrientation.Horizontal,
Children =
{
new Label { Text = $"{name}: " },
new Label
{
Text = $"{quantity}u",
StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
},
// Padding
new Control { HorizontalExpand = true },
// Colored panels for reagents
new PanelContainer
{
Name = "colorPanel",
VerticalExpand = true,
MinWidth = 4,
PanelOverride = new StyleBoxFlat
{
BackgroundColor = reagentColor
},
Margin = new Thickness(0, 1)
}
}
};
// Add the reagent buttons after the color panel
foreach (var reagentTransferButton in reagentButtonConstructors)
{
rowContainer.AddChild(reagentTransferButton);
}
//Apply panencontainer to allow for striped rows
return new PanelContainer
{
PanelOverride = new StyleBoxFlat(currentRowColor),
Children = { rowContainer }
};
}
public string LabelLine
{
get => LabelLineEdit.Text;
set => LabelLineEdit.Text = value;
}
}

View File

@@ -7,7 +7,7 @@ using Robust.Client.GameObjects;
namespace Content.Client.Clothing;
public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<FlippableClothingVisualsComponent>
public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<FlippableClothingVisualsComponent>
{
[Dependency] private readonly SharedItemSystem _itemSys = default!;

View File

@@ -1,17 +1,62 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'comms-console-menu-title'}"
MinSize="400 225">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" Margin="5">
<TextEdit Name="MessageInput" HorizontalExpand="True" VerticalExpand="True" Margin="0 0 0 5" MinHeight="100" />
<Button Name="AnnounceButton" Text="{Loc 'comms-console-menu-announcement-button'}" ToolTip="{Loc 'comms-console-menu-announcement-button-tooltip'}" StyleClasses="OpenLeft" Access="Public" />
<Button Name="BroadcastButton" Text="{Loc 'comms-console-menu-broadcast-button'}" ToolTip="{Loc 'comms-console-menu-broadcast-button-tooltip'}" StyleClasses="OpenLeft" Access="Public" />
MinSize="400 300">
<OptionButton Name="AlertLevelButton" ToolTip="{Loc 'comms-console-menu-alert-level-button-tooltip'}" StyleClasses="OpenRight" Access="Public" />
<!-- Main Container -->
<BoxContainer Orientation="Vertical"
HorizontalExpand="False"
VerticalExpand="True"
Margin="6 6 6 5">
<Control MinSize="10 10" />
<TextEdit Name="MessageInput"
VerticalExpand="True"
HorizontalExpand="True"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
MinHeight="100"/>
<RichTextLabel Name="CountdownLabel" VerticalExpand="True" />
<Button Name="EmergencyShuttleButton" Text="Placeholder Text" ToolTip="{Loc 'comms-console-menu-emergency-shuttle-button-tooltip'}" Access="Public" />
<!-- ButtonsPart -->
<BoxContainer Orientation="Vertical"
VerticalAlignment="Bottom"
SeparationOverride="4">
<!-- AnnouncePart -->
<BoxContainer Orientation="Vertical"
Margin="0 2">
<Button Name="AnnounceButton"
Access="Public"
Text="{Loc 'comms-console-menu-announcement-button'}"
ToolTip="{Loc 'comms-console-menu-announcement-button-tooltip'}"
StyleClasses="OpenLeft"
Margin="0 0 1 0"
Disabled="True"/>
<Button Name="BroadcastButton"
Access="Public"
Text="{Loc 'comms-console-menu-broadcast-button'}"
ToolTip="{Loc 'comms-console-menu-broadcast-button-tooltip'}"
StyleClasses="OpenBoth"/>
<OptionButton Name="AlertLevelButton"
Access="Public"
ToolTip="{Loc 'comms-console-menu-alert-level-button-tooltip'}"
StyleClasses="OpenRight"/>
</BoxContainer>
<!-- EmergencyPart -->
<BoxContainer Orientation="Vertical"
SeparationOverride="6">
<RichTextLabel Name="CountdownLabel"/>
<Button Name="EmergencyShuttleButton"
Access="Public"
Text="Placeholder Text"
ToolTip="{Loc 'comms-console-menu-emergency-shuttle-button-tooltip'}"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,95 @@
using Content.Shared.Electrocution;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Player;
namespace Content.Client.Electrocution;
/// <summary>
/// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent.
/// </summary>
public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<ElectrocutionHUDVisualsComponent>
{
[Dependency] private readonly IPlayerManager _playerMan = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
}
private void OnPlayerAttached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerAttachedEvent args)
{
ShowHUD();
}
private void OnPlayerDetached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerDetachedEvent args)
{
RemoveHUD();
}
private void OnInit(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentInit args)
{
if (_playerMan.LocalEntity == ent)
{
ShowHUD();
}
}
private void OnShutdown(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentShutdown args)
{
if (_playerMan.LocalEntity == ent)
{
RemoveHUD();
}
}
// Show the HUD to the client.
// We have to look for all current entities that can be electrified and toggle the HUD layer on if they are.
private void ShowHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
{
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp))
continue;
if (electrified)
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}
// Remove the HUD from the client.
// Find all current entities that can be electrified and hide the HUD layer.
private void RemoveHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
{
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}
// Toggle the HUD layer if an entity becomes (de-)electrified
protected override void OnAppearanceChange(EntityUid uid, ElectrocutionHUDVisualsComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component))
return;
var player = _playerMan.LocalEntity;
if (electrified && HasComp<ShowElectrocutionHUDComponent>(player))
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}

View File

@@ -12,6 +12,7 @@ using Content.Client.IoC;
using Content.Client.Launcher;
using Content.Client.Lobby;
using Content.Client.MainMenu;
using Content.Client.Overlays;
using Content.Client.Parallax.Managers;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Radiation.Overlays;
@@ -159,6 +160,7 @@ namespace Content.Client.Entry
_parallaxManager.LoadDefaultParallax();
_overlayManager.AddOverlay(new CP14BasePostProcessOverlay()); // CP14-PostProcess
_overlayManager.AddOverlay(new SingularityOverlay());
_overlayManager.AddOverlay(new RadiationPulseOverlay());
_chatManager.Initialize();

View File

@@ -55,7 +55,7 @@ namespace Content.Client.Eui
/// </summary>
protected void SendMessage(EuiMessageBase msg)
{
var netMsg = _netManager.CreateNetMessage<MsgEuiMessage>();
var netMsg = new MsgEuiMessage();
netMsg.Id = Id;
netMsg.Message = msg;

View File

@@ -0,0 +1,8 @@
using Content.Shared.Explosion.EntitySystems;
namespace Content.Client.Explosion;
public sealed class ScatteringGrenadeSystem : SharedScatteringGrenadeSystem
{
}

View File

@@ -112,7 +112,12 @@ namespace Content.Client.Ghost
_actions.RemoveAction(uid, component.ToggleLightingActionEntity);
_actions.RemoveAction(uid, component.ToggleFoVActionEntity);
_actions.RemoveAction(uid, component.ToggleGhostsActionEntity);
_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity);
//_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity); //Dont need in CP14
//CP14
_actions.RemoveAction(uid, component.CP14ZLevelUpActionEntity);
_actions.RemoveAction(uid, component.CP14ZLevelDownActionEntity);
_actions.RemoveAction(uid, component.CP14ToggleRoofActionEntity);
//CP14 end
if (uid != _playerManager.LocalEntity)
return;

View File

@@ -0,0 +1,101 @@
using Content.Shared.Holopad;
using Content.Shared.Silicons.StationAi;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Shared.Player;
using System.Numerics;
namespace Content.Client.Holopad;
public sealed class HolopadBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;
[Dependency] private readonly IClyde _displayManager = default!;
[ViewVariables]
private HolopadWindow? _window;
public HolopadBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
IoCManager.InjectDependencies(this);
}
protected override void Open()
{
base.Open();
_window = this.CreateWindow<HolopadWindow>();
_window.Title = Loc.GetString("holopad-window-title", ("title", EntMan.GetComponent<MetaDataComponent>(Owner).EntityName));
if (this.UiKey is not HolopadUiKey)
{
Close();
return;
}
var uiKey = (HolopadUiKey)this.UiKey;
// AIs will see a different holopad interface to crew when interacting with them in the world
if (uiKey == HolopadUiKey.InteractionWindow && EntMan.HasComponent<StationAiHeldComponent>(_playerManager.LocalEntity))
uiKey = HolopadUiKey.InteractionWindowForAi;
_window.SetState(Owner, uiKey);
_window.UpdateState(new Dictionary<NetEntity, string>());
// Set message actions
_window.SendHolopadStartNewCallMessageAction += SendHolopadStartNewCallMessage;
_window.SendHolopadAnswerCallMessageAction += SendHolopadAnswerCallMessage;
_window.SendHolopadEndCallMessageAction += SendHolopadEndCallMessage;
_window.SendHolopadStartBroadcastMessageAction += SendHolopadStartBroadcastMessage;
_window.SendHolopadActivateProjectorMessageAction += SendHolopadActivateProjectorMessage;
_window.SendHolopadRequestStationAiMessageAction += SendHolopadRequestStationAiMessage;
// If this call is addressed to an AI, open the window in the bottom right hand corner of the screen
if (uiKey == HolopadUiKey.AiRequestWindow)
_window.OpenCenteredAt(new Vector2(1f, 1f));
// Otherwise offset to the left so the holopad can still be seen
else
_window.OpenCenteredAt(new Vector2(0.3333f, 0.50f));
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
var castState = (HolopadBoundInterfaceState)state;
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
_window?.UpdateState(castState.Holopads);
}
public void SendHolopadStartNewCallMessage(NetEntity receiver)
{
SendMessage(new HolopadStartNewCallMessage(receiver));
}
public void SendHolopadAnswerCallMessage()
{
SendMessage(new HolopadAnswerCallMessage());
}
public void SendHolopadEndCallMessage()
{
SendMessage(new HolopadEndCallMessage());
}
public void SendHolopadStartBroadcastMessage()
{
SendMessage(new HolopadStartBroadcastMessage());
}
public void SendHolopadActivateProjectorMessage()
{
SendMessage(new HolopadActivateProjectorMessage());
}
public void SendHolopadRequestStationAiMessage()
{
SendMessage(new HolopadStationAiRequestMessage());
}
}

View File

@@ -0,0 +1,172 @@
using Content.Shared.Chat.TypingIndicator;
using Content.Shared.Holopad;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using System.Linq;
namespace Content.Client.Holopad;
public sealed class HolopadSystem : SharedHolopadSystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HolopadHologramComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<HolopadHologramComponent, BeforePostShaderRenderEvent>(OnShaderRender);
SubscribeAllEvent<TypingChangedEvent>(OnTypingChanged);
SubscribeNetworkEvent<PlayerSpriteStateRequest>(OnPlayerSpriteStateRequest);
SubscribeNetworkEvent<PlayerSpriteStateMessage>(OnPlayerSpriteStateMessage);
}
private void OnComponentInit(EntityUid uid, HolopadHologramComponent component, ComponentInit ev)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
UpdateHologramSprite(uid);
}
private void OnShaderRender(EntityUid uid, HolopadHologramComponent component, BeforePostShaderRenderEvent ev)
{
if (ev.Sprite.PostShader == null)
return;
ev.Sprite.PostShader.SetParameter("t", (float)_timing.CurTime.TotalSeconds * component.ScrollRate);
}
private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args)
{
var uid = args.SenderSession.AttachedEntity;
if (!Exists(uid))
return;
if (!HasComp<HolopadUserComponent>(uid))
return;
var netEv = new HolopadUserTypingChangedEvent(GetNetEntity(uid.Value), ev.IsTyping);
RaiseNetworkEvent(netEv);
}
private void OnPlayerSpriteStateRequest(PlayerSpriteStateRequest ev)
{
var targetPlayer = GetEntity(ev.TargetPlayer);
var player = _playerManager.LocalSession?.AttachedEntity;
// Ignore the request if received by a player who isn't the target
if (targetPlayer != player)
return;
if (!TryComp<SpriteComponent>(player, out var playerSprite))
return;
var spriteLayerData = new List<PrototypeLayerData>();
if (playerSprite.Visible)
{
// Record the RSI paths, state names and shader paramaters of all visible layers
for (int i = 0; i < playerSprite.AllLayers.Count(); i++)
{
if (!playerSprite.TryGetLayer(i, out var layer))
continue;
if (!layer.Visible ||
string.IsNullOrEmpty(layer.ActualRsi?.Path.ToString()) ||
string.IsNullOrEmpty(layer.State.Name))
continue;
var layerDatum = new PrototypeLayerData();
layerDatum.RsiPath = layer.ActualRsi.Path.ToString();
layerDatum.State = layer.State.Name;
if (layer.CopyToShaderParameters != null)
{
var key = (string)layer.CopyToShaderParameters.LayerKey;
if (playerSprite.LayerMapTryGet(key, out var otherLayerIdx) &&
playerSprite.TryGetLayer(otherLayerIdx, out var otherLayer) &&
otherLayer.Visible)
{
layerDatum.MapKeys = new() { key };
layerDatum.CopyToShaderParameters = new PrototypeCopyToShaderParameters()
{
LayerKey = key,
ParameterTexture = layer.CopyToShaderParameters.ParameterTexture,
ParameterUV = layer.CopyToShaderParameters.ParameterUV
};
}
}
spriteLayerData.Add(layerDatum);
}
}
// Return the recorded data to the server
var evResponse = new PlayerSpriteStateMessage(ev.TargetPlayer, spriteLayerData.ToArray());
RaiseNetworkEvent(evResponse);
}
private void OnPlayerSpriteStateMessage(PlayerSpriteStateMessage ev)
{
UpdateHologramSprite(GetEntity(ev.SpriteEntity), ev.SpriteLayerData);
}
private void UpdateHologramSprite(EntityUid uid, PrototypeLayerData[]? layerData = null)
{
if (!TryComp<SpriteComponent>(uid, out var hologramSprite))
return;
if (!TryComp<HolopadHologramComponent>(uid, out var holopadhologram))
return;
for (int i = hologramSprite.AllLayers.Count() - 1; i >= 0; i--)
hologramSprite.RemoveLayer(i);
if (layerData == null || layerData.Length == 0)
{
layerData = new PrototypeLayerData[1];
layerData[0] = new PrototypeLayerData()
{
RsiPath = holopadhologram.RsiPath,
State = holopadhologram.RsiState
};
}
for (int i = 0; i < layerData.Length; i++)
{
var layer = layerData[i];
layer.Shader = "unshaded";
hologramSprite.AddLayer(layerData[i], i);
}
UpdateHologramShader(uid, hologramSprite, holopadhologram);
}
private void UpdateHologramShader(EntityUid uid, SpriteComponent sprite, HolopadHologramComponent holopadHologram)
{
// Find the texture height of the largest layer
float texHeight = sprite.AllLayers.Max(x => x.PixelSize.Y);
var instance = _prototypeManager.Index<ShaderPrototype>(holopadHologram.ShaderName).InstanceUnique();
instance.SetParameter("color1", new Vector3(holopadHologram.Color1.R, holopadHologram.Color1.G, holopadHologram.Color1.B));
instance.SetParameter("color2", new Vector3(holopadHologram.Color2.R, holopadHologram.Color2.G, holopadHologram.Color2.B));
instance.SetParameter("alpha", holopadHologram.Alpha);
instance.SetParameter("intensity", holopadHologram.Intensity);
instance.SetParameter("texHeight", texHeight);
instance.SetParameter("t", (float)_timing.CurTime.TotalSeconds * holopadHologram.ScrollRate);
sprite.PostShader = instance;
sprite.RaiseShaderEvent = true;
}
}

View File

@@ -0,0 +1,118 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Resizable="False"
MaxSize="400 800"
MinSize="400 150">
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<BoxContainer Name="ControlsLockOutContainer" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" ReservesSpace="False" Visible="False">
<!-- Header text -->
<controls:StripeBack>
<PanelContainer>
<RichTextLabel Name="EmergencyBroadcastText" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 10 10 10" ReservesSpace="False"/>
</PanelContainer>
</controls:StripeBack>
<Label Text="{Loc 'holopad-window-controls-locked-out'}" HorizontalAlignment="Center" Margin="10 5 10 0" ReservesSpace="False"/>
<RichTextLabel Name="LockOutIdText" HorizontalAlignment="Center" Margin="10 5 10 0" ReservesSpace="False"/>
<Label Name="LockOutCountDownText" Text="{Loc 'holopad-window-controls-unlock-countdown'}" HorizontalAlignment="Center" Margin="10 15 10 10" ReservesSpace="False"/>
</BoxContainer>
<BoxContainer Name="ControlsContainer" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" ReservesSpace="False">
<!-- Active call controls (either this or the call placement controls will be active) -->
<BoxContainer Name="ActiveCallControlsContainer" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" ReservesSpace="False">
<!-- Header text -->
<BoxContainer MinHeight="60" Orientation="Vertical" VerticalAlignment="Center">
<Label Name="CallStatusText" Margin="10 5 10 0" ReservesSpace="False"/>
<BoxContainer Name="CallerIdContainer" Orientation="Vertical" ReservesSpace="False">
<RichTextLabel Name="CallerIdText" HorizontalAlignment="Center" Margin="0 0 0 0"/>
<Label Text="{Loc 'holopad-window-relay-label'}" Margin="10 5 10 0" ReservesSpace="False"/>
<RichTextLabel Name="HolopadIdText" HorizontalAlignment="Center" Margin="0 0 0 10"/>
</BoxContainer>
</BoxContainer>
<!-- Controls (the answer call button is absent when the phone is not ringing) -->
<GridContainer Columns="2" ReservesSpace="False">
<Control HorizontalExpand="True" Margin="10 0 2 5">
<Button Name="AnswerCallButton" Text="{Loc 'holopad-window-answer-call'}" StyleClasses="OpenRight" Margin="0 0 0 5" Disabled="True"/>
</Control>
<Control HorizontalExpand="True" Margin="2 0 10 5">
<Button Name="EndCallButton" Text="{Loc 'holopad-window-end-call'}" StyleClasses="OpenLeft" Margin="0 0 0 5" Disabled="True"/>
</Control>
</GridContainer>
</BoxContainer>
<!-- Call placement controls (either this or the active call controls will be active) -->
<BoxContainer Name="CallPlacementControlsContainer" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" ReservesSpace="False">
<controls:StripeBack>
<PanelContainer>
<BoxContainer Orientation="Vertical">
<RichTextLabel Name="SubtitleText" HorizontalAlignment="Center" Margin="0 5 0 0"/>
<RichTextLabel Name="OptionsText" HorizontalAlignment="Center" Margin="0 0 0 5"/>
</BoxContainer>
</PanelContainer>
</controls:StripeBack>
<!-- Request the station AI or activate the holopad projector (only one of these should be active at a time) -->
<BoxContainer Name="RequestStationAiContainer" Orientation="Vertical" ReservesSpace="False" Visible="False">
<Button Name="RequestStationAiButton" Text="{Loc 'holopad-window-request-station-ai'}" Margin="10 5 10 5" Disabled="False"/>
</BoxContainer>
<BoxContainer Name="ActivateProjectorContainer" Orientation="Vertical" ReservesSpace="False" Visible="False">
<Button Name="ActivateProjectorButton" Text="{Loc 'holopad-window-activate-projector'}" Margin="10 5 10 5" Disabled="False"/>
</BoxContainer>
<!-- List of contactable holopads (the list is created in C#) -->
<BoxContainer Name="HolopadContactListContainer" Orientation="Vertical" Margin="10 0 10 5" ReservesSpace="False" Visible="False">
<PanelContainer Name="HolopadContactListHeaderPanel">
<Label Text="{Loc 'holopad-window-select-contact-from-list'}" HorizontalAlignment="Center" Margin="0 3 0 3"/>
</PanelContainer>
<PanelContainer Name="HolopadContactListPanel">
<BoxContainer Orientation="Vertical">
<!-- Contact filter -->
<LineEdit Name="SearchLineEdit" HorizontalExpand="True" Margin="4, 4, 4, 0"
PlaceHolder="{Loc holopad-window-filter-line-placeholder}" />
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" Margin="8, 8, 8, 8" MinHeight="256">
<!-- If there is no data yet, this will be displayed -->
<BoxContainer Name="FetchingAvailableHolopadsContainer" HorizontalAlignment="Center" HorizontalExpand="True" VerticalExpand="True" ReservesSpace="False">
<Label Text="{Loc 'holopad-window-fetching-contacts-list'}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</BoxContainer>
<!-- Container for the contacts -->
<BoxContainer Name="ContactsList" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" Margin="10 0 10 0"/>
</ScrollContainer>
</BoxContainer>
</PanelContainer>
</BoxContainer>
<!-- Button to start an emergency broadcast (the user requires a certain level of access to interact with it) -->
<BoxContainer Name="StartBroadcastContainer" Orientation="Vertical" ReservesSpace="False" Visible="False">
<Button Name="StartBroadcastButton" Text="{Loc 'holopad-window-emergency-broadcast'}" Margin="10 0 10 5" Disabled="False" ReservesSpace="False"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
<!-- Footer -->
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'holopad-window-flavor-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'holopad-window-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,344 @@
using Content.Client.Popups;
using Content.Client.UserInterface.Controls;
using Content.Shared.Access.Systems;
using Content.Shared.Holopad;
using Content.Shared.Telephone;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using System.Linq;
namespace Content.Client.Holopad;
[GenerateTypedNameReferences]
public sealed partial class HolopadWindow : FancyWindow
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly SharedHolopadSystem _holopadSystem = default!;
private readonly SharedTelephoneSystem _telephoneSystem = default!;
private readonly AccessReaderSystem _accessReaderSystem = default!;
private readonly PopupSystem _popupSystem = default!;
private EntityUid? _owner = null;
private HolopadUiKey _currentUiKey;
private TelephoneState _currentState;
private TelephoneState _previousState;
private TimeSpan _buttonUnlockTime;
private float _updateTimer = 0.25f;
private const float UpdateTime = 0.25f;
private TimeSpan _buttonUnlockDelay = TimeSpan.FromSeconds(0.5f);
public event Action<NetEntity>? SendHolopadStartNewCallMessageAction;
public event Action? SendHolopadAnswerCallMessageAction;
public event Action? SendHolopadEndCallMessageAction;
public event Action? SendHolopadStartBroadcastMessageAction;
public event Action? SendHolopadActivateProjectorMessageAction;
public event Action? SendHolopadRequestStationAiMessageAction;
public HolopadWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_holopadSystem = _entManager.System<SharedHolopadSystem>();
_telephoneSystem = _entManager.System<SharedTelephoneSystem>();
_accessReaderSystem = _entManager.System<AccessReaderSystem>();
_popupSystem = _entManager.System<PopupSystem>();
_buttonUnlockTime = _timing.CurTime + _buttonUnlockDelay;
// Assign button actions
AnswerCallButton.OnPressed += args => { OnHolopadAnswerCallMessage(); };
EndCallButton.OnPressed += args => { OnHolopadEndCallMessage(); };
StartBroadcastButton.OnPressed += args => { OnHolopadStartBroadcastMessage(); };
ActivateProjectorButton.OnPressed += args => { OnHolopadActivateProjectorMessage(); };
RequestStationAiButton.OnPressed += args => { OnHolopadRequestStationAiMessage(); };
// XML formatting
AnswerCallButton.AddStyleClass("ButtonAccept");
EndCallButton.AddStyleClass("Caution");
StartBroadcastButton.AddStyleClass("Caution");
HolopadContactListPanel.PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(47, 47, 59) * Color.DarkGray,
BorderColor = new Color(82, 82, 82), //new Color(70, 73, 102),
BorderThickness = new Thickness(2),
};
HolopadContactListHeaderPanel.PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(82, 82, 82),
};
EmergencyBroadcastText.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("holopad-window-emergency-broadcast-in-progress")));
SubtitleText.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("holopad-window-subtitle")));
OptionsText.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("holopad-window-options")));
}
#region: Button actions
private void OnSendHolopadStartNewCallMessage(NetEntity receiver)
{
SendHolopadStartNewCallMessageAction?.Invoke(receiver);
}
private void OnHolopadAnswerCallMessage()
{
SendHolopadAnswerCallMessageAction?.Invoke();
}
private void OnHolopadEndCallMessage()
{
SendHolopadEndCallMessageAction?.Invoke();
if (_currentUiKey == HolopadUiKey.AiRequestWindow)
Close();
}
private void OnHolopadStartBroadcastMessage()
{
if (_playerManager.LocalSession?.AttachedEntity == null || _owner == null)
return;
var player = _playerManager.LocalSession.AttachedEntity;
if (!_accessReaderSystem.IsAllowed(player.Value, _owner.Value))
{
_popupSystem.PopupClient(Loc.GetString("holopad-window-access-denied"), _owner.Value, player.Value);
return;
}
SendHolopadStartBroadcastMessageAction?.Invoke();
}
private void OnHolopadActivateProjectorMessage()
{
SendHolopadActivateProjectorMessageAction?.Invoke();
}
private void OnHolopadRequestStationAiMessage()
{
SendHolopadRequestStationAiMessageAction?.Invoke();
}
#endregion
public void SetState(EntityUid owner, HolopadUiKey uiKey)
{
_owner = owner;
_currentUiKey = uiKey;
// Determines what UI containers are available to the user.
// Components of these will be toggled on and off when
// UpdateAppearance() is called
switch (uiKey)
{
case HolopadUiKey.InteractionWindow:
RequestStationAiContainer.Visible = true;
HolopadContactListContainer.Visible = true;
StartBroadcastContainer.Visible = true;
break;
case HolopadUiKey.InteractionWindowForAi:
ActivateProjectorContainer.Visible = true;
StartBroadcastContainer.Visible = true;
break;
case HolopadUiKey.AiActionWindow:
HolopadContactListContainer.Visible = true;
StartBroadcastContainer.Visible = true;
break;
case HolopadUiKey.AiRequestWindow:
break;
}
}
public void UpdateState(Dictionary<NetEntity, string> holopads)
{
if (_owner == null || !_entManager.TryGetComponent<TelephoneComponent>(_owner.Value, out var telephone))
return;
// Caller ID text
var callerId = _telephoneSystem.GetFormattedCallerIdForEntity(telephone.LastCallerId.Item1, telephone.LastCallerId.Item2, Color.LightGray, "Default", 11);
var holoapdId = _telephoneSystem.GetFormattedDeviceIdForEntity(telephone.LastCallerId.Item3, Color.LightGray, "Default", 11);
CallerIdText.SetMessage(FormattedMessage.FromMarkupOrThrow(callerId));
HolopadIdText.SetMessage(FormattedMessage.FromMarkupOrThrow(holoapdId));
LockOutIdText.SetMessage(FormattedMessage.FromMarkupOrThrow(callerId));
// Sort holopads alphabetically
var holopadArray = holopads.ToArray();
Array.Sort(holopadArray, AlphabeticalSort);
// Clear excess children from the contact list
while (ContactsList.ChildCount > holopadArray.Length)
ContactsList.RemoveChild(ContactsList.GetChild(ContactsList.ChildCount - 1));
// Make / update required children
for (int i = 0; i < holopadArray.Length; i++)
{
var (netEntity, label) = holopadArray[i];
if (i >= ContactsList.ChildCount)
{
var newContactButton = new HolopadContactButton();
newContactButton.OnPressed += args => { OnSendHolopadStartNewCallMessage(newContactButton.NetEntity); };
ContactsList.AddChild(newContactButton);
}
var child = ContactsList.GetChild(i);
if (child is not HolopadContactButton)
continue;
var contactButton = (HolopadContactButton)child;
contactButton.UpdateValues(netEntity, label);
}
// Update buttons
UpdateAppearance();
}
private void UpdateAppearance()
{
if (_owner == null || !_entManager.TryGetComponent<TelephoneComponent>(_owner.Value, out var telephone))
return;
if (_owner == null || !_entManager.TryGetComponent<HolopadComponent>(_owner.Value, out var holopad))
return;
var hasBroadcastAccess = !_holopadSystem.IsHolopadBroadcastOnCoolDown((_owner.Value, holopad));
var localPlayer = _playerManager.LocalSession?.AttachedEntity;
ControlsLockOutContainer.Visible = _holopadSystem.IsHolopadControlLocked((_owner.Value, holopad), localPlayer);
ControlsContainer.Visible = !ControlsLockOutContainer.Visible;
// Temporarily disable the interface buttons when the call state changes to prevent any misclicks
if (_currentState != telephone.CurrentState)
{
_previousState = _currentState;
_currentState = telephone.CurrentState;
_buttonUnlockTime = _timing.CurTime + _buttonUnlockDelay;
}
var lockButtons = _timing.CurTime < _buttonUnlockTime;
// Make / update required children
foreach (var child in ContactsList.Children)
{
if (child is not HolopadContactButton contactButton)
continue;
var passesFilter = string.IsNullOrEmpty(SearchLineEdit.Text) ||
contactButton.Text?.Contains(SearchLineEdit.Text, StringComparison.CurrentCultureIgnoreCase) == true;
contactButton.Visible = passesFilter;
contactButton.Disabled = (_currentState != TelephoneState.Idle || lockButtons);
}
// Update control text
var cooldown = _holopadSystem.GetHolopadBroadcastCoolDown((_owner.Value, holopad));
var cooldownString = $"{cooldown.Minutes:00}:{cooldown.Seconds:00}";
StartBroadcastButton.Text = _holopadSystem.IsHolopadBroadcastOnCoolDown((_owner.Value, holopad)) ?
Loc.GetString("holopad-window-emergency-broadcast-with-countdown", ("countdown", cooldownString)) :
Loc.GetString("holopad-window-emergency-broadcast");
var lockout = _holopadSystem.GetHolopadControlLockedPeriod((_owner.Value, holopad));
var lockoutString = $"{lockout.Minutes:00}:{lockout.Seconds:00}";
LockOutCountDownText.Text = Loc.GetString("holopad-window-controls-unlock-countdown", ("countdown", lockoutString));
switch (_currentState)
{
case TelephoneState.Idle:
CallStatusText.Text = Loc.GetString("holopad-window-no-calls-in-progress"); break;
case TelephoneState.Calling:
CallStatusText.Text = Loc.GetString("holopad-window-outgoing-call"); break;
case TelephoneState.Ringing:
CallStatusText.Text = (_currentUiKey == HolopadUiKey.AiRequestWindow) ?
Loc.GetString("holopad-window-ai-request") : Loc.GetString("holopad-window-incoming-call"); break;
case TelephoneState.InCall:
CallStatusText.Text = Loc.GetString("holopad-window-call-in-progress"); break;
case TelephoneState.EndingCall:
if (_previousState == TelephoneState.Calling || _previousState == TelephoneState.Idle)
CallStatusText.Text = Loc.GetString("holopad-window-call-rejected");
else
CallStatusText.Text = Loc.GetString("holopad-window-call-ending");
break;
}
// Update control disability
AnswerCallButton.Disabled = (_currentState != TelephoneState.Ringing || lockButtons);
EndCallButton.Disabled = (_currentState == TelephoneState.Idle || _currentState == TelephoneState.EndingCall || lockButtons);
StartBroadcastButton.Disabled = (_currentState != TelephoneState.Idle || !hasBroadcastAccess || lockButtons);
RequestStationAiButton.Disabled = (_currentState != TelephoneState.Idle || lockButtons);
ActivateProjectorButton.Disabled = (_currentState != TelephoneState.Idle || lockButtons);
// Update control visibility
FetchingAvailableHolopadsContainer.Visible = (ContactsList.ChildCount == 0);
ActiveCallControlsContainer.Visible = (_currentState != TelephoneState.Idle || _currentUiKey == HolopadUiKey.AiRequestWindow);
CallPlacementControlsContainer.Visible = !ActiveCallControlsContainer.Visible;
CallerIdContainer.Visible = (_currentState == TelephoneState.Ringing);
AnswerCallButton.Visible = (_currentState == TelephoneState.Ringing);
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
_updateTimer += args.DeltaSeconds;
if (_updateTimer >= UpdateTime)
{
_updateTimer -= UpdateTime;
UpdateAppearance();
}
}
private sealed class HolopadContactButton : Button
{
public NetEntity NetEntity;
public HolopadContactButton()
{
HorizontalExpand = true;
SetHeight = 32;
Margin = new Thickness(0f, 1f, 0f, 1f);
ReservesSpace = false;
}
public void UpdateValues(NetEntity netEntity, string label)
{
NetEntity = netEntity;
Text = Loc.GetString("holopad-window-contact-label", ("label", label));
}
}
private int AlphabeticalSort(KeyValuePair<NetEntity, string> x, KeyValuePair<NetEntity, string> y)
{
if (string.IsNullOrEmpty(x.Value))
return -1;
if (string.IsNullOrEmpty(y.Value))
return 1;
return x.Value.CompareTo(y.Value);
}
}

View File

@@ -191,9 +191,15 @@ namespace Content.Client.Inventory
return;
if (ev.Function == ContentKeyFunctions.ExamineEntity)
{
_examine.DoExamine(slot.Entity.Value);
ev.Handle();
}
else if (ev.Function == EngineKeyFunctions.UseSecondary)
{
_ui.GetUIController<VerbMenuUIController>().OpenVerbMenu(slot.Entity.Value);
ev.Handle();
}
}
private void AddInventoryButton(EntityUid invUid, string slotId, InventoryComponent inv)

View File

@@ -21,6 +21,22 @@ public sealed class HandheldLightSystem : SharedHandheldLightSystem
SubscribeLocalEvent<HandheldLightComponent, AppearanceChangeEvent>(OnAppearanceChange);
}
/// <remarks>
/// TODO: Not properly predicted yet. Don't call this function if you want a the actual return value!
/// </remarks>
public override bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
{
return true;
}
/// <remarks>
/// TODO: Not properly predicted yet. Don't call this function if you want a the actual return value!
/// </remarks>
public override bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
{
return true;
}
private void OnAppearanceChange(EntityUid uid, HandheldLightComponent? component, ref AppearanceChangeEvent args)
{
if (!Resolve(uid, ref component))

View File

@@ -116,7 +116,7 @@ namespace Content.Client.Lobby
return;
}
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
string text;
if (_gameTicker.Paused)
@@ -136,6 +136,10 @@ namespace Content.Client.Lobby
{
text = Loc.GetString(seconds < -5 ? "lobby-state-right-now-question" : "lobby-state-right-now-confirmation");
}
else if (difference.TotalHours >= 1)
{
text = $"{Math.Floor(difference.TotalHours)}:{difference.Minutes:D2}:{difference.Seconds:D2}";
}
else
{
text = $"{difference.Minutes}:{difference.Seconds:D2}";

View File

@@ -455,7 +455,21 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
{
EntityUid dummyEnt;
if (humanoid is not null)
EntProtoId? previewEntity = null;
if (humanoid != null && jobClothes)
{
job ??= GetPreferredJob(humanoid);
previewEntity = job.JobPreviewEntity ?? (EntProtoId?)job?.JobEntity;
}
if (previewEntity != null)
{
// Special type like borg or AI, do not spawn a human just spawn the entity.
dummyEnt = EntityManager.SpawnEntity(previewEntity, MapCoordinates.Nullspace);
return dummyEnt;
}
else if (humanoid is not null)
{
var dummy = _prototypeManager.Index<SpeciesPrototype>(humanoid.Species).DollPrototype;
dummyEnt = EntityManager.SpawnEntity(dummy, MapCoordinates.Nullspace);
@@ -469,7 +483,8 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
if (humanoid != null && jobClothes)
{
job ??= GetPreferredJob(humanoid);
DebugTools.Assert(job != null);
GiveDummyJobClothes(dummyEnt, humanoid, job);
if (_prototypeManager.HasIndex<RoleLoadoutPrototype>(LoadoutSystem.GetJobPrototype(job.ID)))

View File

@@ -6,6 +6,7 @@
SeparationOverride="0"
Name="InternalHBox">
<SpriteView Scale="2 2"
Margin="0 4 4 4"
OverrideDirection="South"
Name="View"/>
<Label Name="DescriptionLabel"

View File

@@ -140,7 +140,7 @@
</BoxContainer>
<!-- Right side -->
<BoxContainer Orientation="Vertical" VerticalExpand="True" VerticalAlignment="Center">
<SpriteView Name="SpriteView" Scale="8 8" SizeFlagsStretchRatio="1" />
<SpriteView Name="SpriteView" Scale="8 8" Margin="4" SizeFlagsStretchRatio="1" />
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 5">
<Button Name="SpriteRotateLeft" Text="◀" StyleClasses="OpenRight" />
<cc:VSeparator Margin="2 0 3 0" />

View File

@@ -0,0 +1,46 @@
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Timing;
namespace Content.Client.Movement.Systems;
/// <summary>
/// Controls the switching of motion and standing still animation
/// </summary>
public sealed class ClientSpriteMovementSystem : SharedSpriteMovementSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
private EntityQuery<SpriteComponent> _spriteQuery;
public override void Initialize()
{
base.Initialize();
_spriteQuery = GetEntityQuery<SpriteComponent>();
SubscribeLocalEvent<SpriteMovementComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
}
private void OnAfterAutoHandleState(Entity<SpriteMovementComponent> ent, ref AfterAutoHandleStateEvent args)
{
if (!_spriteQuery.TryGetComponent(ent, out var sprite))
return;
if (ent.Comp.IsMoving)
{
foreach (var (layer, state) in ent.Comp.MovementLayers)
{
sprite.LayerSetData(layer, state);
}
}
else
{
foreach (var (layer, state) in ent.Comp.NoMovementLayers)
{
sprite.LayerSetData(layer, state);
}
}
}
}

View File

@@ -1,51 +0,0 @@
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
using Content.Shared.Movement.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Timing;
namespace Content.Client.Movement.Systems;
/// <summary>
/// Handles setting sprite states based on whether an entity has movement input.
/// </summary>
public sealed class SpriteMovementSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
private EntityQuery<SpriteComponent> _spriteQuery;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SpriteMovementComponent, MoveInputEvent>(OnSpriteMoveInput);
_spriteQuery = GetEntityQuery<SpriteComponent>();
}
private void OnSpriteMoveInput(EntityUid uid, SpriteMovementComponent component, ref MoveInputEvent args)
{
if (!_timing.IsFirstTimePredicted)
return;
var oldMoving = (SharedMoverController.GetNormalizedMovement(args.OldMovement) & MoveButtons.AnyDirection) != MoveButtons.None;
var moving = (SharedMoverController.GetNormalizedMovement(args.Entity.Comp.HeldMoveButtons) & MoveButtons.AnyDirection) != MoveButtons.None;
if (oldMoving == moving || !_spriteQuery.TryGetComponent(uid, out var sprite))
return;
if (moving)
{
foreach (var (layer, state) in component.MovementLayers)
{
sprite.LayerSetData(layer, state);
}
}
else
{
foreach (var (layer, state) in component.NoMovementLayers)
{
sprite.LayerSetData(layer, state);
}
}
}
}

View File

@@ -35,7 +35,7 @@ public sealed partial class StencilOverlay
var matty = Matrix3x2.Multiply(matrix, invMatrix);
worldHandle.SetTransform(matty);
foreach (var tile in grid.Comp.GetTilesIntersecting(worldAABB))
foreach (var tile in _map.GetTilesIntersecting(grid.Owner, grid, worldAABB))
{
// Ignored tiles for stencil
if (_weather.CanWeatherAffect(grid.Owner, grid, tile))

View File

@@ -26,6 +26,7 @@ public sealed partial class StencilOverlay : Overlay
[Dependency] private readonly IPrototypeManager _protoManager = default!;
private readonly ParallaxSystem _parallax;
private readonly SharedTransformSystem _transform;
private readonly SharedMapSystem _map;
private readonly SpriteSystem _sprite;
private readonly WeatherSystem _weather;
@@ -35,11 +36,12 @@ public sealed partial class StencilOverlay : Overlay
private readonly ShaderInstance _shader;
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SpriteSystem sprite, WeatherSystem weather)
public StencilOverlay(ParallaxSystem parallax, SharedTransformSystem transform, SharedMapSystem map, SpriteSystem sprite, WeatherSystem weather)
{
ZIndex = ParallaxSystem.ParallaxZIndex + 1;
_parallax = parallax;
_transform = transform;
_map = map;
_sprite = sprite;
_weather = weather;
IoCManager.InjectDependencies(this);

View File

@@ -10,13 +10,14 @@ public sealed class StencilOverlaySystem : EntitySystem
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly ParallaxSystem _parallax = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly WeatherSystem _weather = default!;
public override void Initialize()
{
base.Initialize();
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _sprite, _weather));
_overlay.AddOverlay(new StencilOverlay(_parallax, _transform, _map, _sprite, _weather));
}
public override void Shutdown()

View File

@@ -9,6 +9,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Utility;
using Robust.Client.UserInterface.RichText;
using Content.Client.UserInterface.RichText;
using Robust.Shared.Input;
namespace Content.Client.Paper.UI
@@ -43,7 +44,8 @@ namespace Content.Client.Paper.UI
typeof(BulletTag),
typeof(ColorTag),
typeof(HeadingTag),
typeof(ItalicTag)
typeof(ItalicTag),
typeof(MonoTag)
};
public event Action<string>? OnSaved;

View File

@@ -385,26 +385,6 @@ public partial class NavMapControl : MapGridControl
if (PostWallDrawingAction != null)
PostWallDrawingAction.Invoke(handle);
// Beacons
if (_beacons.Pressed)
{
var rectBuffer = new Vector2(5f, 3f);
// Calculate font size for current zoom level
var fontSize = (int) Math.Round(1 / WorldRange * DefaultDisplayedRange * UIScale * _targetFontsize, 0);
var font = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Bold.ttf"), fontSize);
foreach (var beacon in _navMap.Beacons.Values)
{
var position = beacon.Position - offset;
position = ScalePosition(position with { Y = -position.Y });
var textDimensions = handle.GetDimensions(font, beacon.Text, 1f);
handle.DrawRect(new UIBox2(position - textDimensions / 2 - rectBuffer, position + textDimensions / 2 + rectBuffer), BackgroundColor);
handle.DrawString(font, position - textDimensions / 2, beacon.Text, beacon.Color);
}
}
var curTime = Timing.RealTime;
var blinkFrequency = 1f / 1f;
var lit = curTime.TotalSeconds % blinkFrequency > blinkFrequency / 2f;
@@ -443,11 +423,31 @@ public partial class NavMapControl : MapGridControl
position = ScalePosition(new Vector2(position.X, -position.Y));
var scalingCoefficient = MinmapScaleModifier * float.Sqrt(MinimapScale);
var positionOffset = new Vector2(scalingCoefficient * blip.Texture.Width, scalingCoefficient * blip.Texture.Height);
var positionOffset = new Vector2(scalingCoefficient * blip.Scale * blip.Texture.Width, scalingCoefficient * blip.Scale * blip.Texture.Height);
handle.DrawTextureRect(blip.Texture, new UIBox2(position - positionOffset, position + positionOffset), blip.Color);
}
}
// Beacons
if (_beacons.Pressed)
{
var rectBuffer = new Vector2(5f, 3f);
// Calculate font size for current zoom level
var fontSize = (int)Math.Round(1 / WorldRange * DefaultDisplayedRange * UIScale * _targetFontsize, 0);
var font = new VectorFont(_cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Bold.ttf"), fontSize);
foreach (var beacon in _navMap.Beacons.Values)
{
var position = beacon.Position - offset;
position = ScalePosition(position with { Y = -position.Y });
var textDimensions = handle.GetDimensions(font, beacon.Text, 1f);
handle.DrawRect(new UIBox2(position - textDimensions / 2 - rectBuffer, position + textDimensions / 2 + rectBuffer), BackgroundColor);
handle.DrawString(font, position - textDimensions / 2, beacon.Text, beacon.Color);
}
}
}
protected override void FrameUpdate(FrameEventArgs args)
@@ -689,6 +689,9 @@ public partial class NavMapControl : MapGridControl
Vector2i foundTermius;
Vector2i foundOrigin;
if (origin == terminus)
return;
// Does our new line end at the beginning of an existing line?
if (lookup.Remove(terminus, out foundTermius))
{
@@ -739,13 +742,15 @@ public struct NavMapBlip
public Color Color;
public bool Blinks;
public bool Selectable;
public float Scale;
public NavMapBlip(EntityCoordinates coordinates, Texture texture, Color color, bool blinks, bool selectable = true)
public NavMapBlip(EntityCoordinates coordinates, Texture texture, Color color, bool blinks, bool selectable = true, float scale = 1f)
{
Coordinates = coordinates;
Texture = texture;
Color = color;
Blinks = blinks;
Selectable = selectable;
Scale = scale;
}
}

View File

@@ -6,6 +6,7 @@ using Robust.Shared.Utility;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using Vector4 = Robust.Shared.Maths.Vector4;
namespace Content.Client.Power;
@@ -104,6 +105,26 @@ public sealed partial class PowerMonitoringWindow
// Update power value
// Don't use SI prefixes, just give the number in W, so that it is readily apparent which consumer is using a lot of power.
button.PowerValue.Text = Loc.GetString("power-monitoring-window-button-value", ("value", Math.Round(entry.PowerValue).ToString("N0")));
// Update battery level if applicable
if (entry.BatteryLevel != null)
{
button.BatteryLevel.Value = entry.BatteryLevel.Value;
button.BatteryLevel.Visible = true;
button.BatteryPercentage.Text = entry.BatteryLevel.Value.ToString("P0");
button.BatteryPercentage.Visible = true;
// Set progress bar color based on percentage
var color = Color.FromHsv(new Vector4(entry.BatteryLevel.Value * 0.33f, 1, 1, 1));
button.BatteryLevel.ForegroundStyleBoxOverride = new StyleBoxFlat { BackgroundColor = color };
}
else
{
button.BatteryLevel.Visible = false;
button.BatteryPercentage.Visible = false;
}
}
private void UpdateEntrySourcesOrLoads(BoxContainer masterContainer, BoxContainer currentContainer, PowerMonitoringConsoleEntry[]? entries, SpriteSpecifier.Texture icon)
@@ -443,6 +464,11 @@ public sealed class PowerMonitoringButton : Button
public BoxContainer MainContainer;
public TextureRect TextureRect;
public Label NameLocalized;
public ProgressBar BatteryLevel;
public PanelContainer BackgroundPanel;
public Label BatteryPercentage;
public Label PowerValue;
public PowerMonitoringButton()
@@ -478,6 +504,49 @@ public sealed class PowerMonitoringButton : Button
MainContainer.AddChild(NameLocalized);
BatteryLevel = new ProgressBar()
{
SetWidth = 47f,
SetHeight = 20f,
Margin = new Thickness(15, 0, 0, 0),
MaxValue = 1,
Visible = false,
BackgroundStyleBoxOverride = new StyleBoxFlat { BackgroundColor = Color.Black },
};
MainContainer.AddChild(BatteryLevel);
BackgroundPanel = new PanelContainer
{
// Draw a half-transparent box over the battery level to make the text more readable.
PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(0, 0, 0, 0.9f)
},
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
HorizontalExpand = true,
VerticalExpand = true,
// Box is undersized perfectly compared to the progress bar, so a little bit of the unaffected progress bar is visible.
SetSize = new Vector2(43f, 16f)
};
BatteryLevel.AddChild(BackgroundPanel);
BatteryPercentage = new Label()
{
VerticalAlignment = VAlignment.Center,
HorizontalAlignment = HAlignment.Center,
Align = Label.AlignMode.Center,
SetWidth = 45f,
MinWidth = 20f,
Margin = new Thickness(10, -4, 10, 0),
ClipText = true,
Visible = false,
};
BackgroundPanel.AddChild(BatteryPercentage);
PowerValue = new Label()
{
HorizontalAlignment = HAlignment.Right,

View File

@@ -110,7 +110,7 @@ namespace Content.Client.Sandbox
}
// Try copy tile.
if (!_map.TryFindGridAt(_transform.ToMapCoordinates(coords), out var gridUid, out var grid) || !_mapSystem.TryGetTileRef(gridUid, grid, coords, out var tileRef))
return false;
@@ -157,10 +157,5 @@ namespace Content.Client.Sandbox
{
_consoleHost.ExecuteCommand("physics shapes");
}
public void MachineLinking()
{
_consoleHost.ExecuteCommand("signallink");
}
}
}

View File

@@ -28,6 +28,7 @@ public sealed partial class SensorMonitoringWindow : FancyWindow, IComputerWindo
public SensorMonitoringWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
}
public void UpdateState(ConsoleUIState state)

View File

@@ -116,7 +116,7 @@ public partial class BaseShuttleControl : MapGridControl
}
}
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 matrix, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
{
var rator = Maps.GetAllTilesEnumerator(grid.Owner, grid.Comp);
var minimapScale = MinimapScale;
@@ -264,7 +264,7 @@ public partial class BaseShuttleControl : MapGridControl
Extensions.EnsureLength(ref _allVertices, totalData);
_drawJob.MidPoint = midpoint;
_drawJob.Matrix = matrix;
_drawJob.Matrix = gridToView;
_drawJob.MinimapScale = minimapScale;
_drawJob.Vertices = gridData.Vertices;
_drawJob.ScaledVertices = _allVertices;
@@ -286,7 +286,7 @@ public partial class BaseShuttleControl : MapGridControl
private record struct GridDrawJob : IParallelRobustJob
{
public int BatchSize => 16;
public int BatchSize => 64;
public float MinimapScale;
public Vector2 MidPoint;
@@ -297,12 +297,7 @@ public partial class BaseShuttleControl : MapGridControl
public void Execute(int index)
{
var vert = Vertices[index];
var adjustedVert = Vector2.Transform(vert, Matrix);
adjustedVert = adjustedVert with { Y = -adjustedVert.Y };
var scaledVert = ScalePosition(adjustedVert, MinimapScale, MidPoint);
ScaledVertices[index] = scaledVert;
ScaledVertices[index] = Vector2.Transform(Vertices[index], Matrix);
}
}
}

View File

@@ -15,6 +15,7 @@ public sealed partial class NavScreen : BoxContainer
[Dependency] private readonly IEntityManager _entManager = default!;
private SharedTransformSystem _xformSystem;
private EntityUid? _consoleEntity; // Entity of controlling console
private EntityUid? _shuttleEntity;
public NavScreen()
@@ -35,6 +36,12 @@ public sealed partial class NavScreen : BoxContainer
_shuttleEntity = shuttle;
}
public void SetConsole(EntityUid? console)
{
_consoleEntity = console;
NavRadar.SetConsole(console);
}
private void OnIFFTogglePressed(BaseButton.ButtonEventArgs args)
{
NavRadar.ShowIFF ^= true;

View File

@@ -138,6 +138,7 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow,
{
var coordinates = _entManager.GetCoordinates(cState.NavState.Coordinates);
NavContainer.SetShuttle(coordinates?.EntityId);
NavContainer.SetConsole(owner);
MapContainer.SetShuttle(coordinates?.EntityId);
MapContainer.SetConsole(owner);

View File

@@ -107,16 +107,19 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
DrawCircles(handle);
var gridNent = EntManager.GetNetEntity(GridEntity);
var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value);
var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value);
var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix);
var ourGridToWorld = _xformSystem.GetWorldMatrix(GridEntity.Value);
var selectedDockToOurGrid = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero);
var selectedDockToWorld = Matrix3x2.Multiply(selectedDockToOurGrid, ourGridToWorld);
Matrix3x2.Invert(worldFromDock, out var offsetMatrix);
Box2 viewBoundsWorld = Matrix3Helpers.TransformBox(selectedDockToWorld, new Box2(-WorldRangeVector, WorldRangeVector));
Matrix3x2.Invert(selectedDockToWorld, out var worldToSelectedDock);
var selectedDockToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
// Draw nearby grids
var controlBounds = PixelSizeBox;
_grids.Clear();
_mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(mapPos.Position - WorldRangeVector, mapPos.Position + WorldRangeVector), ref _grids);
_mapManager.FindGridsIntersecting(gridXform.MapID, viewBoundsWorld, ref _grids);
// offset the dotted-line position to the bounds.
Vector2? viewedDockPos = _viewedState != null ? MidPointVector : null;
@@ -136,11 +139,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
if (grid.Owner != GridEntity && !_shuttles.CanDraw(grid.Owner, iffComp: iffComp))
continue;
var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner);
var matty = Matrix3x2.Multiply(gridMatrix, offsetMatrix);
var curGridToWorld = _xformSystem.GetWorldMatrix(grid.Owner);
var curGridToView = curGridToWorld * worldToSelectedDock * selectedDockToView;
var color = _shuttles.GetIFFColor(grid.Owner, grid.Owner == GridEntity, component: iffComp);
DrawGrid(handle, matty, grid, color);
DrawGrid(handle, curGridToView, grid, color);
// Draw any docks on that grid
if (!DockState.Docks.TryGetValue(EntManager.GetNetEntity(grid), out var gridDocks))
@@ -151,23 +154,24 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
if (ViewedDock == dock.Entity)
continue;
var position = Vector2.Transform(dock.Coordinates.Position, matty);
var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle);
var scaledPos = ScalePosition(position with {Y = -position.Y});
if (!controlBounds.Contains(scaledPos.Floored()))
// This box is the AABB of all the vertices we draw below.
var dockRenderBoundsLocal = new Box2(-0.5f, -0.7f, 0.5f, 0.5f);
var currentDockToCurGrid = Matrix3Helpers.CreateTransform(dock.Coordinates.Position, dock.Angle);
var currentDockToWorld = Matrix3x2.Multiply(currentDockToCurGrid, curGridToWorld);
var dockRenderBoundsWorld = Matrix3Helpers.TransformBox(currentDockToWorld, dockRenderBoundsLocal);
if (!viewBoundsWorld.Intersects(dockRenderBoundsWorld))
continue;
// Draw the dock's collision
var collisionBL = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), matty);
Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), curGridToView);
var collisionBR = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), matty);
Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), curGridToView);
var collisionTR = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), matty);
Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), curGridToView);
var collisionTL = Vector2.Transform(dock.Coordinates.Position +
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), matty);
Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), curGridToView);
var verts = new[]
{
@@ -181,13 +185,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
collisionBL,
};
for (var i = 0; i < verts.Length; i++)
{
var vert = verts[i];
vert.Y = -vert.Y;
verts[i] = ScalePosition(vert);
}
var collisionCenter = verts[0] + verts[1] + verts[3] + verts[5];
var otherDockConnection = Color.ToSrgb(Color.Pink);
@@ -195,10 +192,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
handle.DrawPrimitives(DrawPrimitiveTopology.LineList, verts, otherDockConnection);
// Draw the dock itself
var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), matty);
var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), matty);
var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), matty);
var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), matty);
var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), curGridToView);
var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), curGridToView);
var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), curGridToView);
var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), curGridToView);
verts = new[]
{
@@ -212,13 +209,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
dockBL
};
for (var i = 0; i < verts.Length; i++)
{
var vert = verts[i];
vert.Y = -vert.Y;
verts[i] = ScalePosition(vert);
}
Color otherDockColor;
if (HighlightedDock == dock.Entity)
@@ -253,9 +243,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
collisionCenter /= 4;
var range = viewedDockPos.Value - collisionCenter;
if (range.Length() < SharedDockingSystem.DockingHiglightRange * MinimapScale)
var maxRange = SharedDockingSystem.DockingHiglightRange * MinimapScale;
var maxRangeSq = maxRange * maxRange;
if (range.LengthSquared() < maxRangeSq)
{
if (_viewedState?.GridDockedWith == null)
if (dock.GridDockedWith == null)
{
var coordsOne = EntManager.GetCoordinates(_viewedState!.Coordinates);
var coordsTwo = EntManager.GetCoordinates(dock.Coordinates);
@@ -265,10 +257,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
var rotA = _xformSystem.GetWorldRotation(coordsOne.EntityId) + _viewedState!.Angle;
var rotB = _xformSystem.GetWorldRotation(coordsTwo.EntityId) + dock.Angle;
var distance = (mapOne.Position - mapTwo.Position).Length();
var distanceSq = (mapOne.Position - mapTwo.Position).LengthSquared();
var inAlignment = _dockSystem.InAlignment(mapOne, rotA, mapTwo, rotB);
var canDock = distance < SharedDockingSystem.DockRange && inAlignment;
var maxDockDistSq = SharedDockingSystem.DockRange * SharedDockingSystem.DockRange;
var canDock = distanceSq < maxDockDistSq && inAlignment;
if (dockButton != null)
dockButton.Disabled = !canDock || !canDockChange;
@@ -297,7 +290,8 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl
{
// Because it's being layed out top-down we have to arrange for first frame.
container.Arrange(PixelRect);
var containerPos = scaledPos / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
var dockPositionInView = Vector2.Transform(dock.Coordinates.Position, curGridToView);
var containerPos = dockPositionInView / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale;
SetPosition(container, containerPos);
}

View File

@@ -29,6 +29,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
/// </summary>
private EntityCoordinates? _coordinates;
/// <summary>
/// Entity of controlling console
/// </summary>
private EntityUid? _consoleEntity;
private Angle? _rotation;
private Dictionary<NetEntity, List<DockingPortState>> _docks = new();
@@ -57,6 +62,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
_rotation = angle;
}
public void SetConsole(EntityUid? consoleEntity)
{
_consoleEntity = consoleEntity;
}
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.KeyBindUp(args);
@@ -139,40 +149,35 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
}
var mapPos = _transform.ToMapCoordinates(_coordinates.Value);
var offset = _coordinates.Value.Position;
var posMatrix = Matrix3Helpers.CreateTransform(offset, _rotation.Value);
var posMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, _rotation.Value);
var ourEntRot = RotateWithEntity ? _transform.GetWorldRotation(xform) : _rotation.Value;
var ourEntMatrix = Matrix3Helpers.CreateTransform(_transform.GetWorldPosition(xform), ourEntRot);
var ourWorldMatrix = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
Matrix3x2.Invert(ourWorldMatrix, out var ourWorldMatrixInvert);
var shuttleToWorld = Matrix3x2.Multiply(posMatrix, ourEntMatrix);
Matrix3x2.Invert(shuttleToWorld, out var worldToShuttle);
var shuttleToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector);
// Draw our grid in detail
var ourGridId = xform.GridUid;
if (EntManager.TryGetComponent<MapGridComponent>(ourGridId, out var ourGrid) &&
fixturesQuery.HasComponent(ourGridId.Value))
{
var ourGridMatrix = _transform.GetWorldMatrix(ourGridId.Value);
var matrix = Matrix3x2.Multiply(ourGridMatrix, ourWorldMatrixInvert);
var ourGridToWorld = _transform.GetWorldMatrix(ourGridId.Value);
var ourGridToShuttle = Matrix3x2.Multiply(ourGridToWorld, worldToShuttle);
var ourGridToView = ourGridToShuttle * shuttleToView;
var color = _shuttles.GetIFFColor(ourGridId.Value, self: true);
DrawGrid(handle, matrix, (ourGridId.Value, ourGrid), color);
DrawDocks(handle, ourGridId.Value, matrix);
DrawGrid(handle, ourGridToView, (ourGridId.Value, ourGrid), color);
DrawDocks(handle, ourGridId.Value, ourGridToView);
}
var invertedPosition = _coordinates.Value.Position - offset;
invertedPosition.Y = -invertedPosition.Y;
// Don't need to transform the InvWorldMatrix again as it's already offset to its position.
// Draw radar position on the station
var radarPos = invertedPosition;
const float radarVertRadius = 2f;
var radarPosVerts = new Vector2[]
{
ScalePosition(radarPos + new Vector2(0f, -radarVertRadius)),
ScalePosition(radarPos + new Vector2(radarVertRadius / 2f, 0f)),
ScalePosition(radarPos + new Vector2(0f, radarVertRadius)),
ScalePosition(radarPos + new Vector2(radarVertRadius / -2f, 0f)),
ScalePosition(new Vector2(0f, -radarVertRadius)),
ScalePosition(new Vector2(radarVertRadius / 2f, 0f)),
ScalePosition(new Vector2(0f, radarVertRadius)),
ScalePosition(new Vector2(radarVertRadius / -2f, 0f)),
};
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, radarPosVerts, Color.Lime);
@@ -197,8 +202,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
if (!_shuttles.CanDraw(gUid, gridBody, iff))
continue;
var gridMatrix = _transform.GetWorldMatrix(gUid);
var matty = Matrix3x2.Multiply(gridMatrix, ourWorldMatrixInvert);
var curGridToWorld = _transform.GetWorldMatrix(gUid);
var curGridToView = curGridToWorld * worldToShuttle * shuttleToView;
var labelColor = _shuttles.GetIFFColor(grid, self: false, iff);
var coordColor = new Color(labelColor.R * 0.8f, labelColor.G * 0.8f, labelColor.B * 0.8f, 0.5f);
@@ -213,8 +218,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
{
var gridBounds = grid.Comp.LocalAABB;
var gridCentre = Vector2.Transform(gridBody.LocalCenter, matty);
gridCentre.Y = -gridCentre.Y;
var gridCentre = Vector2.Transform(gridBody.LocalCenter, curGridToView);
var distance = gridCentre.Length();
var labelText = Loc.GetString("shuttle-console-iff-label", ("name", labelName),
@@ -230,9 +234,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
// y-offset the control to always render below the grid (vertically)
var yOffset = Math.Max(gridBounds.Height, gridBounds.Width) * MinimapScale / 1.8f;
// The actual position in the UI. We centre the label by offsetting the matrix position
// by half the label's width, plus the y-offset
var gridScaledPosition = ScalePosition(gridCentre) - new Vector2(0, -yOffset);
// The actual position in the UI.
var gridScaledPosition = gridCentre - new Vector2(0, -yOffset);
// Normalize the grid position if it exceeds the viewport bounds
// normalizing it instead of clamping it preserves the direction of the vector and prevents corner-hugging
@@ -264,18 +267,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
}
// Detailed view
var gridAABB = gridMatrix.TransformBox(grid.Comp.LocalAABB);
var gridAABB = curGridToWorld.TransformBox(grid.Comp.LocalAABB);
// Skip drawing if it's out of range.
if (!gridAABB.Intersects(viewAABB))
continue;
DrawGrid(handle, matty, grid, labelColor);
DrawDocks(handle, gUid, matty);
DrawGrid(handle, curGridToView, grid, labelColor);
DrawDocks(handle, gUid, curGridToView);
}
// If we've set the controlling console, and it's on a different grid
// to the shuttle itself, then draw an additional marker to help the
// player determine where they are relative to the shuttle.
if (_consoleEntity != null && xformQuery.TryGetComponent(_consoleEntity, out var consoleXform))
{
if (consoleXform.ParentUid != _coordinates.Value.EntityId)
{
var consolePositionWorld = _transform.GetWorldPosition((EntityUid)_consoleEntity);
var p = Vector2.Transform(consolePositionWorld, worldToShuttle * shuttleToView);
handle.DrawCircle(p, 5, Color.ToSrgb(Color.Cyan), true);
}
}
}
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 matrix)
private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 gridToView)
{
if (!ShowDocks)
return;
@@ -283,33 +300,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl
const float DockScale = 0.6f;
var nent = EntManager.GetNetEntity(uid);
const float sqrt2 = 1.41421356f;
const float dockRadius = DockScale * sqrt2;
// Worst-case bounds used to cull a dock:
Box2 viewBounds = new Box2(-dockRadius, -dockRadius, Size.X + dockRadius, Size.Y + dockRadius);
if (_docks.TryGetValue(nent, out var docks))
{
foreach (var state in docks)
{
var position = state.Coordinates.Position;
var uiPosition = Vector2.Transform(position, matrix);
if (uiPosition.Length() > (WorldRange * 2f) - DockScale)
var positionInView = Vector2.Transform(position, gridToView);
if (!viewBounds.Contains(positionInView))
{
continue;
}
var color = Color.ToSrgb(Color.Magenta);
var verts = new[]
{
Vector2.Transform(position + new Vector2(-DockScale, -DockScale), matrix),
Vector2.Transform(position + new Vector2(DockScale, -DockScale), matrix),
Vector2.Transform(position + new Vector2(DockScale, DockScale), matrix),
Vector2.Transform(position + new Vector2(-DockScale, DockScale), matrix),
Vector2.Transform(position + new Vector2(-DockScale, -DockScale), gridToView),
Vector2.Transform(position + new Vector2(DockScale, -DockScale), gridToView),
Vector2.Transform(position + new Vector2(DockScale, DockScale), gridToView),
Vector2.Transform(position + new Vector2(-DockScale, DockScale), gridToView),
};
for (var i = 0; i < verts.Length; i++)
{
var vert = verts[i];
vert.Y = -vert.Y;
verts[i] = ScalePosition(vert);
}
handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts, color.WithAlpha(0.8f));
handle.DrawPrimitives(DrawPrimitiveTopology.LineStrip, verts, color);
}

View File

@@ -9,6 +9,7 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.Silicons.Laws.Ui;
@@ -18,8 +19,13 @@ public sealed partial class LawDisplay : Control
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly EntityManager _entityManager = default!;
private static readonly TimeSpan PressCooldown = TimeSpan.FromSeconds(3);
private readonly Dictionary<Button, TimeSpan> _nextAllowedPress = new();
public LawDisplay(EntityUid uid, SiliconLaw law, HashSet<string>? radioChannels)
{
RobustXamlLoader.Load(this);
@@ -47,9 +53,12 @@ public sealed partial class LawDisplay : Control
MinWidth = 75,
};
_nextAllowedPress[localButton] = TimeSpan.Zero;
localButton.OnPressed += _ =>
{
_chatManager.SendMessage($"{lawIdentifierPlaintext}: {lawDescriptionPlaintext}", ChatSelectChannel.Local);
_nextAllowedPress[localButton] = _timing.CurTime + PressCooldown;
};
LawAnnouncementButtons.AddChild(localButton);
@@ -71,6 +80,8 @@ public sealed partial class LawDisplay : Control
MinWidth = 75,
};
_nextAllowedPress[radioChannelButton] = TimeSpan.Zero;
radioChannelButton.OnPressed += _ =>
{
switch (radioChannel)
@@ -80,9 +91,21 @@ public sealed partial class LawDisplay : Control
default:
_chatManager.SendMessage($"{SharedChatSystem.RadioChannelPrefix}{radioChannelProto.KeyCode} {lawIdentifierPlaintext}: {lawDescriptionPlaintext}", ChatSelectChannel.Radio); break;
}
_nextAllowedPress[radioChannelButton] = _timing.CurTime + PressCooldown;
};
LawAnnouncementButtons.AddChild(radioChannelButton);
}
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
var curTime = _timing.CurTime;
foreach (var (button, nextPress) in _nextAllowedPress)
{
button.Disabled = curTime < nextPress;
}
}
}

View File

@@ -54,7 +54,7 @@ public sealed partial class StoreMenu : DefaultWindow
foreach (var ((_, amount), proto) in currency)
{
balanceStr += Loc.GetString("store-ui-balance-display", ("amount", amount),
("currency", Loc.GetString(proto.DisplayName, ("amount", 1))));
("currency", Loc.GetString(proto.DisplayName, ("amount", 1)))) + "\n";
}
BalanceInfo.SetMarkup(balanceStr.TrimEnd());
@@ -63,7 +63,10 @@ public sealed partial class StoreMenu : DefaultWindow
foreach (var type in currency)
{
if (type.Value.CanWithdraw && type.Value.Cash != null && type.Key.Item2 > 0)
{
disabled = false;
break;
}
}
WithdrawButton.Disabled = disabled;

View File

@@ -18,7 +18,7 @@ public sealed partial class StoreWithdrawWindow : DefaultWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private Dictionary<FixedPoint2, CurrencyPrototype> _validCurrencies = new();
private Dictionary<CurrencyPrototype, FixedPoint2> _validCurrencies = new();
private HashSet<CurrencyWithdrawButton> _buttons = new();
public event Action<BaseButton.ButtonEventArgs, string, int>? OnWithdrawAttempt;
@@ -36,7 +36,7 @@ public sealed partial class StoreWithdrawWindow : DefaultWindow
if (!_prototypeManager.TryIndex(currency.Key, out var proto))
continue;
_validCurrencies.Add(currency.Value, proto);
_validCurrencies.Add(proto, currency.Value);
}
//this shouldn't ever happen but w/e
@@ -47,14 +47,17 @@ public sealed partial class StoreWithdrawWindow : DefaultWindow
_buttons.Clear();
foreach (var currency in _validCurrencies)
{
if (!currency.Key.CanWithdraw)
continue;
var button = new CurrencyWithdrawButton()
{
Id = currency.Value.ID,
Amount = currency.Key,
Id = currency.Key.ID,
Amount = currency.Value,
MinHeight = 20,
Text = Loc.GetString("store-withdraw-button-ui", ("currency",Loc.GetString(currency.Value.DisplayName, ("amount", currency.Key)))),
Text = Loc.GetString("store-withdraw-button-ui", ("currency",Loc.GetString(currency.Key.DisplayName, ("amount", currency.Value)))),
Disabled = false,
};
button.Disabled = false;
button.OnPressed += args =>
{
OnWithdrawAttempt?.Invoke(args, button.Id, WithdrawSlider.Value);
@@ -65,7 +68,7 @@ public sealed partial class StoreWithdrawWindow : DefaultWindow
ButtonContainer.AddChild(button);
}
var maxWithdrawAmount = _validCurrencies.Keys.Max().Int();
var maxWithdrawAmount = _validCurrencies.Values.Max().Int();
// setup withdraw slider
WithdrawSlider.MinValue = 1;

View File

@@ -110,6 +110,7 @@ namespace Content.Client.Stylesheets
public static readonly Color ButtonColorGoodDefault = Color.FromHex("#3E6C45");
public static readonly Color ButtonColorGoodHovered = Color.FromHex("#31843E");
public static readonly Color ButtonColorGoodDisabled = Color.FromHex("#164420");
//NavMap
public static readonly Color PointRed = Color.FromHex("#B02E26");
@@ -1499,6 +1500,20 @@ namespace Content.Client.Stylesheets
Element<Button>().Class("ButtonColorGreen").Pseudo(ContainerButton.StylePseudoClassHover)
.Prop(Control.StylePropertyModulateSelf, ButtonColorGoodHovered),
// Accept button (merge with green button?) ---
Element<Button>().Class("ButtonAccept")
.Prop(Control.StylePropertyModulateSelf, ButtonColorGoodDefault),
Element<Button>().Class("ButtonAccept").Pseudo(ContainerButton.StylePseudoClassNormal)
.Prop(Control.StylePropertyModulateSelf, ButtonColorGoodDefault),
Element<Button>().Class("ButtonAccept").Pseudo(ContainerButton.StylePseudoClassHover)
.Prop(Control.StylePropertyModulateSelf, ButtonColorGoodHovered),
Element<Button>().Class("ButtonAccept").Pseudo(ContainerButton.StylePseudoClassDisabled)
.Prop(Control.StylePropertyModulateSelf, ButtonColorGoodDisabled),
// ---
// Small Button ---

View File

@@ -0,0 +1,8 @@
using Content.Shared.Telephone;
namespace Content.Client.Telephone;
public sealed class TelephoneSystem : SharedTelephoneSystem
{
}

View File

@@ -104,7 +104,7 @@ public sealed class TippyUIController : UIController
? -WaddleRotation
: WaddleRotation;
if (EntityManager.TryGetComponent(_entity, out FootstepModifierComponent? step))
if (EntityManager.TryGetComponent(_entity, out FootstepModifierComponent? step) && step.FootstepSoundCollection != null)
{
var audioParams = step.FootstepSoundCollection.Params
.AddVolume(-7f)

View File

@@ -0,0 +1,34 @@
using System.Linq;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.RichText;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client.UserInterface.RichText;
/// <summary>
/// Sets the font to a monospaced variant
/// </summary>
public sealed class MonoTag : IMarkupTag
{
[ValidatePrototypeId<FontPrototype>] public const string MonoFont = "Monospace";
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string Name => "mono";
/// <inheritdoc/>
public void PushDrawContext(MarkupNode node, MarkupDrawingContext context)
{
var font = FontTag.CreateFont(context.Font, node, _resourceCache, _prototypeManager, MonoFont);
context.Font.Push(font);
}
/// <inheritdoc/>
public void PopDrawContext(MarkupNode node, MarkupDrawingContext context)
{
context.Font.Pop();
}
}

View File

@@ -572,6 +572,10 @@ public sealed class UserAHelpUIHandler : IAHelpUIHandler
_window.OnClose += () => { OnClose?.Invoke(); };
_window.OnOpen += () => { OnOpen?.Invoke(); };
_window.Contents.AddChild(_chatPanel);
var introText = Loc.GetString("bwoink-system-introductory-message");
var introMessage = new SharedBwoinkSystem.BwoinkTextMessage( _ownerId, SharedBwoinkSystem.SystemUserId, introText);
Receive(introMessage);
}
public void Dispose()

View File

@@ -16,9 +16,8 @@ using static Robust.Client.UserInterface.Controls.LineEdit;
namespace Content.Client.UserInterface.Systems.Chat.Widgets;
[GenerateTypedNameReferences]
#pragma warning disable RA0003
[Virtual]
public partial class ChatBox : UIWidget
#pragma warning restore RA0003
{
private readonly ChatUIController _controller;
private readonly IEntityManager _entManager;

View File

@@ -71,6 +71,7 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
buttonHeading.AddStyleClass(ContainerButton.StyleClassButton);
buttonHeading.Label.HorizontalAlignment = HAlignment.Center;
buttonHeading.Label.HorizontalExpand = true;
buttonHeading.Margin = new Thickness(8, 0, 8, 2);
var body = new CollapsibleBody
{

View File

@@ -83,22 +83,27 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
if (args.Function == EngineKeyFunctions.UIClick)
{
_handsSystem.UIHandClick(_playerHandsComponent, hand.SlotName);
args.Handle();
}
else if (args.Function == EngineKeyFunctions.UseSecondary)
{
_handsSystem.UIHandOpenContextMenu(hand.SlotName);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ActivateItemInWorld)
{
_handsSystem.UIHandActivate(hand.SlotName);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.AltActivateItemInWorld)
{
_handsSystem.UIHandAltActivateItem(hand.SlotName);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ExamineEntity)
{
_handsSystem.UIInventoryExamine(hand.SlotName);
args.Handle();
}
}

View File

@@ -1,4 +1,5 @@
using Content.Client.Administration.Managers;
using System.Numerics;
using Content.Client.Administration.Managers;
using Content.Client.Gameplay;
using Content.Client.Markers;
using Content.Client.Sandbox;
@@ -7,9 +8,7 @@ using Content.Client.UserInterface.Controls;
using Content.Client.UserInterface.Systems.DecalPlacer;
using Content.Client.UserInterface.Systems.Sandbox.Windows;
using Content.Shared.Input;
using Content.Shared.Silicons.StationAi;
using JetBrains.Annotations;
using Robust.Client.Console;
using Robust.Client.Debugging;
using Robust.Client.Graphics;
using Robust.Client.Input;
@@ -109,9 +108,13 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
private void EnsureWindow()
{
if(_window is { Disposed: false })
if (_window is { Disposed: false })
return;
_window = UIManager.CreateWindow<SandboxWindow>();
// Pre-center the window without forcing it to the center every time.
_window.OpenCentered();
_window.Close();
_window.OnOpen += () => { SandboxButton!.Pressed = true; };
_window.OnClose += () => { SandboxButton!.Pressed = false; };
_window.ToggleLightButton.Pressed = !_light.Enabled;
@@ -149,7 +152,6 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
_window.ToggleSubfloorButton.OnPressed += _ => _sandbox.ToggleSubFloor();
_window.ShowMarkersButton.OnPressed += _ => _sandbox.ShowMarkers();
_window.ShowBbButton.OnPressed += _ => _sandbox.ShowBb();
_window.MachineLinkingButton.OnPressed += _ => _sandbox.MachineLinking();
}
private void CheckSandboxVisibility()
@@ -164,7 +166,7 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
{
if (_window != null)
{
_window.Dispose();
_window.Close();
_window = null;
}
@@ -209,7 +211,7 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
if (_sandbox.SandboxAllowed && _window.IsOpen != true)
{
UIManager.ClickSound();
_window.OpenCentered();
_window.Open();
}
else
{

View File

@@ -4,20 +4,24 @@
Title="{Loc sandbox-window-title}"
Resizable="False">
<BoxContainer Orientation="Vertical" SeparationOverride="4">
<Button Name="AiOverlayButton" Access="Public" Text="{Loc sandbox-window-ai-overlay-button}" ToggleMode="True"/>
<Button Name="RespawnButton" Access="Public" Text="{Loc sandbox-window-respawn-button}"/>
<Button Name="SpawnEntitiesButton" Access="Public" Text="{Loc sandbox-window-spawn-entities-button}"/>
<Label Text="{Loc sandbox-window-map-editing-label}"/>
<Button Name="SpawnTilesButton" Access="Public" Text="{Loc sandbox-window-spawn-tiles-button}"/>
<Button Name="SpawnEntitiesButton" Access="Public" Text="{Loc sandbox-window-spawn-entities-button}"/>
<Button Name="SpawnDecalsButton" Access="Public" Text="{Loc sandbox-window-spawn-decals-button}"/>
<Button Name="GiveFullAccessButton" Access="Public" Text="{Loc sandbox-window-grant-full-access-button}"/>
<Button Name="GiveAghostButton" Access="Public" Text="{Loc sandbox-window-ghost-button}"/>
<Label Text="{Loc sandbox-window-visibility-label}"/>
<Button Name="ToggleLightButton" Access="Public" Text="{Loc sandbox-window-toggle-lights-button}" ToggleMode="True"/>
<Button Name="ToggleFovButton" Access="Public" Text="{Loc sandbox-window-toggle-fov-button}" ToggleMode="True"/>
<Button Name="ToggleShadowsButton" Access="Public" Text="{Loc sandbox-window-toggle-shadows-button}" ToggleMode="True"/>
<Button Name="ToggleSubfloorButton" Access="Public" Text="{Loc sandbox-window-toggle-subfloor-button}" ToggleMode="True"/>
<Button Name="SuicideButton" Access="Public" Text="{Loc sandbox-window-toggle-suicide-button}" ToggleMode="True"/>
<Button Name="AiOverlayButton" Access="Public" Text="{Loc sandbox-window-ai-overlay-button}" ToggleMode="True"/>
<Button Name="ShowMarkersButton" Access="Public" Text="{Loc sandbox-window-show-spawns-button}" ToggleMode="True"/>
<Button Name="ShowBbButton" Access="Public" Text="{Loc sandbox-window-show-bb-button}" ToggleMode="True"/>
<Button Name="MachineLinkingButton" Access="Public" Text="{Loc sandbox-window-link-machines-button}" ToggleMode="True"/>
<Label Text="{Loc sandbox-window-your-character-label}"/>
<Button Name="GiveAghostButton" Access="Public" Text="{Loc sandbox-window-ghost-button}"/>
<Button Name="GiveFullAccessButton" Access="Public" Text="{Loc sandbox-window-grant-full-access-button}"/>
<Button Name="SuicideButton" Access="Public" Text="{Loc sandbox-window-toggle-suicide-button}"/>
<Button Name="RespawnButton" Access="Public" Text="{Loc sandbox-window-respawn-button}"/>
</BoxContainer>
</windows:SandboxWindow>

View File

@@ -77,6 +77,7 @@ public sealed partial class GunSystem : SharedGunSystem
base.Initialize();
UpdatesOutsidePrediction = true;
SubscribeLocalEvent<AmmoCounterComponent, ItemStatusCollectMessage>(OnAmmoCounterCollect);
SubscribeLocalEvent<AmmoCounterComponent, UpdateClientAmmoEvent>(OnUpdateClientAmmo);
SubscribeAllEvent<MuzzleFlashEvent>(OnMuzzleFlash);
// Plays animated effects on the client.
@@ -86,6 +87,11 @@ public sealed partial class GunSystem : SharedGunSystem
InitializeSpentAmmo();
}
private void OnUpdateClientAmmo(EntityUid uid, AmmoCounterComponent ammoComp, ref UpdateClientAmmoEvent args)
{
UpdateAmmoCount(uid, ammoComp);
}
private void OnMuzzleFlash(MuzzleFlashEvent args)
{
var gunUid = GetEntity(args.Uid);

View File

@@ -206,8 +206,7 @@ namespace Content.Client.Wires.UI
(_statusContainer = new GridContainer
{
Margin = new Thickness(8, 4),
// TODO: automatically change columns count.
Columns = 3
Rows = 2
})
}
}
@@ -227,7 +226,8 @@ namespace Content.Client.Wires.UI
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#525252ff")}
});
CloseButton.OnPressed += _ => Close();
SetSize = new Vector2(320, 200);
SetHeight = 200;
MinWidth = 320;
}
@@ -503,6 +503,8 @@ namespace Content.Client.Wires.UI
public StatusLight(StatusLightData data, IResourceCache resourceCache)
{
HorizontalAlignment = HAlignment.Right;
var hsv = Color.ToHsv(data.Color);
hsv.Z /= 2;
var dimColor = Color.FromHsv(hsv);

View File

@@ -0,0 +1,7 @@
using Content.Shared._CP14.Knowledge;
namespace Content.Client._CP14.Knowledge;
public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSystem
{
}

View File

@@ -80,6 +80,9 @@ public sealed class CP14ClientModularCraftSystem : CP14SharedModularCraftSystem
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(defaultLayer);
sprite.LayerMapSet(keyCode, index);
if (indexedPart.Color is not null)
sprite.LayerSetColor(keyCode, indexedPart.Color.Value);
}
else
{
@@ -148,6 +151,7 @@ public sealed class CP14ClientModularCraftSystem : CP14SharedModularCraftSystem
{
RsiPath = indexedPart.RsiPath,
State = state,
Color = indexedPart.Color,
};
var key = $"{defaultKey}-{counterPart}-default";
@@ -203,6 +207,7 @@ public sealed class CP14ClientModularCraftSystem : CP14SharedModularCraftSystem
{
RsiPath = indexedPart.RsiPath,
State = state,
Color = indexedPart.Color,
};
var key = $"{defaultKey}-{counterPart}-default";

View File

@@ -16,11 +16,12 @@
<Label Text="{Loc 'cp14-ui-options-main-graphics-label'}"
StyleClasses="LabelKeyText"/>
<!-- CP14 Wave shader settings -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'cp14-ui-options-main-graphics-wave-shader'}" Margin="0 0 4 0"/>
<CheckBox Name="WaveShaderEnabled"/>
</BoxContainer>
<CheckBox Name="WaveShaderEnabled"
Text="{Loc 'cp14-ui-options-main-graphics-wave-shader'}"/>
<!-- TODO: Wave shader tooltip -->
<CheckBox Name="PostProcessCheckBox"
Text="{Loc 'cp14-ui-options-postprocess'}"
ToolTip="{Loc 'cp14-ui-options-postprocess-tooltip'}"/>
</BoxContainer>
</ScrollContainer>

View File

@@ -13,6 +13,7 @@ public sealed partial class CP14OptionsMenuMainTab : Control
RobustXamlLoader.Load(this);
Control.AddOptionCheckBox(CP14ConfigVars.WaveShaderEnabled, WaveShaderEnabled);
Control.AddOptionCheckBox(CP14ConfigVars.PostProcess, PostProcessCheckBox);
Control.Initialize();
}

View File

@@ -0,0 +1,77 @@
using Content.Shared._CP14.Configuration;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Graphics;
using Robust.Shared.Physics;
using Robust.Shared.Prototypes;
namespace Content.Client.Overlays;
// This overlay serves as the foundational post processing overlay.
// Ideally, for performance reasons, post processing designed to be present at all times, such as additive light blending or tonemapping, should be done as part of a single shader pass.
public sealed class CP14BasePostProcessOverlay : Overlay
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly ILightManager _lightManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override bool RequestScreenTexture => true;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _basePostProcessShader;
public CP14BasePostProcessOverlay()
{
IoCManager.InjectDependencies(this);
_basePostProcessShader = _prototypeManager.Index<ShaderPrototype>("BasePostProcess").InstanceUnique();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
if (!_configManager.GetCVar(CP14ConfigVars.PostProcess))
return false;
if (!_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, out EyeComponent? eyeComp))
return false;
if (args.Viewport.Eye != eyeComp.Eye)
return false;
if (!_lightManager.Enabled || !eyeComp.Eye.DrawLight || !eyeComp.Eye.DrawFov)
return false;
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
if (playerEntity == null)
return false;
return true;
}
protected override void Draw(in OverlayDrawArgs args)
{
if (ScreenTexture == null)
return;
if (args.Viewport.Eye == null)
return;
var playerEntity = _playerManager.LocalSession?.AttachedEntity;
var worldHandle = args.WorldHandle;
var viewport = args.WorldBounds;
_basePostProcessShader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
_basePostProcessShader.SetParameter("LIGHT_TEXTURE", args.Viewport.LightRenderTarget.Texture);
_basePostProcessShader.SetParameter("Zoom", args.Viewport.Eye.Zoom.X);
worldHandle.UseShader(_basePostProcessShader);
worldHandle.DrawRect(viewport, Color.White);
worldHandle.UseShader(null);
}
}

View File

@@ -0,0 +1,127 @@
using Content.Shared._CP14.Roof;
using Content.Shared.Ghost;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Console;
using Robust.Shared.Map.Components;
namespace Content.Client._CP14.Roof;
public sealed class CP14RoofSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
private bool _roofVisible = true;
public bool DisabledByCommand = false;
private EntityQuery<GhostComponent> _ghostQuery;
private EntityQuery<TransformComponent> _xformQuery;
public bool RoofVisibility
{
get => _roofVisible && !DisabledByCommand;
set
{
_roofVisible = value;
UpdateRoofVisibilityAll();
}
}
public override void Initialize()
{
base.Initialize();
_ghostQuery = GetEntityQuery<GhostComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<CP14RoofComponent, ComponentStartup>(RoofStartup);
SubscribeLocalEvent<GhostComponent, CP14ToggleRoofVisibilityAction>(OnToggleRoof);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var player = _playerManager.LocalEntity;
if (_ghostQuery.HasComp(player))
return;
if (_xformQuery.TryComp(player, out var playerXform))
{
var grid = playerXform.GridUid;
if (grid == null || !TryComp<MapGridComponent>(grid, out var gridComp))
return;
var roofQuery = GetEntityQuery<CP14RoofComponent>();
var anchored = _map.GetAnchoredEntities(grid.Value, gridComp, playerXform.Coordinates);
var underRoof = false;
foreach (var ent in anchored)
{
if (!roofQuery.HasComp(ent))
continue;
underRoof = true;
}
if (underRoof && _roofVisible)
{
RoofVisibility = false;
}
if (!underRoof && !_roofVisible)
{
RoofVisibility = true;
}
}
}
private void OnToggleRoof(Entity<GhostComponent> ent, ref CP14ToggleRoofVisibilityAction args)
{
if (args.Handled)
return;
DisabledByCommand = !DisabledByCommand;
UpdateRoofVisibilityAll();
args.Handled = true;
}
private void RoofStartup(Entity<CP14RoofComponent> ent, ref ComponentStartup args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
UpdateVisibility(ent, sprite);
}
private void UpdateVisibility(Entity<CP14RoofComponent> ent, SpriteComponent sprite)
{
sprite.Visible = RoofVisibility;
}
public void UpdateRoofVisibilityAll()
{
var query = EntityQueryEnumerator<CP14RoofComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out var marker, out var sprite))
{
UpdateVisibility((uid, marker), sprite);
}
}
}
internal sealed class ShowRoof : LocalizedCommands
{
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
public override string Command => "cp14_toggleroof";
public override string Help => "Toggle roof visibility";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var roofSystem = _entitySystemManager.GetEntitySystem<CP14RoofSystem>();
roofSystem.DisabledByCommand = !roofSystem.DisabledByCommand;
roofSystem.UpdateRoofVisibilityAll();
}
}

View File

@@ -12,6 +12,9 @@ public sealed class CP14WorkbenchBoundUserInterface : BoundUserInterface
{
private CP14WorkbenchWindow? _window;
[ViewVariables]
private string _search = string.Empty;
public CP14WorkbenchBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
@@ -23,6 +26,12 @@ public sealed class CP14WorkbenchBoundUserInterface : BoundUserInterface
_window = this.CreateWindow<CP14WorkbenchWindow>();
_window.OnCraft += entry => SendMessage(new CP14WorkbenchUiCraftMessage(entry.ProtoId));
_window.OnTextUpdated += search =>
{
_search = search.Trim().ToLowerInvariant();
_window.UpdateFilter(_search);
};
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -32,7 +41,7 @@ public sealed class CP14WorkbenchBoundUserInterface : BoundUserInterface
switch (state)
{
case CP14WorkbenchUiRecipesState recipesState:
_window?.UpdateRecipes(recipesState);
_window?.UpdateRecipes(recipesState, _search);
break;
}
}

View File

@@ -1,10 +1,20 @@
<Control xmlns="https://spacestation14.io">
<GridContainer Columns="2">
<TextureRect Name="View"
Margin="0,0,4,0"
MinSize="48 48"
HorizontalAlignment="Left"
Stretch="KeepAspectCentered"/>
<Label Name="Name"/>
<EntityPrototypeView
Name="EntityView"
Margin="0,0,4,0"
MinSize="48 48"
MaxSize="48 48"
Scale="2,2"
HorizontalAlignment="Left"
VerticalExpand="True" />
<TextureRect
Name="View"
Margin="0,0,4,0"
MinSize="48 48"
MaxSize="48 48"
HorizontalAlignment="Left"
Stretch="KeepAspectCentered" />
<Label Name="Name" />
</GridContainer>
</Control>

View File

@@ -31,7 +31,9 @@ public sealed partial class CP14WorkbenchRecipeControl : Control
{
var entityName = prototype.Name;
Name.Text = count <= 1 ? entityName : $"{entityName} x{count}";
View.Texture = _sprite.GetPrototypeIcon(prototype).Default;
View.Visible = false;
EntityView.SetPrototype(prototype);
}
public CP14WorkbenchRecipeControl(StackPrototype prototype, int count) : this()
@@ -43,6 +45,7 @@ public sealed partial class CP14WorkbenchRecipeControl : Control
if (icon is null)
return;
EntityView.Visible = false;
View.Texture = _sprite.Frame0(icon);
}
}

View File

@@ -1,11 +1,13 @@
<Control xmlns="https://spacestation14.io">
<Button Name="Button">
<GridContainer Columns="2">
<TextureRect Name="View"
Margin="0,0,4,0"
MinSize="48 48"
HorizontalAlignment="Left"
Stretch="KeepAspectCentered"/>
<EntityPrototypeView Name="View"
Margin="0,0,4,0"
MinSize="48 48"
MaxSize="48 48"
Scale="2,2"
HorizontalAlignment="Center"
VerticalExpand="True"/>
<Label Name="Name"/>
</GridContainer>
</Button>

View File

@@ -59,6 +59,6 @@ public sealed partial class CP14WorkbenchRequirementControl : Control
private void UpdateView()
{
View.Texture = _sprite.GetPrototypeIcon(_recipePrototype.Result).Default;
View.SetPrototype(_recipePrototype.Result);
}
}

View File

@@ -2,59 +2,68 @@
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'cp14-workbench-ui-title'}"
MinSize="700 600">
<BoxContainer Orientation="Vertical">
SetSize="700 500"
MinSize="700 300">
<BoxContainer Orientation="Horizontal">
<!-- Main -->
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Horizontal">
<GridContainer HorizontalExpand="True" VerticalExpand="True" Columns="2">
<!-- Product list (left side UI) -->
<BoxContainer SizeFlagsStretchRatio="0.5" HorizontalExpand="True" Orientation="Vertical" Margin="0 0 10 0">
<!-- Search Bar -->
<LineEdit Name="SearchBar" Margin="4" PlaceHolder="Search" HorizontalExpand="True" />
<!-- Crafts container -->
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" MinSize="0 200">
<BoxContainer Name="CraftsContainer" Orientation="Vertical" HorizontalExpand="True"/>
<BoxContainer Name="CraftsContainer" Orientation="Vertical" HorizontalExpand="True" />
</ScrollContainer>
</BoxContainer>
<!-- Craft view -->
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<PanelContainer HorizontalExpand="True" VerticalExpand="True">
<!-- Background -->
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#41332f"/>
</PanelContainer.PanelOverride>
<!-- Craft view (right side UI) -->
<BoxContainer SizeFlagsStretchRatio="0.5" Orientation="Vertical" HorizontalExpand="True"
VerticalExpand="True">
<PanelContainer HorizontalExpand="True" VerticalExpand="True">
<!-- Background -->
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#41332f" />
</PanelContainer.PanelOverride>
<!-- Content -->
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<!-- Item info -->
<GridContainer HorizontalExpand="True" Columns="2">
<!-- Left panel - icon -->
<TextureRect Name="ItemView"
<!-- Content -->
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<!-- Item info -->
<!-- icon -->
<EntityPrototypeView Name="ItemView"
Scale="2,2"
Margin="0,0,4,0"
MinSize="64 64"
HorizontalAlignment="Left"
Stretch="KeepAspectCentered"/>
MaxSize="64 64"
HorizontalAlignment="Left" />
<!-- Right panel - name & description -->
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
<Label Name="ItemName" Text="Name"/>
<Label Name="ItemDescription" Text="Description" ClipText="True"/>
</BoxContainer>
</GridContainer>
<controls:HLine Color="#404040" Thickness="2" Margin="0 5"/>
<!-- Required title -->
<Label Text="{Loc 'cp14-workbench-recipe-list'}"/>
<!-- Craft requirements content -->
<!-- Added by code -->
<BoxContainer Name="ItemRequirements" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True"/>
<controls:HLine Color="#404040" Thickness="2" Margin="0 5"/>
<!-- Craft button -->
<Button Name="CraftButton" Text="{Loc 'cp14-workbench-craft'}"/>
<!-- name & description -->
<BoxContainer Margin="5 0 0 0" HorizontalExpand="True" VerticalExpand="True"
Orientation="Vertical">
<RichTextLabel Name="ItemName" Margin="5" />
<RichTextLabel Name="ItemDescription" Margin="5" />
</BoxContainer>
</PanelContainer>
</BoxContainer>
</GridContainer>
<controls:HLine Color="#404040" Thickness="2" Margin="0 5" />
<!-- Required title -->
<Label Margin="5 0 0 0" Text="{Loc 'cp14-workbench-recipe-list'}" />
<!-- Craft requirements content -->
<!-- Added by code -->
<BoxContainer
Margin="5 0 0 0"
Name="ItemRequirements"
Orientation="Vertical" VerticalExpand="True"
HorizontalExpand="True" />
<controls:HLine Color="#404040" Thickness="5" Margin="0 5" />
<!-- Craft button -->
<Button Name="CraftButton" Text="{Loc 'cp14-workbench-craft'}" />
</BoxContainer>
</PanelContainer>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</DefaultWindow>

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